Add -x option (like in gcc).
authorMikhail Glushenkov <foldr@codedgers.com>
Tue, 6 May 2008 18:10:53 +0000 (18:10 +0000)
committerMikhail Glushenkov <foldr@codedgers.com>
Tue, 6 May 2008 18:10:53 +0000 (18:10 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50750 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvmc2/Action.cpp
tools/llvmc2/CompilationGraph.cpp
tools/llvmc2/CompilationGraph.h
tools/llvmc2/Tools.td
tools/llvmc2/llvmc.cpp

index 3d61d37368ff7436af18011a464695b51bed5136..80531c0806a7f1f4cdb9ee062ec5d1901c1bf1c2 100644 (file)
@@ -34,7 +34,7 @@ namespace {
     if (!prog.canExecute())
       throw std::runtime_error("Program '" + name + "' is not executable.");
 
-    // Build the command line vector and redirects.
+    // Build the command line vector and the redirects array.
     const sys::Path* redirects[3] = {0,0,0};
     sys::Path stdout_redirect;
 
index ed03f5856ec544439f2feaf39aad72d62df19abc..4b04d6f60b36451a6bce2ff51c7d0469a6c48325 100644 (file)
 
 #include "CompilationGraph.h"
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/DOTGraphTraits.h"
 #include "llvm/Support/GraphWriter.h"
 
 #include <algorithm>
-#include <iostream>
 #include <iterator>
+#include <limits>
 #include <queue>
 #include <stdexcept>
 
@@ -28,10 +29,13 @@ using namespace llvmc;
 
 extern cl::list<std::string> InputFilenames;
 extern cl::opt<std::string> OutputFilename;
+extern cl::list<std::string> Languages;
 
 namespace {
 
-  // Choose edge that returns
+  // Go through the list C and find the edge that isEnabled(); if
+  // there is no such edge, return the default edge; if there is no
+  // default edge, throw an exception.
   template <class C>
   const Edge* ChooseEdge(const C& EdgesContainer,
                          const std::string& NodeName = "root") {
@@ -47,7 +51,7 @@ namespace {
         else
           throw std::runtime_error("Node " + NodeName
                                    + ": multiple default outward edges found!"
-                                   "Most probably a specification error.");
+                                   " Most probably a specification error.");
       if (E->isEnabled())
         return E;
     }
@@ -57,7 +61,7 @@ namespace {
     else
       throw std::runtime_error("Node " + NodeName
                                + ": no default outward edge found!"
-                               "Most probably a specification error.");
+                               " Most probably a specification error.");
   }
 
 }
@@ -92,8 +96,8 @@ CompilationGraph::getToolsVector(const std::string& LangName) const
 {
   tools_map_type::const_iterator I = ToolsMap.find(LangName);
   if (I == ToolsMap.end())
-    throw std::runtime_error("No tools corresponding to " + LangName
-                             + found!");
+    throw std::runtime_error("No tool corresponding to the language "
+                             + LangName + "found!");
   return I->second;
 }
 
@@ -121,15 +125,15 @@ void CompilationGraph::insertEdge(const std::string& A, Edge* E) {
   B.IncrInEdges();
 }
 
-// Make a temporary file named like BaseName-RandomDigits.Suffix
-sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
-                       const std::string& Suffix) {
-  sys::Path Out = TempDir;
-  Out.appendComponent(BaseName);
-  Out.appendSuffix(Suffix);
-  Out.makeUnique(true, NULL);
-  Out.eraseFromDisk();
-  return Out;
+namespace {
+  sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
+                         const std::string& Suffix) {
+    sys::Path Out = TempDir;
+    Out.appendComponent(BaseName);
+    Out.appendSuffix(Suffix);
+    Out.makeUnique(true, NULL);
+    return Out;
+  }
 }
 
 // Pass input file through the chain until we bump into a Join node or
@@ -170,6 +174,9 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
     if (CurTool->GenerateAction(In, Out).Execute() != 0)
       throw std::runtime_error("Tool returned error code!");
 
+    if (Last)
+      return;
+
     CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
                                   CurNode->Name())->ToolName());
     In = Out; Out.clear();
@@ -212,8 +219,10 @@ TopologicalSortFilterJoinNodes(std::vector<const Node*>& Out) {
 }
 
 // Find head of the toolchain corresponding to the given file.
