Take object file as input and handle files with the same name correctly.
authorMikhail Glushenkov <foldr@codedgers.com>
Tue, 6 May 2008 18:10:20 +0000 (18:10 +0000)
committerMikhail Glushenkov <foldr@codedgers.com>
Tue, 6 May 2008 18:10:20 +0000 (18:10 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50749 91177308-0d34-0410-b5e6-96231b3b80d8

test/LLVMC/together.c [new file with mode: 0644]
test/LLVMC/together.cpp
test/LLVMC/together1.c [deleted file]
tools/llvmc2/Action.cpp
tools/llvmc2/CompilationGraph.cpp
tools/llvmc2/CompilationGraph.h
tools/llvmc2/Example.td
tools/llvmc2/Tools.td

diff --git a/test/LLVMC/together.c b/test/LLVMC/together.c
new file mode 100644 (file)
index 0000000..1b9b5f6
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * RUN: ignore
+ */
+
+#include <stdio.h>
+
+void test() {
+  printf("hello\n");
+}
index 62ff821154de16464fde2ce4ae1882f3b5d38af7..97df1937524608ac79e5c64560efbb393ce345e2 100644 (file)
@@ -1,6 +1,5 @@
 // Check that we can compile files of different types together.
-// TOFIX: compiling files with same names should work.
-// RUN: llvmc2 %s %p/together1.c -o %t
+// RUN: llvmc2 %s %p/together.c -o %t
 // RUN: ./%t | grep hello
 
 extern "C" void test();
diff --git a/test/LLVMC/together1.c b/test/LLVMC/together1.c
deleted file mode 100644 (file)
index 1b9b5f6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * RUN: ignore
- */
-
-#include <stdio.h>
-
-void test() {
-  printf("hello\n");
-}
index fdbfb886113c793f5a0c9ff68cbfefe4919beb59..3d61d37368ff7436af18011a464695b51bed5136 100644 (file)
@@ -34,6 +34,7 @@ namespace {
     if (!prog.canExecute())
       throw std::runtime_error("Program '" + name + "' is not executable.");
 
+    // Build the command line vector and redirects.
     const sys::Path* redirects[3] = {0,0,0};
     sys::Path stdout_redirect;
 
@@ -54,6 +55,7 @@ namespace {
     }
     argv.push_back(0);  // null terminate list.
 
+    // Invoke the program.
     return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
   }
 
index 817e0fb4c6b1ec5add4b616c622a70953ed9e002..ed03f5856ec544439f2feaf39aad72d62df19abc 100644 (file)
@@ -121,42 +121,50 @@ 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;
+}
+
 // Pass input file through the chain until we bump into a Join node or
 // a node that says that it is the last.
-const JoinTool*
-CompilationGraph::PassThroughGraph (sys::Path& In,
-                                    const Node* StartNode,
-                                    const sys::Path& TempDir) const {
+void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
+                                         const Node* StartNode,
+                                         const sys::Path& TempDir) const {
   bool Last = false;
+  sys::Path In = InFile;
   const Node* CurNode = StartNode;
-  JoinTool* ret = 0;
 
   while(!Last) {
     sys::Path Out;
     Tool* CurTool = CurNode->ToolPtr.getPtr();
 
     if (CurTool->IsJoin()) {
-      ret = &dynamic_cast<JoinTool&>(*CurTool);
-      ret->AddToJoinList(In);
+      JoinTool& JT = dynamic_cast<JoinTool&>(*CurTool);
+      JT.AddToJoinList(In);
       break;
     }
 
-    // Is this the last tool?
+    // Since toolchains do not have to end with a Join node, we should
+    // check if this Node is the last.
     if (!CurNode->HasChildren() || CurTool->IsLast()) {
-      // Check if the first tool is also the last
-      if (Out.empty())
+      if (!OutputFilename.empty()) {
+        Out.set(OutputFilename);
+      }
+      else {
         Out.set(In.getBasename());
-      else
-        Out.appendComponent(In.getBasename());
-      Out.appendSuffix(CurTool->OutputSuffix());
+        Out.appendSuffix(CurTool->OutputSuffix());
+      }
       Last = true;
     }
     else {
-      Out = TempDir;
-      Out.appendComponent(In.getBasename());
-      Out.appendSuffix(CurTool->OutputSuffix());
-      Out.makeUnique(true, NULL);
-      Out.eraseFromDisk();
+      Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
     }
 
     if (CurTool->GenerateAction(In, Out).Execute() != 0)
@@ -166,8 +174,6 @@ CompilationGraph::PassThroughGraph (sys::Path& In,
                                   CurNode->Name())->ToolName());
     In = Out; Out.clear();
   }
