From 010887765a9a80ecb5e34b65a3aeacf098298cb3 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Mon, 17 Nov 2008 17:29:18 +0000 Subject: [PATCH] Add a layer of indirection to make plugins more flexible. Use strings instead of TableGen defs in the compilation graph definition. Makes it easier for the plugins to modify an existing graph. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59447 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CompilerDriver/Common.td | 16 +-- tools/llvmc2/doc/LLVMC-Reference.rst | 21 ++-- tools/llvmc2/doc/LLVMC-Tutorial.rst | 2 +- tools/llvmc2/plugins/Base/Base.td | 54 ++++----- tools/llvmc2/plugins/Clang/Clang.td | 12 +- tools/llvmc2/plugins/Simple/Simple.td | 2 +- utils/TableGen/LLVMCConfigurationEmitter.cpp | 113 ++++++++++--------- 7 files changed, 111 insertions(+), 109 deletions(-) diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td index 45518385e41..e017326069e 100644 --- a/include/llvm/CompilerDriver/Common.td +++ b/include/llvm/CompilerDriver/Common.td @@ -15,10 +15,6 @@ class Tool l> { list properties = l; } -// Special Tool instance - the root node of the compilation graph. - -def root : Tool<[]>; - // Possible Tool properties def in_language; @@ -87,19 +83,19 @@ class LanguageMap lst> { // Compilation graph -class EdgeBase { - Tool a = t1; - Tool b = t2; +class EdgeBase { + string a = t1; + string b = t2; dag weight = d; } -class Edge : EdgeBase; +class Edge : EdgeBase; // Edge and SimpleEdge are synonyms. -class SimpleEdge : EdgeBase; +class SimpleEdge : EdgeBase; // Optionally enabled edge. -class OptionalEdge : EdgeBase; +class OptionalEdge : EdgeBase; class CompilationGraph lst> { list edges = lst; diff --git a/tools/llvmc2/doc/LLVMC-Reference.rst b/tools/llvmc2/doc/LLVMC-Reference.rst index 62e2ef41a8b..2d782572987 100644 --- a/tools/llvmc2/doc/LLVMC-Reference.rst +++ b/tools/llvmc2/doc/LLVMC-Reference.rst @@ -158,7 +158,7 @@ definitions:: include "llvm/CompilerDriver/Common.td" // And optionally: // include "llvm/CompilerDriver/Tools.td" - // which contains tool definitions. + // which contains some useful tool definitions. Internally, LLVMC stores information about possible source transformations in form of a graph. Nodes in this graph represent @@ -171,19 +171,19 @@ The definition of the compilation graph (see file ``plugins/Base/Base.td`` for an example) is just a list of edges:: def CompilationGraph : CompilationGraph<[ - Edge, - Edge, + Edge<"root", "llvm_gcc_c">, + Edge<"root", "llvm_gcc_assembler">, ... - Edge, - Edge, + Edge<"llvm_gcc_c", "llc">, + Edge<"llvm_gcc_cpp", "llc">, ... - OptionalEdge, - OptionalEdge, + OptionalEdge<"llvm_gcc_c", "opt", [(switch_on "opt")]>, + OptionalEdge<"llvm_gcc_cpp", "opt", [(switch_on "opt")]>, ... - OptionalEdge, @@ -193,7 +193,10 @@ The definition of the compilation graph (see file As you can see, the edges can be either default or optional, where optional edges are differentiated by an additional ``case`` expression -used to calculate the weight of this edge. +used to calculate the weight of this edge. Notice also that we refer +to tools via their names (as strings). This allows us to add edges to +an existing compilation graph without having to include all tool +definitions that it uses. The default edges are assigned a weight of 1, and optional edges get a weight of 0 + 2*N where N is the number of tests that evaluated to diff --git a/tools/llvmc2/doc/LLVMC-Tutorial.rst b/tools/llvmc2/doc/LLVMC-Tutorial.rst index ffc1de903b8..9c6741eba1d 100644 --- a/tools/llvmc2/doc/LLVMC-Tutorial.rst +++ b/tools/llvmc2/doc/LLVMC-Tutorial.rst @@ -66,7 +66,7 @@ Contents of the file ``Simple.td`` look like this:: def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>; // Compilation graph - def CompilationGraph : CompilationGraph<[Edge]>; + def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>; As you can see, this file consists of three parts: tool descriptions, language map, and the compilation graph definition. diff --git a/tools/llvmc2/plugins/Base/Base.td b/tools/llvmc2/plugins/Base/Base.td index 158520c278e..85a37cb41a7 100644 --- a/tools/llvmc2/plugins/Base/Base.td +++ b/tools/llvmc2/plugins/Base/Base.td @@ -17,42 +17,42 @@ include "llvm/CompilerDriver/Tools.td" // Toolchains def CompilationGraph : CompilationGraph<[ - Edge, - Edge, - Edge, - Edge, - Edge, - Edge, - - Edge, - Edge, - Edge, - Edge, - Edge, - - OptionalEdge, - OptionalEdge, - OptionalEdge, - OptionalEdge, - OptionalEdge, - Edge, - - Edge, - Edge, - OptionalEdge, + Edge<"root", "llvm_gcc_assembler">, + Edge<"root", "llvm_gcc_cpp">, + Edge<"root", "llvm_gcc_m">, + Edge<"root", "llvm_gcc_mxx">, + Edge<"root", "llvm_as">, + + Edge<"llvm_gcc_c", "llc">, + Edge<"llvm_gcc_cpp", "llc">, + Edge<"llvm_gcc_m", "llc">, + Edge<"llvm_gcc_mxx", "llc">, + Edge<"llvm_as", "llc">, + + OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_gcc_m", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_gcc_mxx", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_as", "opt", (case (switch_on "opt"), (inc_weight))>, + Edge<"opt", "llc">, + + Edge<"llc", "llvm_gcc_assembler">, + Edge<"llvm_gcc_assembler", "llvm_gcc_linker">, + OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker", (case (or (input_languages_contain "c++"), - (input_languages_contain "objective-c++")), + (input_languages_contain "objective-c++")), (inc_weight), (or (parameter_equals "linker", "g++"), (parameter_equals "linker", "c++")), (inc_weight))>, - Edge, - OptionalEdge, + OptionalEdge<"root", "llvm_gcc_cpp_linker", (case (or (input_languages_contain "c++"), - (input_languages_contain "objective-c++")), + (input_languages_contain "objective-c++")), (inc_weight), (or (parameter_equals "linker", "g++"), (parameter_equals "linker", "c++")), (inc_weight))> diff --git a/tools/llvmc2/plugins/Clang/Clang.td b/tools/llvmc2/plugins/Clang/Clang.td index d30bc978aa8..ee6987fa352 100644 --- a/tools/llvmc2/plugins/Clang/Clang.td +++ b/tools/llvmc2/plugins/Clang/Clang.td @@ -76,11 +76,11 @@ def LanguageMap : LanguageMap< // Compilation graph def CompilationGraph : CompilationGraph<[ - Edge, - Edge, - Edge, - Edge, - Edge, - Edge + Edge<"root", "clang_c">, + Edge<"root", "clang_cpp">, + Edge<"root", "clang_objective_c">, + Edge<"clang_c", "llvm_ld">, + Edge<"clang_cpp", "llvm_ld">, + Edge<"clang_objective_c", "llvm_ld"> ]>; diff --git a/tools/llvmc2/plugins/Simple/Simple.td b/tools/llvmc2/plugins/Simple/Simple.td index 2bc40119261..b974cbc95eb 100644 --- a/tools/llvmc2/plugins/Simple/Simple.td +++ b/tools/llvmc2/plugins/Simple/Simple.td @@ -27,4 +27,4 @@ def gcc : Tool< def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>; -def CompilationGraph : CompilationGraph<[Edge]>; +def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>; diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index bacde538daa..f5a1cf8652c 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -764,11 +764,11 @@ void CollectToolProperties (RecordVector::const_iterator B, } -/// CollectPropertiesFromOptionList - Gather information about -/// *global* option properties from the OptionList. -void CollectPropertiesFromOptionList (RecordVector::const_iterator B, - RecordVector::const_iterator E, - GlobalOptionDescriptions& OptDescs) +/// CollectPropertiesFromOptionLists - Gather information about +/// *global* option properties from all OptionLists. +void CollectPropertiesFromOptionLists (RecordVector::const_iterator B, + RecordVector::const_iterator E, + GlobalOptionDescriptions& OptDescs) { // Iterate over a properties list of every Tool definition for (;B!=E;++B) { @@ -805,7 +805,7 @@ void CheckForSuperfluousOptions (const ToolPropertiesList& TPList, const GlobalOptionDescription& Val = B->second; if (!nonSuperfluousOptions.count(Val.Name) && Val.Type != OptionType::Alias) - cerr << "Warning: option '-" << Val.Name << "' has no effect! " + llvm::cerr << "Warning: option '-" << Val.Name << "' has no effect! " "Probable cause: this option is specified only in the OptionList.\n"; } } @@ -1448,29 +1448,31 @@ void EmitOptionDescriptions (const GlobalOptionDescriptions& descs, /// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function. void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O) { + // Generate code + O << "namespace {\n\n"; + O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n"; + // Get the relevant field out of RecordKeeper Record* LangMapRecord = Records.getDef("LanguageMap"); - if (!LangMapRecord) - throw std::string("Language map definition not found!"); - ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map"); - if (!LangsToSuffixesList) - throw std::string("Error in the language map definition!"); + // It is allowed for a plugin to have no language map. + if (LangMapRecord) { - // Generate code - O << "namespace {\n\n"; - O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n"; + ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map"); + if (!LangsToSuffixesList) + throw std::string("Error in the language map definition!"); - for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) { - Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i); + for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) { + Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i); - const std::string& Lang = LangToSuffixes->getValueAsString("lang"); - const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes"); + const std::string& Lang = LangToSuffixes->getValueAsString("lang"); + const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes"); - for (unsigned i = 0; i < Suffixes->size(); ++i) - O << Indent1 << "langMap[\"" - << InitPtrToString(Suffixes->getElement(i)) - << "\"] = \"" << Lang << "\";\n"; + for (unsigned i = 0; i < Suffixes->size(); ++i) + O << Indent1 << "langMap[\"" + << InitPtrToString(Suffixes->getElement(i)) + << "\"] = \"" << Lang << "\";\n"; + } } O << "}\n\n}\n\n"; @@ -1492,13 +1494,11 @@ void FillInToolToLang (const ToolPropertiesList& TPList, } /// TypecheckGraph - Check that names for output and input languages -/// on all edges do match. -// TOFIX: It would be nice if this function also checked for cycles -// and multiple default edges in the graph (better error -// reporting). Unfortunately, it is awkward to do right now because -// our intermediate representation is not sufficiently -// sophisticated. Algorithms like these require a real graph instead of -// an AST. +/// on all edges do match. This doesn't do much when the information +/// about the whole graph is not available (i.e. when compiling most +/// plugins). +// TODO: add a --check-graph switch to llvmc2. It would also make it +// possible to detect cycles and multiple default edges. void TypecheckGraph (Record* CompilationGraph, const ToolPropertiesList& TPList) { StringMap > ToolToInLang; @@ -1511,18 +1511,18 @@ void TypecheckGraph (Record* CompilationGraph, for (unsigned i = 0; i < edges->size(); ++i) { Record* Edge = edges->getElementAsRecord(i); - Record* A = Edge->getValueAsDef("a"); - Record* B = Edge->getValueAsDef("b"); - StringMap::iterator IA = ToolToOutLang.find(A->getName()); - StringMap >::iterator IB = ToolToInLang.find(B->getName()); - if (IA == IAE) - throw A->getName() + ": no such tool!"; - if (IB == IBE) - throw B->getName() + ": no such tool!"; - if (A->getName() != "root" && IB->second.count(IA->second) == 0) - throw "Edge " + A->getName() + "->" + B->getName() - + ": output->input language mismatch"; - if (B->getName() == "root") + const std::string& A = Edge->getValueAsString("a"); + const std::string& B = Edge->getValueAsString("b"); + StringMap::iterator IA = ToolToOutLang.find(A); + StringMap >::iterator IB = ToolToInLang.find(B); + + if (A != "root") { + if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0) + throw "Edge " + A + "->" + B + + ": output->input language mismatch"; + } + + if (B == "root") throw std::string("Edges back to the root are not allowed!"); } } @@ -1578,13 +1578,13 @@ void EmitEdgeClasses (Record* CompilationGraph, for (unsigned i = 0; i < edges->size(); ++i) { Record* Edge = edges->getElementAsRecord(i); - Record* B = Edge->getValueAsDef("b"); + const std::string& B = Edge->getValueAsString("b"); DagInit* Weight = Edge->getValueAsDag("weight"); if (isDagEmpty(Weight)) continue; - EmitEdgeClass(i, B->getName(), Weight, OptDescs, O); + EmitEdgeClass(i, B, Weight, OptDescs, O); } } @@ -1605,13 +1605,12 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph, for (unsigned i = 0; i < edges->size(); ++i) { Record* Edge = edges->getElementAsRecord(i); - Record* A = Edge->getValueAsDef("a"); - Record* B = Edge->getValueAsDef("b"); + const std::string& A = Edge->getValueAsString("a"); + const std::string& B = Edge->getValueAsString("b"); - if (A->getName() != "root") - ToolsInGraph.insert(A->getName()); - if (B->getName() != "root") - ToolsInGraph.insert(B->getName()); + if (A != "root") + ToolsInGraph.insert(A); + ToolsInGraph.insert(B); } for (llvm::StringSet<>::iterator B = ToolsInGraph.begin(), @@ -1624,14 +1623,14 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph, for (unsigned i = 0; i < edges->size(); ++i) { Record* Edge = edges->getElementAsRecord(i); - Record* A = Edge->getValueAsDef("a"); - Record* B = Edge->getValueAsDef("b"); + const std::string& A = Edge->getValueAsString("a"); + const std::string& B = Edge->getValueAsString("b"); DagInit* Weight = Edge->getValueAsDag("weight"); - O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", "; + O << Indent1 << "G.insertEdge(\"" << A << "\", "; if (isDagEmpty(Weight)) - O << "new SimpleEdge(\"" << B->getName() << "\")"; + O << "new SimpleEdge(\"" << B << "\")"; else O << "new Edge" << i << "()"; @@ -1763,6 +1762,7 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) { EmitIncludes(O); // Get a list of all defined Tools. + RecordVector Tools = Records.getAllDerivedDefinitions("Tool"); if (Tools.empty()) throw std::string("No tool definitions found!"); @@ -1773,8 +1773,8 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) { CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs); RecordVector OptionLists = Records.getAllDerivedDefinitions("OptionList"); - CollectPropertiesFromOptionList(OptionLists.begin(), OptionLists.end(), - opt_descs); + CollectPropertiesFromOptionLists(OptionLists.begin(), OptionLists.end(), + opt_descs); // Check that there are no options without side effects (specified // only in the OptionList). @@ -1795,6 +1795,9 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) { E = tool_props.end(); B!=E; ++B) EmitToolClassDefinition(*(*B), opt_descs, O); + // TOTHINK: Nothing actually prevents us from having multiple + // compilation graphs in a single plugin; OTOH, I do not see how + // that could be useful. Record* CompilationGraphRecord = Records.getDef("CompilationGraph"); if (!CompilationGraphRecord) throw std::string("Compilation graph description not found!"); -- 2.34.1