-const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
-  const std::string& InLanguage = getLanguage(In);
+const Node* CompilationGraph::
+FindToolChain(const sys::Path& In, const std::string* forceLanguage) const {
+  const std::string& InLanguage =
+    forceLanguage ? *forceLanguage : getLanguage(In);
   const tools_vector_type& TV = getToolsVector(InLanguage);
   if (TV.empty())
     throw std::runtime_error("No toolchain corresponding to language"
@@ -225,13 +234,55 @@ const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
 // temporary variables.
 int CompilationGraph::Build (const sys::Path& TempDir) {
 
+  // This is related to -x option handling.
+  cl::list<std::string>::const_iterator xIter = Languages.begin(),
+    xBegin = xIter, xEnd = Languages.end();
+  bool xEmpty = true;
+  const std::string* xLanguage = 0;
+  unsigned xPos = 0, xPosNext = 0, filePos = 0;
+
+  if (xIter != xEnd) {
+    xEmpty = false;
+    xPos = Languages.getPosition(xIter - xBegin);
+    cl::list<std::string>::const_iterator xNext = llvm::next(xIter);
+    xPosNext = (xNext == xEnd) ? std::numeric_limits<unsigned>::max()
+      : Languages.getPosition(xNext - xBegin);
+    xLanguage = (*xIter == "none") ? 0 : &(*xIter);
+  }
+
   // For each input file:
   for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
-        E = InputFilenames.end(); B != E; ++B) {
+         CB = B, E = InputFilenames.end(); B != E; ++B) {
     sys::Path In = sys::Path(*B);
 
+    // Code for handling the -x option.
+    // Output: std::string* xLanguage (can be NULL).
+    if (!xEmpty) {
+      filePos = InputFilenames.getPosition(B - CB);
+
+      if (xPos < filePos) {
+        if (filePos < xPosNext) {
+          xLanguage = (*xIter == "none") ? 0 : &(*xIter);
+        }
+        else { // filePos >= xPosNext
+          // Skip xIters while filePos > xPosNext
+          while (filePos > xPosNext) {
+            ++xIter;
+            xPos = xPosNext;
+
+            cl::list<std::string>::const_iterator xNext = llvm::next(xIter);
+            if (xNext == xEnd)
+              xPosNext = std::numeric_limits<unsigned>::max();
+            else
+              xPosNext = Languages.getPosition(xNext - xBegin);
+            xLanguage = (*xIter == "none") ? 0 : &(*xIter);
+          }
+        }
+      }
+    }
+
     // Find the toolchain corresponding to this file.
-    const Node* N = FindToolChain(In);
+    const Node* N = FindToolChain(In, xLanguage);
     // Pass file through the chain starting at head.
     PassThroughGraph(In, N, TempDir);
   }
index 72cde9a9e244b8bfaa858ffb00f7e1ddc79a911e..4692e5155d79f1361945d07cf57b33243959c357 100644 (file)
@@ -165,7 +165,8 @@ namespace llvmc {
                            const llvm::sys::Path& TempDir) const;
 
     // Find head of the toolchain corresponding to the given file.
-    const Node* FindToolChain(const llvm::sys::Path& In) const;
+    const Node* FindToolChain(const llvm::sys::Path& In,
+                              const std::string* forceLanguage) const;
 
     // Sort the nodes in topological order.
     void TopologicalSort(std::vector<const Node*>& Out);
index 64c59ffdeaf0b3c38a76cc0c31a6ba99e3e5ac83..897892415ebd2028bbf0ae6fa935a6567406bb07 100644 (file)
@@ -56,7 +56,7 @@ def llc : Tool<
 [(in_language "llvm-bitcode"),
  (out_language "assembler"),
  (output_suffix "s"),
- (cmd_line "llc $INFILE -o $OUTFILE")
+ (cmd_line "llc -f $INFILE -o $OUTFILE")
 ]>;
 
 def llvm_gcc_assembler : Tool<
@@ -68,6 +68,7 @@ def llvm_gcc_assembler : Tool<
  (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
 ]>;
 
+// Default linker
 def llvm_gcc_linker : Tool<
 [(in_language "object-code"),
  (out_language "executable"),
@@ -79,6 +80,21 @@ def llvm_gcc_linker : Tool<
  (prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
 ]>;
 
+// Alternative linker for C++
+// TOTHINK: how to implement this best?
+// Something like input_file_language can only choose between two languages.
+// def llvm_gcc_cpp_linker : Tool<
+// [(in_language "object-code"),
+//  (out_language "executable"),
+//  (output_suffix "out"),
+//  (cmd_line "llvm-g++ $INFILE -o $OUTFILE"),
+//  (join),
+//  //(input_file_language "c++"),
+//  (prefix_list_option "L", (forward)),
+//  (prefix_list_option "l", (forward)),
+//  (prefix_list_option "Wl", (unpack_values))
+// ]>;
+
 // Language map
 
 def LanguageMap : LanguageMap<
index b4f0afeb14e53b5d1333cdd40e588193b7fe2523..138c30691ac4f93a555502dff8b6acf3e8fd386d 100644 (file)
@@ -35,6 +35,9 @@ cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input file>"),
                                      cl::ZeroOrMore);
 cl::opt<std::string> OutputFilename("o", cl::desc("Output file name"),
                                     cl::value_desc("file"));
+cl::list<std::string> Languages("x",
+          cl::desc("Specify the language of the following input files"),
+          cl::ZeroOrMore);
 cl::opt<bool> VerboseMode("v",
                           cl::desc("Enable verbose mode"));
 cl::opt<bool> WriteGraph("write-graph",