diff options
author | Mikhail Glushenkov <foldr@codedgers.com> | 2010-09-21 14:59:42 +0000 |
---|---|---|
committer | Mikhail Glushenkov <foldr@codedgers.com> | 2010-09-21 14:59:42 +0000 |
commit | 46aa524f0d34c21ccd64d674ae3628c69fb9883e (patch) | |
tree | 62a3dae95328988fee6065eca1b456ba4a2be856 | |
parent | 6d31c0b79a06483d7a80209bba34226ccf9088bb (diff) | |
download | external_llvm-46aa524f0d34c21ccd64d674ae3628c69fb9883e.zip external_llvm-46aa524f0d34c21ccd64d674ae3628c69fb9883e.tar.gz external_llvm-46aa524f0d34c21ccd64d674ae3628c69fb9883e.tar.bz2 |
llvmc: Allow multiple output languages.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114433 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/CompilerDriver/Tool.h | 2 | ||||
-rw-r--r-- | lib/CompilerDriver/CompilationGraph.cpp | 58 | ||||
-rw-r--r-- | test/LLVMC/MultipleOutputLanguages.td | 27 | ||||
-rw-r--r-- | utils/TableGen/LLVMCConfigurationEmitter.cpp | 96 |
4 files changed, 124 insertions, 59 deletions
diff --git a/include/llvm/CompilerDriver/Tool.h b/include/llvm/CompilerDriver/Tool.h index 45ef50d..7316dfd 100644 --- a/include/llvm/CompilerDriver/Tool.h +++ b/include/llvm/CompilerDriver/Tool.h @@ -58,7 +58,7 @@ namespace llvmc { virtual const char* Name() const = 0; virtual const char** InputLanguages() const = 0; - virtual const char* OutputLanguage() const = 0; + virtual const char** OutputLanguages() const = 0; virtual bool IsJoin() const = 0; virtual bool WorksOnEmpty() const = 0; diff --git a/lib/CompilerDriver/CompilationGraph.cpp b/lib/CompilerDriver/CompilationGraph.cpp index 0aecfa6..87a2c48 100644 --- a/lib/CompilerDriver/CompilationGraph.cpp +++ b/lib/CompilerDriver/CompilationGraph.cpp @@ -440,13 +440,17 @@ int CompilationGraph::CheckLanguageNames() const { continue; } - const char* OutLang = N1.ToolPtr->OutputLanguage(); + const char** OutLangs = N1.ToolPtr->OutputLanguages(); const char** InLangs = N2->ToolPtr->InputLanguages(); bool eq = false; - for (;*InLangs; ++InLangs) { - if (std::strcmp(OutLang, *InLangs) == 0) { - eq = true; - break; + const char* OutLang = 0; + for (;*OutLangs; ++OutLangs) { + OutLang = *OutLangs; + for (;*InLangs; ++InLangs) { + if (std::strcmp(OutLang, *InLangs) == 0) { + eq = true; + break; + } } } @@ -481,7 +485,7 @@ int CompilationGraph::CheckMultipleDefaultEdges() const { for (const_nodes_iterator B = this->NodesMap.begin(), E = this->NodesMap.end(); B != E; ++B) { const Node& N = B->second; - int MaxWeight = 0; + int MaxWeight = -1024; // Ignore the root node. if (!N.ToolPtr) @@ -573,6 +577,26 @@ int CompilationGraph::Check () { // Code related to graph visualization. +namespace { + +std::string SquashStrArray (const char** StrArr) { + std::string ret; + + for (; *StrArr; ++StrArr) { + if (*(StrArr + 1)) { + ret += *StrArr; + ret += ", "; + } + else { + ret += *StrArr; + } + } + + return ret; +} + +} // End anonymous namespace. + namespace llvm { template <> struct DOTGraphTraits<llvmc::CompilationGraph*> @@ -587,7 +611,8 @@ namespace llvm { if (N->ToolPtr->IsJoin()) return N->Name() + "\n (join" + (N->HasChildren() ? ")" - : std::string(": ") + N->ToolPtr->OutputLanguage() + ')'); + : std::string(": ") + + SquashStrArray(N->ToolPtr->OutputLanguages()) + ')'); else return N->Name(); else @@ -597,28 +622,15 @@ namespace llvm { template<typename EdgeIter> static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) { if (N->ToolPtr) { - return N->ToolPtr->OutputLanguage(); + return SquashStrArray(N->ToolPtr->OutputLanguages()); } else { - const char** InLangs = I->ToolPtr->InputLanguages(); - std::string ret; - - for (; *InLangs; ++InLangs) { - if (*(InLangs + 1)) { - ret += *InLangs; - ret += ", "; - } - else { - ret += *InLangs; - } - } - - return ret; + return SquashStrArray(I->ToolPtr->InputLanguages()); } } }; -} +} // End namespace llvm int CompilationGraph::writeGraph(const std::string& OutputFilename) { std::string ErrorInfo; diff --git a/test/LLVMC/MultipleOutputLanguages.td b/test/LLVMC/MultipleOutputLanguages.td new file mode 100644 index 0000000..02512c2 --- /dev/null +++ b/test/LLVMC/MultipleOutputLanguages.td @@ -0,0 +1,27 @@ +// Check that multiple output languages work. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: FileCheck -input-file %t %s +// RUN: %compile_cxx %t +// XFAIL: vg_leak + +include "llvm/CompilerDriver/Common.td" + +def dummy_tool : Tool<[ + (command "dummy_cmd"), + (in_language "dummy_lang"), + (out_language ["another_dummy_lang", "yet_another_dummy_lang"]) +]>; + +def another_dummy_tool : Tool<[ + (command "another_dummy_cmd"), + (in_language ["another_dummy_lang", "some_other_dummy_lang"]), + (out_language "executable"), + (join) +]>; + +// CHECK: new SimpleEdge("dummy_tool") +// CHECK: new SimpleEdge("another_dummy_tool") +def DummyGraph : CompilationGraph<[ + (edge "root", "dummy_tool"), + (edge "dummy_tool", "another_dummy_tool") +]>; diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index 8b81e14..7ad981f 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -833,7 +833,7 @@ struct ToolDescription : public RefCountedBase<ToolDescription> { StrVector InLanguage; std::string InFileOption; std::string OutFileOption; - std::string OutLanguage; + StrVector OutLanguage; std::string OutputSuffix; unsigned Flags; const Init* OnEmpty; @@ -919,41 +919,43 @@ private: toolDesc_.CmdLine = d.getArg(0); } - void onInLanguage (const DagInit& d) { + /// onInOutLanguage - Common implementation of on{In,Out}Language(). + void onInOutLanguage (const DagInit& d, StrVector& OutVec) { CheckNumberOfArguments(d, 1); Init* arg = d.getArg(0); // Find out the argument's type. if (typeid(*arg) == typeid(StringInit)) { // It's a string. - toolDesc_.InLanguage.push_back(InitPtrToString(arg)); + OutVec.push_back(InitPtrToString(arg)); } else { // It's a list. const ListInit& lst = InitPtrToList(arg); - StrVector& out = toolDesc_.InLanguage; // Copy strings to the output vector. - for (ListInit::const_iterator B = lst.begin(), E = lst.end(); - B != E; ++B) { - out.push_back(InitPtrToString(*B)); - } + for (ListInit::const_iterator B = lst.begin(), E = lst.end(); B != E; ++B) + OutVec.push_back(InitPtrToString(*B)); // Remove duplicates. - std::sort(out.begin(), out.end()); - StrVector::iterator newE = std::unique(out.begin(), out.end()); - out.erase(newE, out.end()); + std::sort(OutVec.begin(), OutVec.end()); + StrVector::iterator newE = std::unique(OutVec.begin(), OutVec.end()); + OutVec.erase(newE, OutVec.end()); } } + + void onInLanguage (const DagInit& d) { + this->onInOutLanguage(d, toolDesc_.InLanguage); + } + void onJoin (const DagInit& d) { CheckNumberOfArguments(d, 0); toolDesc_.setJoin(); } void onOutLanguage (const DagInit& d) { - CheckNumberOfArguments(d, 1); - toolDesc_.OutLanguage = InitPtrToString(d.getArg(0)); + this->onInOutLanguage(d, toolDesc_.OutLanguage); } void onOutFileOption (const DagInit& d) { @@ -1062,47 +1064,62 @@ void FilterNotInGraph (const DagVector& EdgeVector, } /// FillInToolToLang - Fills in two tables that map tool names to -/// (input, output) languages. Helper function used by TypecheckGraph(). +/// input & output language names. Helper function used by TypecheckGraph(). void FillInToolToLang (const ToolDescriptions& ToolDescs, StringMap<StringSet<> >& ToolToInLang, - StringMap<std::string>& ToolToOutLang) { + StringMap<StringSet<> >& ToolToOutLang) { for (ToolDescriptions::const_iterator B = ToolDescs.begin(), E = ToolDescs.end(); B != E; ++B) { const ToolDescription& D = *(*B); for (StrVector::const_iterator B = D.InLanguage.begin(), E = D.InLanguage.end(); B != E; ++B) ToolToInLang[D.Name].insert(*B); - ToolToOutLang[D.Name] = D.OutLanguage; + for (StrVector::const_iterator B = D.OutLanguage.begin(), + E = D.OutLanguage.end(); B != E; ++B) + ToolToOutLang[D.Name].insert(*B); } } +/// Intersect - Is set intersection non-empty? +bool Intersect (const StringSet<>& S1, const StringSet<>& S2) { + for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) { + if (S2.count(B->first()) != 0) + return true; + } + return false; +} + /// TypecheckGraph - Check that names for output and input languages /// on all edges do match. void TypecheckGraph (const DagVector& EdgeVector, const ToolDescriptions& ToolDescs) { StringMap<StringSet<> > ToolToInLang; - StringMap<std::string> ToolToOutLang; + StringMap<StringSet<> > ToolToOutLang; FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang); - StringMap<std::string>::iterator IAE = ToolToOutLang.end(); - StringMap<StringSet<> >::iterator IBE = ToolToInLang.end(); for (DagVector::const_iterator B = EdgeVector.begin(), E = EdgeVector.end(); B != E; ++B) { const DagInit* Edge = *B; const std::string& NodeA = InitPtrToString(Edge->getArg(0)); const std::string& NodeB = InitPtrToString(Edge->getArg(1)); - StringMap<std::string>::iterator IA = ToolToOutLang.find(NodeA); + StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA); StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB); + if (NodeB == "root") + throw "Edges back to the root are not allowed!"; + if (NodeA != "root") { - if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0) + if (IA == ToolToOutLang.end()) + throw NodeA + ": no output language defined!"; + if (IB == ToolToInLang.end()) + throw NodeB + ": no input language defined!"; + + if (!Intersect(IA->second, IB->second)) { throw "Edge " + NodeA + "->" + NodeB + ": output->input language mismatch"; + } } - - if (NodeB == "root") - throw "Edges back to the root are not allowed!"; } } @@ -2250,11 +2267,8 @@ void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) { O.indent(Indent2) << "return InputLanguages_;\n"; O.indent(Indent1) << "}\n\n"; - if (D.OutLanguage.empty()) - throw "Tool " + D.Name + " has no 'out_language' property!"; - - O.indent(Indent1) << "const char* OutputLanguage() const {\n"; - O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\n"; + O.indent(Indent1) << "const char** OutputLanguages() const {\n"; + O.indent(Indent2) << "return OutputLanguages_;\n"; O.indent(Indent1) << "}\n\n"; } @@ -2299,17 +2313,28 @@ void EmitWorksOnEmptyMethod (const ToolDescription& D, O.indent(Indent1) << "}\n\n"; } +/// EmitStrArray - Emit definition of a 'const char**' static member +/// variable. Helper used by EmitStaticMemberDefinitions(); +void EmitStrArray(const std::string& Name, const std::string& VarName, + const StrVector& StrVec, raw_ostream& O) { + O << "const char* " << Name << "::" << VarName << "[] = {"; + for (StrVector::const_iterator B = StrVec.begin(), E = StrVec.end(); + B != E; ++B) + O << '\"' << *B << "\", "; + O << "0};\n"; +} + /// EmitStaticMemberDefinitions - Emit static member definitions for a /// given Tool class. void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) { if (D.InLanguage.empty()) throw "Tool " + D.Name + " has no 'in_language' property!"; + if (D.OutLanguage.empty()) + throw "Tool " + D.Name + " has no 'out_language' property!"; - O << "const char* " << D.Name << "::InputLanguages_[] = {"; - for (StrVector::const_iterator B = D.InLanguage.begin(), - E = D.InLanguage.end(); B != E; ++B) - O << '\"' << *B << "\", "; - O << "0};\n\n"; + EmitStrArray(D.Name, "InputLanguages_", D.InLanguage, O); + EmitStrArray(D.Name, "OutputLanguages_", D.OutLanguage, O); + O << '\n'; } /// EmitToolClassDefinition - Emit a Tool class definition. @@ -2327,7 +2352,8 @@ void EmitToolClassDefinition (const ToolDescription& D, O << "Tool"; O << " {\nprivate:\n"; - O.indent(Indent1) << "static const char* InputLanguages_[];\n\n"; + O.indent(Indent1) << "static const char* InputLanguages_[];\n"; + O.indent(Indent1) << "static const char* OutputLanguages_[];\n\n"; O << "public:\n"; EmitNameMethod(D, O); |