llvm.org GIT mirror llvm / 35a85e8
Take object file as input and handle files with the same name correctly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50749 91177308-0d34-0410-b5e6-96231b3b80d8 Mikhail Glushenkov 12 years ago
8 changed file(s) with 69 addition(s) and 58 deletion(s). Raw diff Collapse all Expand all
0 /*
1 * RUN: ignore
2 */
3
4 #include
5
6 void test() {
7 printf("hello\n");
8 }
0 // Check that we can compile files of different types together.
1 // TOFIX: compiling files with same names should work.
2 // RUN: llvmc2 %s %p/together1.c -o %t
1 // RUN: llvmc2 %s %p/together.c -o %t
32 // RUN: ./%t | grep hello
43
54 extern "C" void test();
+0
-9
test/LLVMC/together1.c less more
None /*
1 * RUN: ignore
2 */
3
4 #include
5
6 void test() {
7 printf("hello\n");
8 }
3333 if (!prog.canExecute())
3434 throw std::runtime_error("Program '" + name + "' is not executable.");
3535
36 // Build the command line vector and redirects.
3637 const sys::Path* redirects[3] = {0,0,0};
3738 sys::Path stdout_redirect;
3839
5354 }
5455 argv.push_back(0); // null terminate list.
5556
57 // Invoke the program.
5658 return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
5759 }
5860
120120 B.IncrInEdges();
121121 }
122122
123 // Make a temporary file named like BaseName-RandomDigits.Suffix
124 sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
125 const std::string& Suffix) {
126 sys::Path Out = TempDir;
127 Out.appendComponent(BaseName);
128 Out.appendSuffix(Suffix);
129 Out.makeUnique(true, NULL);
130 Out.eraseFromDisk();
131 return Out;
132 }
133
123134 // Pass input file through the chain until we bump into a Join node or
124135 // a node that says that it is the last.
125 const JoinTool*
126 CompilationGraph::PassThroughGraph (sys::Path& In,
127 const Node* StartNode,
128 const sys::Path& TempDir) const {
136 void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
137 const Node* StartNode,
138 const sys::Path& TempDir) const {
129139 bool Last = false;
140 sys::Path In = InFile;
130141 const Node* CurNode = StartNode;
131 JoinTool* ret = 0;
132142
133143 while(!Last) {
134144 sys::Path Out;
135145 Tool* CurTool = CurNode->ToolPtr.getPtr();
136146
137147 if (CurTool->IsJoin()) {
138 ret = &dynamic_cast(*CurTool);
139 ret->AddToJoinList(In);
148 JoinTool& JT = dynamic_cast(*CurTool);
149 JT.AddToJoinList(In);
140150 break;
141151 }
142152
143 // Is this the last tool?
153 // Since toolchains do not have to end with a Join node, we should
154 // check if this Node is the last.
144155 if (!CurNode->HasChildren() || CurTool->IsLast()) {
145 // Check if the first tool is also the last
146 if (Out.empty())
156 if (!OutputFilename.empty()) {
157 Out.set(OutputFilename);
158 }
159 else {
147160 Out.set(In.getBasename());
148 else
149 Out.appendComponent(In.getBasename());
150 Out.appendSuffix(CurTool->OutputSuffix());
161 Out.appendSuffix(CurTool->OutputSuffix());
162 }
151163 Last = true;
152164 }
153165 else {
154 Out = TempDir;
155 Out.appendComponent(In.getBasename());
156 Out.appendSuffix(CurTool->OutputSuffix());
157 Out.makeUnique(true, NULL);
158 Out.eraseFromDisk();
166 Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
159167 }
160168
161169 if (CurTool->GenerateAction(In, Out).Execute() != 0)
165173 CurNode->Name())->ToolName());
166174 In = Out; Out.clear();
167175 }
168
169 return ret;
170176 }
171177
172178 // Sort the nodes in topological order.
214220 return &getNode(ChooseEdge(TV)->ToolName());
215221 }
216222
217 // TOFIX: merge some parts with PassThroughGraph.
218223 // Build the targets. Command-line options are passed through
219224 // temporary variables.
220225 int CompilationGraph::Build (const sys::Path& TempDir) {
242247 JoinTool* JT = &dynamic_cast(*CurNode->ToolPtr.getPtr());
243248 bool IsLast = false;
244249
245 // Has files pending?
250 // Are there any files to be joined?
246251 if (JT->JoinListEmpty())
247252 continue;
248253
254 // Is this the last tool in the chain?
255 // NOTE: we can process several chains in parallel.
249256 if (!CurNode->HasChildren() || JT->IsLast()) {
250257 if (OutputFilename.empty()) {
251258 Out.set("a");
256263 IsLast = true;
257264 }
258265 else {
259 Out = TempDir;
260 Out.appendComponent("tmp");
261 Out.appendSuffix(JT->OutputSuffix());
262 Out.makeUnique(true, NULL);
263 Out.eraseFromDisk();
266 Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix());
264267 }
265268
266269 if (JT->GenerateAction(Out).Execute() != 0)
2727
2828 namespace llvmc {
2929
30 // An edge in the graph.
30 // An edge of the compilation graph.
3131 class Edge : public llvm::RefCountedBaseVPTR {
3232 public:
3333 Edge(const std::string& T) : ToolName_(T) {}
4040 std::string ToolName_;
4141 };
4242
43 // Edges with no properties are instances of this class.
43 // Edges that have no properties are instances of this class.
4444 class SimpleEdge : public Edge {
4545 public:
4646 SimpleEdge(const std::string& T) : Edge(T) {}
4848 bool isDefault() const { return true;}
4949 };
5050
51 // A node in the graph.
51 // A node of the compilation graph.
5252 struct Node {
53 // A Node holds a list of the outward edges.
5354 typedef llvm::SmallVector, 3> container_type;
5455 typedef container_type::iterator iterator;
5556 typedef container_type::const_iterator const_iterator;
7374 void AddEdge(Edge* E)
7475 { OutEdges.push_back(llvm::IntrusiveRefCntPtr(E)); }
7576
76 // Inward edge counter. Used by Build() to implement topological
77 // sort.
78 // TOTHINK: Move the counter back into Tool classes? Makes us more
79 // const-correct.
77 // Inward edge counter. Used to implement topological sort.
78 // TOTHINK: Move the mutable counter back into Tool classes? Makes
79 // us more const-correct.
8080 void IncrInEdges() { ++InEdges; }
8181 void DecrInEdges() { --InEdges; }
8282 bool HasNoInEdges() const { return InEdges == 0; }
8484 // Needed to implement NodeChildIterator/GraphTraits
8585 CompilationGraph* OwningGraph;
8686 // The corresponding Tool.
87 // WARNING: For the root node, ToolPtr is NULL.
87 // WARNING: ToolPtr can be NULL (for the root node).
8888 llvm::IntrusiveRefCntPtr ToolPtr;
8989 // Links to children.
9090 container_type OutEdges;
91 // Number of parents. Used for topological sorting.
91 // Inward edge counter. Updated in
92 // CompilationGraph::insertEdge(). Used for topological sorting.
9293 unsigned InEdges;
9394 };
9495
9899 class CompilationGraph {
99100 // Main data structure.
100101 typedef llvm::StringMap nodes_map_type;
101 // These are used to map from language names-> tools. (We can have
102 // several tools associated with each language name.)
102 // These are used to map from language names to tools. (We can
103 // have several tools associated with each language name, hence
104 // the need for a vector of Edges.)
103105 typedef
104106 llvm::SmallVector, 3> tools_vector_type;
105107 typedef llvm::StringMap tools_map_type;
158160 const tools_vector_type& getToolsVector(const std::string& LangName) const;
159161
160162 // Pass the input file through the toolchain.
161 const JoinTool* PassThroughGraph (llvm::sys::Path& In,
162 const Node* StartNode,
163 const llvm::sys::Path& TempDir) const;
163 void PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode,
164 const llvm::sys::Path& TempDir) const;
164165
165166 // Find head of the toolchain corresponding to the given file.
166167 const Node* FindToolChain(const llvm::sys::Path& In) const;
3131 Edge,
3232
3333 Edge,
34 Edge
34 Edge,
35
36 Edge
3537 ]>;
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 // Open issue: should we use DAG lists in Tool specifications
13 // TOTHINK: Open issue: should we use DAG lists in Tool specifications
1414 // or change to something like
15
1516 // def LLVMGccC : < Tool<
1617 // [ InLanguage<"c">,
1718 // PrefixListOption<"Wl", [UnpackValues, PropertyName, ...]>
1819 // ...] ?
20
1921 // DAG lists look more aesthetically pleasing to me.
2022
2123 def llvm_gcc_c : Tool<
2224 [(in_language "c"),
2325 (out_language "llvm-bitcode"),
2426 (output_suffix "bc"),
25 (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE -emit-llvm"),
27 (cmd_line "llvm-gcc -c -x c $INFILE -o $OUTFILE -emit-llvm"),
2628 (sink)
2729 ]>;
2830
3032 [(in_language "c++"),
3133 (out_language "llvm-bitcode"),
3234 (output_suffix "bc"),
33 (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
35 (cmd_line "llvm-g++ -c -x c++ $INFILE -o $OUTFILE -emit-llvm"),
3436 (sink)
3537 ]>;
3638
6062 [(in_language "assembler"),
6163 (out_language "object-code"),
6264 (output_suffix "o"),
63 (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE"),
65 (cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"),
66 (switch_option "c", (stop_compilation)),
6467 (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
6568 ]>;
6669
8487 LangToSuffixes<"llvm-assembler", ["ll"]>,
8588 LangToSuffixes<"llvm-bitcode", ["bc"]>,
8689 LangToSuffixes<"object-code", ["o"]>,
87 LangToSuffixes<"executable", ["out"]>]>;
90 LangToSuffixes<"executable", ["out"]>
91 ]>;