-
-  return ret;
 }
 
 // Sort the nodes in topological order.
@@ -215,7 +221,6 @@ const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
   return &getNode(ChooseEdge(TV)->ToolName());
 }
 
-// TOFIX: merge some parts with PassThroughGraph.
 // Build the targets. Command-line options are passed through
 // temporary variables.
 int CompilationGraph::Build (const sys::Path& TempDir) {
@@ -243,10 +248,12 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
     JoinTool* JT = &dynamic_cast<JoinTool&>(*CurNode->ToolPtr.getPtr());
     bool IsLast = false;
 
-    // Has files pending?
+    // Are there any files to be joined?
     if (JT->JoinListEmpty())
       continue;
 
+    // Is this the last tool in the chain?
+    // NOTE: we can process several chains in parallel.
     if (!CurNode->HasChildren() || JT->IsLast()) {
       if (OutputFilename.empty()) {
         Out.set("a");
@@ -257,11 +264,7 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
       IsLast = true;
     }
     else {
-      Out = TempDir;
-      Out.appendComponent("tmp");
-      Out.appendSuffix(JT->OutputSuffix());
-      Out.makeUnique(true, NULL);
-      Out.eraseFromDisk();
+      Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix());
     }
 
     if (JT->GenerateAction(Out).Execute() != 0)
index 7d949e6d4f4e2367ccb2d93982ae7006789199f2..72cde9a9e244b8bfaa858ffb00f7e1ddc79a911e 100644 (file)
@@ -28,7 +28,7 @@
 
 namespace llvmc {
 
-  // An edge in the graph.
+  // An edge of the compilation graph.
   class Edge : public llvm::RefCountedBaseVPTR<Edge> {
   public:
     Edge(const std::string& T) : ToolName_(T) {}
@@ -41,7 +41,7 @@ namespace llvmc {
     std::string ToolName_;
   };
 
-  // Edges with no properties are instances of this class.
+  // Edges that have no properties are instances of this class.
   class SimpleEdge : public Edge {
   public:
     SimpleEdge(const std::string& T) : Edge(T) {}
@@ -49,8 +49,9 @@ namespace llvmc {
     bool isDefault() const { return true;}
   };
 
-  // A node in the graph.
+  // A node of the compilation graph.
   struct Node {
+    // A Node holds a list of the outward edges.
     typedef llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> container_type;
     typedef container_type::iterator iterator;
     typedef container_type::const_iterator const_iterator;
@@ -74,10 +75,9 @@ namespace llvmc {
     void AddEdge(Edge* E)
     { OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(E)); }
 
-    // Inward edge counter. Used by Build() to implement topological
-    // sort.
-    // TOTHINK: Move the counter back into Tool classes? Makes us more
-    // const-correct.
+    // Inward edge counter. Used to implement topological sort.
+    // TOTHINK: Move the mutable counter back into Tool classes? Makes
+    // us more const-correct.
     void IncrInEdges() { ++InEdges; }
     void DecrInEdges() { --InEdges; }
     bool HasNoInEdges() const { return InEdges == 0; }
@@ -85,11 +85,12 @@ namespace llvmc {
     // Needed to implement NodeChildIterator/GraphTraits
     CompilationGraph* OwningGraph;
     // The corresponding Tool.
-    // WARNING: For the root node, ToolPtr is NULL.
+    // WARNING: ToolPtr can be NULL (for the root node).
     llvm::IntrusiveRefCntPtr<Tool> ToolPtr;
     // Links to children.
     container_type OutEdges;
-    // Number of parents. Used for topological sorting.
+    // Inward edge counter. Updated in
+    // CompilationGraph::insertEdge(). Used for topological sorting.
     unsigned InEdges;
   };
 
@@ -99,8 +100,9 @@ namespace llvmc {
   class CompilationGraph {
     // Main data structure.
     typedef llvm::StringMap<Node> nodes_map_type;
-    // These are used to map from language names-> tools. (We can have
-    // several tools associated with each language name.)
+    // These are used to map from language names to tools. (We can
+    // have several tools associated with each language name, hence
+    // the need for a vector of Edges.)
     typedef
     llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> tools_vector_type;
     typedef llvm::StringMap<tools_vector_type> tools_map_type;
@@ -159,9 +161,8 @@ namespace llvmc {
     const tools_vector_type& getToolsVector(const std::string& LangName) const;
 
     // Pass the input file through the toolchain.
-    const JoinTool* PassThroughGraph (llvm::sys::Path& In,
-                                      const Node* StartNode,
-                                      const llvm::sys::Path& TempDir) const;
+    void PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode,
+                           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;
index 82d9da1515deed98289896d446c2ff97a909dba8..57629904d18dca75424c8d75dd90da2a09f67ec5 100644 (file)
@@ -32,5 +32,7 @@ def CompilationGraph : CompilationGraph<[
     Edge<opt, llc>,
 
     Edge<llc, llvm_gcc_assembler>,
-    Edge<llvm_gcc_assembler, llvm_gcc_linker>
+    Edge<llvm_gcc_assembler, llvm_gcc_linker>,
+
+    Edge<root, llvm_gcc_linker>
     ]>;
index 67104ec2c7368f6af731e1d73b638c92306f6189..64c59ffdeaf0b3c38a76cc0c31a6ba99e3e5ac83 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-// Open issue: should we use DAG lists in Tool specifications
+// TOTHINK: Open issue: should we use DAG lists in Tool specifications
 // or change to something like
+
 // def LLVMGccC : < Tool<
 // [ InLanguage<"c">,
 //   PrefixListOption<"Wl", [UnpackValues, PropertyName<Arg>, ...]>
 //  ...] ?
+
 // DAG lists look more aesthetically pleasing to me.
 
 def llvm_gcc_c : Tool<
 [(in_language "c"),
  (out_language "llvm-bitcode"),
  (output_suffix "bc"),
- (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE -emit-llvm"),
+ (cmd_line "llvm-gcc -c -x c $INFILE -o $OUTFILE -emit-llvm"),
  (sink)
 ]>;
 
@@ -31,7 +33,7 @@ def llvm_gcc_cpp : Tool<
 [(in_language "c++"),
  (out_language "llvm-bitcode"),
  (output_suffix "bc"),
- (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
+ (cmd_line "llvm-g++ -c -x c++ $INFILE -o $OUTFILE -emit-llvm"),
  (sink)
 ]>;
 
@@ -61,7 +63,8 @@ def llvm_gcc_assembler : Tool<
 [(in_language "assembler"),
  (out_language "object-code"),
  (output_suffix "o"),
- (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE"),
+ (cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"),
+ (switch_option "c", (stop_compilation)),
  (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
 ]>;
 
@@ -85,4 +88,5 @@ def LanguageMap : LanguageMap<
      LangToSuffixes<"llvm-assembler", ["ll"]>,
      LangToSuffixes<"llvm-bitcode", ["bc"]>,
      LangToSuffixes<"object-code", ["o"]>,
-     LangToSuffixes<"executable", ["out"]>]>;
+     LangToSuffixes<"executable", ["out"]>
+     ]>;