[llvm-commits] [llvm] r114433 - in /llvm/trunk: include/llvm/CompilerDriver/Tool.h lib/CompilerDriver/CompilationGraph.cpp test/LLVMC/MultipleOutputLanguages.td utils/TableGen/LLVMCConfigurationEmitter.cpp

Mikhail Glushenkov foldr at codedgers.com
Tue Sep 21 07:59:42 PDT 2010


Author: foldr
Date: Tue Sep 21 09:59:42 2010
New Revision: 114433

URL: http://llvm.org/viewvc/llvm-project?rev=114433&view=rev
Log:
llvmc: Allow multiple output languages.

Added:
    llvm/trunk/test/LLVMC/MultipleOutputLanguages.td
Modified:
    llvm/trunk/include/llvm/CompilerDriver/Tool.h
    llvm/trunk/lib/CompilerDriver/CompilationGraph.cpp
    llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp

Modified: llvm/trunk/include/llvm/CompilerDriver/Tool.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CompilerDriver/Tool.h?rev=114433&r1=114432&r2=114433&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CompilerDriver/Tool.h (original)
+++ llvm/trunk/include/llvm/CompilerDriver/Tool.h Tue Sep 21 09:59:42 2010
@@ -58,7 +58,7 @@
 
     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;

Modified: llvm/trunk/lib/CompilerDriver/CompilationGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CompilerDriver/CompilationGraph.cpp?rev=114433&r1=114432&r2=114433&view=diff
==============================================================================
--- llvm/trunk/lib/CompilerDriver/CompilationGraph.cpp (original)
+++ llvm/trunk/lib/CompilerDriver/CompilationGraph.cpp Tue Sep 21 09:59:42 2010
@@ -440,13 +440,17 @@
           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 @@
   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 @@
 
 // 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 @@
         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 @@
     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;

Added: llvm/trunk/test/LLVMC/MultipleOutputLanguages.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/MultipleOutputLanguages.td?rev=114433&view=auto
==============================================================================
--- llvm/trunk/test/LLVMC/MultipleOutputLanguages.td (added)
+++ llvm/trunk/test/LLVMC/MultipleOutputLanguages.td Tue Sep 21 09:59:42 2010
@@ -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")
+]>;

Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp?rev=114433&r1=114432&r2=114433&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Tue Sep 21 09:59:42 2010
@@ -833,7 +833,7 @@
   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 @@
     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 @@
 }
 
 /// 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 @@
   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 @@
   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 @@
     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);





More information about the llvm-commits mailing list