Fix PR8441, a thread unsafe static variable in our dynamic library loading facilities.
[oota-llvm.git] / lib / CompilerDriver / CompilationGraph.cpp
index 4e953cbe1103a0371bbe26df2c98cccdd6ef8f7e..87a2c4817a842487c8d260d2ac18ba7976c4a632 100644 (file)
@@ -46,19 +46,25 @@ namespace llvmc {
 
 namespace {
 
-  /// ChooseEdge - Return the edge with the maximum weight.
+  /// ChooseEdge - Return the edge with the maximum weight. Returns 0 on error.
   template <class C>
   const Edge* ChooseEdge(const C& EdgesContainer,
                          const InputLanguagesSet& InLangs,
                          const std::string& NodeName = "root") {
     const Edge* MaxEdge = 0;
-    unsigned MaxWeight = 0;
+    int MaxWeight = 0;
     bool SingleMax = true;
 
+    // TODO: fix calculation of SingleMax.
     for (typename C::const_iterator B = EdgesContainer.begin(),
            E = EdgesContainer.end(); B != E; ++B) {
       const Edge* e = B->getPtr();
-      unsigned EW = e->Weight(InLangs);
+      int EW = e->Weight(InLangs);
+      if (EW < 0) {
+        // (error) invocation in TableGen -> we don't need to print an error
+        // message.
+        return 0;
+      }
       if (EW > MaxWeight) {
         MaxEdge = e;
         MaxWeight = EW;
@@ -139,7 +145,7 @@ void CompilationGraph::insertNode(Tool* V) {
 int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
   Node* B = getNode(Edg->ToolName());
   if (B == 0)
-    return -1;
+    return 1;
 
   if (A == "root") {
     const char** InLangs = B->ToolPtr->InputLanguages();
@@ -150,7 +156,7 @@ int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
   else {
     Node* N = getNode(A);
     if (N == 0)
-      return -1;
+      return 1;
 
     N->AddEdge(Edg);
   }
@@ -193,11 +199,11 @@ int CompilationGraph::PassThroughGraph (const sys::Path& InFile,
 
     const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name());
     if (Edg == 0)
-      return -1;
+      return 1;
 
     CurNode = getNode(Edg->ToolName());
     if (CurNode == 0)
-      return -1;
+      return 1;
 
     In = CurAction.OutFile();
   }
@@ -212,10 +218,11 @@ FindToolChain(const sys::Path& In, const std::string* ForceLanguage,
               InputLanguagesSet& InLangs, const LanguageMap& LangMap) const {
 
   // Determine the input language.
-  const std::string* InLang = LangMap.GetLanguage(In);
+  const std::string* InLang = (ForceLanguage ? ForceLanguage
+                               : LangMap.GetLanguage(In));
   if (InLang == 0)
     return 0;
-  const std::string& InLanguage = (ForceLanguage ? *ForceLanguage : *InLang);
+  const std::string& InLanguage = *InLang;
 
   // Add the current input language to the input language set.
   InLangs.insert(InLanguage);
@@ -295,7 +302,7 @@ int CompilationGraph::BuildInitial (InputLanguagesSet& InLangs,
     // Find the toolchain corresponding to this file.
     const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap);
     if (N == 0)
-      return -1;
+      return 1;
     // Pass file through the chain starting at head.
     if (int ret = PassThroughGraph(In, N, InLangs, TempDir, LangMap))
       return ret;
@@ -310,7 +317,7 @@ int CompilationGraph::TopologicalSort(std::vector<const Node*>& Out) {
 
   Node* Root = getNode("root");
   if (Root == 0)
-    return -1;
+    return 1;
 
   Q.push(Root);
 
@@ -322,7 +329,7 @@ int CompilationGraph::TopologicalSort(std::vector<const Node*>& Out) {
          EB != EE; ++EB) {
       Node* B = getNode((*EB)->ToolName());
       if (B == 0)
-        return -1;
+        return 1;
 
       B->DecrInEdges();
       if (B->HasNoInEdges())
@@ -355,6 +362,7 @@ TopologicalSortFilterJoinNodes(std::vector<const Node*>& Out) {
 int CompilationGraph::Build (const sys::Path& TempDir,
                              const LanguageMap& LangMap) {
   InputLanguagesSet InLangs;
+  bool WasSomeActionGenerated = !InputFilenames.empty();
 
   // Traverse initial parts of the toolchains and fill in InLangs.
   if (int ret = BuildInitial(InLangs, TempDir, LangMap))
@@ -375,6 +383,7 @@ int CompilationGraph::Build (const sys::Path& TempDir,
     if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty()))
       continue;
 
+    WasSomeActionGenerated = true;
     Action CurAction;
     if (int ret = JT->GenerateAction(CurAction, CurNode->HasChildren(),
                                      TempDir, InLangs, LangMap)) {
@@ -389,11 +398,11 @@ int CompilationGraph::Build (const sys::Path& TempDir,
 
     const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name());
     if (Edg == 0)
-      return -1;
+      return 1;
 
     const Node* NextNode = getNode(Edg->ToolName());
     if (NextNode == 0)
-      return -1;
+      return 1;
 
     if (int ret = PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode,
                                    InLangs, TempDir, LangMap)) {
@@ -401,6 +410,11 @@ int CompilationGraph::Build (const sys::Path& TempDir,
     }
   }
 
+  if (!WasSomeActionGenerated) {
+    PrintError("no input files");
+    return 1;
+  }
+
   return 0;
 }
 
@@ -417,7 +431,7 @@ int CompilationGraph::CheckLanguageNames() const {
            EB != EE; ++EB) {
         const Node* N2 = this->getNode((*EB)->ToolName());
         if (N2 == 0)
-          return -1;
+          return 1;
 
         if (!N2->ToolPtr) {
           ++ret;
@@ -426,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;
+            }
           }
         }
 
@@ -467,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;
-    unsigned MaxWeight = 0;
+    int MaxWeight = -1024;
 
     // Ignore the root node.
     if (!N.ToolPtr)
@@ -475,7 +493,7 @@ int CompilationGraph::CheckMultipleDefaultEdges() const {
 
     for (Node::const_iterator EB = N.EdgesBegin(), EE = N.EdgesEnd();
          EB != EE; ++EB) {
-      unsigned EdgeWeight = (*EB)->Weight(Dummy);
+      int EdgeWeight = (*EB)->Weight(Dummy);
       if (EdgeWeight > MaxWeight) {
         MaxWeight = EdgeWeight;
       }
@@ -497,7 +515,7 @@ int CompilationGraph::CheckCycles() {
 
   Node* Root = getNode("root");
   if (Root == 0)
-    return -1;
+    return 1;
 
   Q.push(Root);
 
@@ -513,7 +531,7 @@ int CompilationGraph::CheckCycles() {
          EB != EE; ++EB) {
       Node* B = getNode((*EB)->ToolName());
       if (B == 0)
-        return -1;
+        return 1;
 
       B->DecrInEdges();
       if (B->HasNoInEdges())
@@ -539,19 +557,19 @@ int CompilationGraph::Check () {
   // Check that output/input language names match.
   ret = this->CheckLanguageNames();
   if (ret < 0)
-    return -1;
+    return 1;
   errs += ret;
 
   // Check for multiple default edges.
   ret = this->CheckMultipleDefaultEdges();
   if (ret < 0)
-    return -1;
+    return 1;
   errs += ret;
 
   // Check for cycles.
   ret = this->CheckCycles();
   if (ret < 0)
-    return -1;
+    return 1;
   errs += ret;
 
   return errs;
@@ -559,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*>
@@ -573,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
@@ -583,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;
@@ -617,7 +643,7 @@ int CompilationGraph::writeGraph(const std::string& OutputFilename) {
   }
   else {
     PrintError("Error opening file '" + OutputFilename + "' for writing!");
-    return -1;
+    return 1;
   }
 
   return 0;