From e57a4033385c5976cbb17af1e962b1224a61183b Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Fri, 30 May 2008 06:10:19 +0000 Subject: [PATCH] Make it possible to use the generalised 'case' construct in the cmd_line property. llvm-svn: 51728 --- llvm/tools/llvmc2/Action.h | 3 +- llvm/tools/llvmc2/Common.td | 1 + llvm/tools/llvmc2/CompilationGraph.cpp | 4 +- llvm/tools/llvmc2/CompilationGraph.h | 16 +- llvm/tools/llvmc2/StringSet.h | 40 ++ llvm/tools/llvmc2/Tool.h | 13 +- llvm/tools/llvmc2/Tools.td | 15 +- .../TableGen/LLVMCConfigurationEmitter.cpp | 395 ++++++++++-------- 8 files changed, 286 insertions(+), 201 deletions(-) create mode 100644 llvm/tools/llvmc2/StringSet.h diff --git a/llvm/tools/llvmc2/Action.h b/llvm/tools/llvmc2/Action.h index 32d185545a6e..0f3f0bd26b6d 100644 --- a/llvm/tools/llvmc2/Action.h +++ b/llvm/tools/llvmc2/Action.h @@ -25,9 +25,10 @@ namespace llvmc { class Action { /// Command_ - The actual command (for example, 'ls'). std::string Command_; - /// Args_ - Command arguments. Stdout redirection is allowed. + /// Args_ - Command arguments. Stdout redirection ("> file") is allowed. std::vector Args_; public: + Action() {} Action (const std::string& C, const StringVector& A) : Command_(C), Args_(A) diff --git a/llvm/tools/llvmc2/Common.td b/llvm/tools/llvmc2/Common.td index 2a6b54eba8e0..364cac354940 100644 --- a/llvm/tools/llvmc2/Common.td +++ b/llvm/tools/llvmc2/Common.td @@ -56,6 +56,7 @@ def switch_on; def parameter_equals; def element_in_list; def input_languages_contain; +def default; // Boolean operators. def and; diff --git a/llvm/tools/llvmc2/CompilationGraph.cpp b/llvm/tools/llvmc2/CompilationGraph.cpp index e06a1688ed69..7ce431341b16 100644 --- a/llvm/tools/llvmc2/CompilationGraph.cpp +++ b/llvm/tools/llvmc2/CompilationGraph.cpp @@ -177,7 +177,7 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile, Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix()); } - if (int ret = CurTool->GenerateAction(In, Out).Execute()) + if (int ret = CurTool->GenerateAction(In, Out, InLangs).Execute()) throw error_code(ret); if (Last) @@ -343,7 +343,7 @@ int CompilationGraph::Build (const sys::Path& TempDir) { Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix()); } - if (int ret = JT->GenerateAction(Out).Execute()) + if (int ret = JT->GenerateAction(Out, InLangs).Execute()) throw error_code(ret); if (!IsLast) { diff --git a/llvm/tools/llvmc2/CompilationGraph.h b/llvm/tools/llvmc2/CompilationGraph.h index 91a9c77f9a51..6b2b290920b6 100644 --- a/llvm/tools/llvmc2/CompilationGraph.h +++ b/llvm/tools/llvmc2/CompilationGraph.h @@ -16,6 +16,7 @@ #include "AutoGenerated.h" #include "Tool.h" +#include "StringSet.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -29,21 +30,6 @@ namespace llvmc { - /// StringSet - A wrapper for StringMap that provides set-like - /// functionality. Only insert() and count() methods are used by my - /// code. - template - class StringSet : public llvm::StringMap { - typedef llvm::StringMap base; - public: - void insert (const std::string& InLang) { - assert(!InLang.empty()); - const char* KeyStart = &InLang[0]; - const char* KeyEnd = KeyStart + InLang.size(); - base::insert(llvm::StringMapEntry:: - Create(KeyStart, KeyEnd, base::getAllocator(), '+')); - } - }; typedef StringSet<> InputLanguagesSet; /// Edge - Represents an edge of the compilation graph. diff --git a/llvm/tools/llvmc2/StringSet.h b/llvm/tools/llvmc2/StringSet.h new file mode 100644 index 000000000000..d9556cc552d2 --- /dev/null +++ b/llvm/tools/llvmc2/StringSet.h @@ -0,0 +1,40 @@ +//===--- StringSet.h - The LLVM Compiler Driver -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// StringSet - A set-like wrapper for the StringMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMC2_STRINGSET_H +#define LLVM_TOOLS_LLVMC2_STRINGSET_H + +#include "llvm/ADT/StringMap.h" + +#include + +namespace llvmc { + + /// StringSet - A wrapper for StringMap that provides set-like + /// functionality. Only insert() and count() methods are used by my + /// code. + template + class StringSet : public llvm::StringMap { + typedef llvm::StringMap base; + public: + void insert (const std::string& InLang) { + assert(!InLang.empty()); + const char* KeyStart = &InLang[0]; + const char* KeyEnd = KeyStart + InLang.size(); + base::insert(llvm::StringMapEntry:: + Create(KeyStart, KeyEnd, base::getAllocator(), '+')); + } + }; +} + +#endif //LLVM_TOOLS_LLVMC2_STRINGSET_H diff --git a/llvm/tools/llvmc2/Tool.h b/llvm/tools/llvmc2/Tool.h index bfa7e46f9e85..3527817026d1 100644 --- a/llvm/tools/llvmc2/Tool.h +++ b/llvm/tools/llvmc2/Tool.h @@ -15,6 +15,7 @@ #define LLVM_TOOLS_LLVMC2_TOOL_H #include "Action.h" +#include "StringSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/System/Path.h" @@ -33,10 +34,12 @@ namespace llvmc { virtual ~Tool() {} virtual Action GenerateAction (const PathVector& inFiles, - const llvm::sys::Path& outFile) const = 0; + const llvm::sys::Path& outFile, + const StringSet<>& InLangs) const = 0; virtual Action GenerateAction (const llvm::sys::Path& inFile, - const llvm::sys::Path& outFile) const = 0; + const llvm::sys::Path& outFile, + const StringSet<>& InLangs) const = 0; virtual const char* Name() const = 0; virtual const char* InputLanguage() const = 0; @@ -54,8 +57,10 @@ namespace llvmc { void ClearJoinList() { JoinList_.clear(); } bool JoinListEmpty() const { return JoinList_.empty(); } - Action GenerateAction(const llvm::sys::Path& outFile) const - { return GenerateAction(JoinList_, outFile); } + Action GenerateAction(const llvm::sys::Path& outFile, + const StringSet<>& InLangs) const { + return GenerateAction(JoinList_, outFile, InLangs); + } // We shouldn't shadow base class's version of GenerateAction. using Tool::GenerateAction; diff --git a/llvm/tools/llvmc2/Tools.td b/llvm/tools/llvmc2/Tools.td index 5a614cf4ac0b..63b713fb0a2e 100644 --- a/llvm/tools/llvmc2/Tools.td +++ b/llvm/tools/llvmc2/Tools.td @@ -25,8 +25,15 @@ def llvm_gcc_c : Tool< [(in_language "c"), (out_language "llvm-bitcode"), (output_suffix "bc"), - (cmd_line "llvm-gcc -c -x c $INFILE -o $OUTFILE -emit-llvm"), + (cmd_line (case + (switch_on "E"), + "llvm-g++ -E -x c $INFILE -o $OUTFILE -emit-llvm", + (default), + "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm")), + // TOFIX: Preprocessed files currently have suffix ".bc". (switch_option "E", (stop_compilation), + // Make this possible: + // (output_suffix "i"), (help "Stop after the preprocessing stage, do not run the compiler")), (sink) ]>; @@ -35,7 +42,11 @@ def llvm_gcc_cpp : Tool< [(in_language "c++"), (out_language "llvm-bitcode"), (output_suffix "bc"), - (cmd_line "llvm-g++ -c -x c++ $INFILE -o $OUTFILE -emit-llvm"), + (cmd_line (case + (switch_on "E"), + "llvm-g++ -E -x c++ $INFILE -o $OUTFILE -emit-llvm", + (default), + "llvm-g++ -c -x c++ $INFILE -o $OUTFILE -emit-llvm")), (switch_option "E", (stop_compilation)), (sink) ]>; diff --git a/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp b/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp index 122424428e54..8f51c67da811 100644 --- a/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -53,18 +53,18 @@ const char * SinkOptionName = "AutoGeneratedSinkOption"; //===----------------------------------------------------------------------===// /// Helper functions -std::string InitPtrToString(Init* ptr) { - StringInit& val = dynamic_cast(*ptr); +const std::string& InitPtrToString(const Init* ptr) { + const StringInit& val = dynamic_cast(*ptr); return val.getValue(); } -int InitPtrToInt(Init* ptr) { - IntInit& val = dynamic_cast(*ptr); +int InitPtrToInt(const Init* ptr) { + const IntInit& val = dynamic_cast(*ptr); return val.getValue(); } -const DagInit& InitPtrToDagInitRef(Init* ptr) { - DagInit& val = dynamic_cast(*ptr); +const DagInit& InitPtrToDagInitRef(const Init* ptr) { + const DagInit& val = dynamic_cast(*ptr); return val; } @@ -307,7 +307,7 @@ namespace ToolFlags { struct ToolProperties : public RefCountedBase { std::string Name; - StrVector CmdLine; + Init* CmdLine; std::string InLanguage; std::string OutLanguage; std::string OutputSuffix; @@ -432,9 +432,7 @@ private: void onCmdLine (const DagInit* d) { checkNumberOfArguments(d, 1); - SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine); - if (toolProps_.CmdLine.empty()) - throw "Tool " + toolProps_.Name + " has empty command line!"; + toolProps_.CmdLine = d->getArg(0); } void onInLanguage (const DagInit* d) { @@ -610,6 +608,138 @@ void CollectToolProperties (RecordVector::const_iterator B, } } +/// EmitCaseTest1Arg - Helper function used by +/// EmitCaseConstructHandler. +bool EmitCaseTest1Arg(const std::string& TestName, + const DagInit& d, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + checkNumberOfArguments(&d, 1); + const std::string& OptName = InitPtrToString(d.getArg(0)); + if (TestName == "switch_on") { + const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName); + if (OptDesc.Type != OptionType::Switch) + throw OptName + ": incorrect option type!"; + O << OptDesc.GenVariableName(); + return true; + } else if (TestName == "input_languages_contain") { + O << "InLangs.count(\"" << OptName << "\") != 0"; + return true; + } + + return false; +} + +/// EmitCaseTest2Args - Helper function used by +/// EmitCaseConstructHandler. +bool EmitCaseTest2Args(const std::string& TestName, + const DagInit& d, + const char* IndentLevel, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + checkNumberOfArguments(&d, 2); + const std::string& OptName = InitPtrToString(d.getArg(0)); + const std::string& OptArg = InitPtrToString(d.getArg(1)); + const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName); + + if (TestName == "parameter_equals") { + if (OptDesc.Type != OptionType::Parameter + && OptDesc.Type != OptionType::Prefix) + throw OptName + ": incorrect option type!"; + O << OptDesc.GenVariableName() << " == \"" << OptArg << "\""; + return true; + } + else if (TestName == "element_in_list") { + if (OptDesc.Type != OptionType::ParameterList + && OptDesc.Type != OptionType::PrefixList) + throw OptName + ": incorrect option type!"; + const std::string& VarName = OptDesc.GenVariableName(); + O << "std::find(" << VarName << ".begin(),\n" + << IndentLevel << Indent1 << VarName << ".end(), \"" + << OptArg << "\") != " << VarName << ".end()"; + return true; + } + + return false; +} + +// Forward declaration. +// EmitLogicalOperationTest and EmitCaseTest are mutually recursive. +void EmitCaseTest(const DagInit& d, const char* IndentLevel, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O); + +/// EmitLogicalOperationTest - Helper function used by +/// EmitCaseConstructHandler. +void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp, + const char* IndentLevel, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + O << '('; + for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) { + const DagInit& InnerTest = InitPtrToDagInitRef(d.getArg(j)); + EmitCaseTest(InnerTest, IndentLevel, OptDescs, O); + if (j != NumArgs - 1) + O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " ("; + else + O << ')'; + } +} + +/// EmitCaseTest - Helper function used by EmitCaseConstructHandler. +void EmitCaseTest(const DagInit& d, const char* IndentLevel, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + const std::string& TestName = d.getOperator()->getAsString(); + + if (TestName == "and") + EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O); + else if (TestName == "or") + EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O); + else if (EmitCaseTest1Arg(TestName, d, OptDescs, O)) + return; + else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O)) + return; + else + throw TestName + ": unknown edge property!"; +} + +// Emit code that handles the 'case' construct. +// Takes a function object that should emit code for every case clause. +// Callback's type is +// void F(Init* Statement, const char* IndentLevel, std::ostream& O). +template +void EmitCaseConstructHandler(const DagInit* d, const char* IndentLevel, + const F& Callback, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + assert(d->getOperator()->getAsString() == "case"); + + for (unsigned i = 0, numArgs = d->getNumArgs(); i != numArgs; ++i) { + const DagInit& Test = InitPtrToDagInitRef(d->getArg(i)); + + if (Test.getOperator()->getAsString() == "default") { + if (i+2 != numArgs) + throw std::string("The 'default' clause should be the last in the" + "'case' construct!"); + O << IndentLevel << "else {\n"; + } + else { + O << IndentLevel << "if ("; + EmitCaseTest(Test, IndentLevel, OptDescs, O); + O << ") {\n"; + } + + ++i; + if (i == numArgs) + throw "Case construct handler: no corresponding action " + "found for the test " + Test.getAsString() + '!'; + + Callback(d->getArg(i), IndentLevel, O); + O << IndentLevel << "}\n"; + } +} + /// EmitForwardOptionPropertyHandlingCode - Helper function used to /// implement EmitOptionPropertyHandlingCode(). Emits code for /// handling the (forward) option property. @@ -698,7 +828,6 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P, << D.GenVariableName() << ", vec, \",\");\n"; } else { - // TOFIX: move this to the type-checking phase throw std::string("Switches can't have unpack_values property!"); } } @@ -707,34 +836,25 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P, O << Indent2 << "}\n"; } -// EmitGenerateActionMethod - Emit one of two versions of the -// Tool::GenerateAction() method. -void EmitGenerateActionMethod (const ToolProperties& P, bool V, std::ostream& O) -{ - if (V) - O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"; - else - O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n"; +void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName, + bool Version, const char* IndentLevel, + std::ostream& O) { + StrVector StrVec; + SplitString(InitPtrToString(CmdLine), StrVec); + if (InitPtrToString(CmdLine).empty()) + throw "Tool " + ToolName + " has empty command line!"; - O << Indent2 << "const sys::Path& outFile) const\n" - << Indent1 << "{\n" - << Indent2 << "std::vector vec;\n"; - - // Parse CmdLine tool property - if(P.CmdLine.empty()) - throw "Tool " + P.Name + " has empty command line!"; - - StrVector::const_iterator I = P.CmdLine.begin(); + StrVector::const_iterator I = StrVec.begin(); ++I; - for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) { + for (StrVector::const_iterator E = StrVec.end(); I != E; ++I) { const std::string& cmd = *I; - O << Indent2; + O << IndentLevel; if (cmd == "$INFILE") { - if (V) + if (Version) O << "for (PathVector::const_iterator B = inFiles.begin()" << ", E = inFiles.end();\n" - << Indent2 << "B != E; ++B)\n" - << Indent3 << "vec.push_back(B->toString());\n"; + << IndentLevel << "B != E; ++B)\n" + << IndentLevel << Indent1 << "vec.push_back(B->toString());\n"; else O << "vec.push_back(inFile.toString());\n"; } @@ -745,6 +865,46 @@ void EmitGenerateActionMethod (const ToolProperties& P, bool V, std::ostream& O) O << "vec.push_back(\"" << cmd << "\");\n"; } } + O << IndentLevel << "ret = Action(\"" << StrVec.at(0) << "\", vec);\n"; +} + +class EmitCmdLineVecFillCallback { + bool Version; + const std::string& ToolName; + public: + EmitCmdLineVecFillCallback(bool Ver, const std::string& TN) + : Version(Ver), ToolName(TN) {} + + void operator()(const Init* Statement, const char* IndentLevel, + std::ostream& O) const + { + EmitCmdLineVecFill(Statement, ToolName, Version, IndentLevel, O); + } +}; + +// EmitGenerateActionMethod - Emit one of two versions of the +// Tool::GenerateAction() method. +void EmitGenerateActionMethod (const ToolProperties& P, + const GlobalOptionDescriptions& OptDescs, + bool Version, std::ostream& O) { + if (Version) + O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"; + else + O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n"; + + O << Indent2 << "const sys::Path& outFile,\n" + << Indent2 << "const InputLanguagesSet& InLangs) const\n" + << Indent1 << "{\n" + << Indent2 << "Action ret;\n" + << Indent2 << "std::vector vec;\n"; + + // cmd_line is either a string or a 'case' construct. + if (typeid(*P.CmdLine) == typeid(StringInit)) + EmitCmdLineVecFill(P.CmdLine, P.Name, Version, Indent2, O); + else + EmitCaseConstructHandler(&InitPtrToDagInitRef(P.CmdLine), Indent2, + EmitCmdLineVecFillCallback(Version, P.Name), + OptDescs, O); // For every understood option, emit handling code. for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(), @@ -761,25 +921,27 @@ void EmitGenerateActionMethod (const ToolProperties& P, bool V, std::ostream& O) << Indent2 << "}\n"; } - O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n" + O << Indent2 << "return ret;\n" << Indent1 << "}\n\n"; } /// EmitGenerateActionMethods - Emit two GenerateAction() methods for /// a given Tool class. -void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) { - +void EmitGenerateActionMethods (const ToolProperties& P, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { if (!P.isJoin()) O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n" - << Indent2 << "const llvm::sys::Path& outFile) const\n" + << Indent2 << "const llvm::sys::Path& outFile,\n" + << Indent2 << "const InputLanguagesSet& InLangs) const\n" << Indent1 << "{\n" << Indent2 << "throw std::runtime_error(\"" << P.Name << " is not a Join tool!\");\n" << Indent1 << "}\n\n"; else - EmitGenerateActionMethod(P, true, O); + EmitGenerateActionMethod(P, OptDescs, true, O); - EmitGenerateActionMethod(P, false, O); + EmitGenerateActionMethod(P, OptDescs, false, O); } /// EmitIsLastMethod - Emit the IsLast() method for a given Tool @@ -841,9 +1003,10 @@ void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) { } /// EmitToolClassDefinition - Emit a Tool class definition. -void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) { - - if(P.Name == "root") +void EmitToolClassDefinition (const ToolProperties& P, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + if (P.Name == "root") return; // Header @@ -858,7 +1021,7 @@ void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) { EmitInOutLanguageMethods(P, O); EmitOutputSuffixMethod(P, O); EmitIsJoinMethod(P, O); - EmitGenerateActionMethods(P, O); + EmitGenerateActionMethods(P, OptDescs, O); EmitIsLastMethod(P, O); // Close class definition @@ -965,144 +1128,22 @@ void TypecheckGraph (Record* CompilationGraph, Record* B = Edge->getValueAsDef("b"); StringMap::iterator IA = ToolToOutLang.find(A->getName()); StringMap::iterator IB = ToolToInLang.find(B->getName()); - if(IA == IAE) + if (IA == IAE) throw A->getName() + ": no such tool!"; - if(IB == IBE) + if (IB == IBE) throw B->getName() + ": no such tool!"; - if(A->getName() != "root" && IA->second != IB->second) + if (A->getName() != "root" && IA->second != IB->second) throw "Edge " + A->getName() + "->" + B->getName() + ": output->input language mismatch"; - if(B->getName() == "root") + if (B->getName() == "root") throw std::string("Edges back to the root are not allowed!"); } } -/// EmitCaseTest1Arg - Helper function used by -/// EmitCaseConstructHandler. -bool EmitCaseTest1Arg(const std::string& TestName, - const DagInit& d, - const GlobalOptionDescriptions& OptDescs, - std::ostream& O) { - checkNumberOfArguments(&d, 1); - const std::string& OptName = InitPtrToString(d.getArg(0)); - if (TestName == "switch_on") { - const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName); - if (OptDesc.Type != OptionType::Switch) - throw OptName + ": incorrect option type!"; - O << OptDesc.GenVariableName(); - return true; - } else if (TestName == "input_languages_contain") { - O << "InLangs.count(\"" << OptName << "\") != 0"; - return true; - } - - return false; -} - -/// EmitCaseTest2Args - Helper function used by -/// EmitCaseConstructHandler. -bool EmitCaseTest2Args(const std::string& TestName, - const DagInit& d, - const char* IndentLevel, - const GlobalOptionDescriptions& OptDescs, - std::ostream& O) { - checkNumberOfArguments(&d, 2); - const std::string& OptName = InitPtrToString(d.getArg(0)); - const std::string& OptArg = InitPtrToString(d.getArg(1)); - const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName); - - if (TestName == "parameter_equals") { - if (OptDesc.Type != OptionType::Parameter - && OptDesc.Type != OptionType::Prefix) - throw OptName + ": incorrect option type!"; - O << OptDesc.GenVariableName() << " == \"" << OptArg << "\""; - return true; - } - else if (TestName == "element_in_list") { - if (OptDesc.Type != OptionType::ParameterList - && OptDesc.Type != OptionType::PrefixList) - throw OptName + ": incorrect option type!"; - const std::string& VarName = OptDesc.GenVariableName(); - O << "std::find(" << VarName << ".begin(),\n" - << IndentLevel << Indent1 << VarName << ".end(), \"" - << OptArg << "\") != " << VarName << ".end()"; - return true; - } - - return false; -} - -// Forward declaration. -// EmitLogicalOperationTest and EmitCaseTest are mutually recursive. -void EmitCaseTest(const DagInit& d, const char* IndentLevel, - const GlobalOptionDescriptions& OptDescs, - std::ostream& O); - -/// EmitLogicalOperationTest - Helper function used by -/// EmitCaseConstructHandler. -void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp, - const char* IndentLevel, - const GlobalOptionDescriptions& OptDescs, - std::ostream& O) { - O << '('; - for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) { - const DagInit& InnerTest = InitPtrToDagInitRef(d.getArg(j)); - EmitCaseTest(InnerTest, IndentLevel, OptDescs, O); - if (j != NumArgs - 1) - O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " ("; - else - O << ')'; - } -} - -/// EmitCaseTest - Helper function used by EmitCaseConstructHandler. -void EmitCaseTest(const DagInit& d, const char* IndentLevel, - const GlobalOptionDescriptions& OptDescs, - std::ostream& O) { - const std::string& TestName = d.getOperator()->getAsString(); - - if (TestName == "and") - EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O); - else if (TestName == "or") - EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O); - else if (EmitCaseTest1Arg(TestName, d, OptDescs, O)) - return; - else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O)) - return; - else - throw TestName + ": unknown edge property!"; -} - -// Emit code that handles the 'case' construct. -// Takes a function object that should emit code for every case clause. -template -void EmitCaseConstructHandler(DagInit* d, const char* IndentLevel, - const F& Callback, - const GlobalOptionDescriptions& OptDescs, - std::ostream& O) { - assert(d->getOperator()->getAsString() == "case"); - - for (DagInit::arg_iterator B = d->arg_begin(), E = d->arg_end(); - B != E; ++B) { - const DagInit& Test = InitPtrToDagInitRef(*B); - O << IndentLevel << "if ("; - EmitCaseTest(Test, IndentLevel, OptDescs, O); - O << ") {\n"; - - ++B; - if (B == E) - throw "Case construct handler: no corresponding action " - "found for the test " + Test.getAsString() + '!'; - - const DagInit& Action = InitPtrToDagInitRef(*B); - Callback(IndentLevel, Action, O); - O << IndentLevel << "}\n"; - } -} - // Helper function passed to EmitCaseConstructHandler by EmitEdgeClass. -void IncDecWeight(const char* IndentLevel, - const DagInit& d, std::ostream& O) { +void IncDecWeight (const Init* i, const char* IndentLevel, + std::ostream& O) { + const DagInit& d = InitPtrToDagInitRef(i); const std::string& OpName = d.getOperator()->getAsString(); if (OpName == "inc_weight") @@ -1120,9 +1161,9 @@ void IncDecWeight(const char* IndentLevel, } /// EmitEdgeClass - Emit a single Edge# class. -void EmitEdgeClass(unsigned N, const std::string& Target, - DagInit* Case, const GlobalOptionDescriptions& OptDescs, - std::ostream& O) { +void EmitEdgeClass (unsigned N, const std::string& Target, + DagInit* Case, const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { // Class constructor. O << "class Edge" << N << ": public Edge {\n" @@ -1178,7 +1219,7 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph, for (RecordVector::iterator B = Tools.begin(), E = Tools.end(); B != E; ++B) { const std::string& Name = (*B)->getName(); - if(Name != "root") + if (Name != "root") O << Indent1 << "G.insertNode(new " << Name << "());\n"; } @@ -1235,7 +1276,7 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) { // Emit Tool classes. for (ToolPropertiesList::const_iterator B = tool_props.begin(), E = tool_props.end(); B!=E; ++B) - EmitToolClassDefinition(*(*B), O); + EmitToolClassDefinition(*(*B), opt_descs, O); Record* CompilationGraphRecord = Records.getDef("CompilationGraph"); if (!CompilationGraphRecord)