llvm.org GIT mirror llvm / 87416b4
Add -x option (like in gcc). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50750 91177308-0d34-0410-b5e6-96231b3b80d8 Mikhail Glushenkov 12 years ago
5 changed file(s) with 93 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
3333 if (!prog.canExecute())
3434 throw std::runtime_error("Program '" + name + "' is not executable.");
3535
36 // Build the command line vector and redirects.
36 // Build the command line vector and the redirects array.
3737 const sys::Path* redirects[3] = {0,0,0};
3838 sys::Path stdout_redirect;
3939
1212
1313 #include "CompilationGraph.h"
1414
15 #include "llvm/ADT/STLExtras.h"
1516 #include "llvm/Support/CommandLine.h"
1617 #include "llvm/Support/DOTGraphTraits.h"
1718 #include "llvm/Support/GraphWriter.h"
1819
1920 #include
20 #include
2121 #include
22 #include
2223 #include
2324 #include
2425
2728
2829 extern cl::list InputFilenames;
2930 extern cl::opt OutputFilename;
31 extern cl::list Languages;
3032
3133 namespace {
3234
33 // Choose edge that returns
35 // Go through the list C and find the edge that isEnabled(); if
36 // there is no such edge, return the default edge; if there is no
37 // default edge, throw an exception.
3438 template
3539 const Edge* ChooseEdge(const C& EdgesContainer,
3640 const std::string& NodeName = "root") {
4650 else
4751 throw std::runtime_error("Node " + NodeName
4852 + ": multiple default outward edges found!"
49 "Most probably a specification error.");
53 " Most probably a specification error.");
5054 if (E->isEnabled())
5155 return E;
5256 }
5660 else
5761 throw std::runtime_error("Node " + NodeName
5862 + ": no default outward edge found!"
59 "Most probably a specification error.");
63 " Most probably a specification error.");
6064 }
6165
6266 }
9195 {
9296 tools_map_type::const_iterator I = ToolsMap.find(LangName);
9397 if (I == ToolsMap.end())
94 throw std::runtime_error("No tools corresponding to " + LangName
95 + " found!");
98 throw std::runtime_error("No tool corresponding to the language "
99 + LangName + "found!");
96100 return I->second;
97101 }
98102
120124 B.IncrInEdges();
121125 }
122126
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;
127 namespace {
128 sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
129 const std::string& Suffix) {
130 sys::Path Out = TempDir;
131 Out.appendComponent(BaseName);
132 Out.appendSuffix(Suffix);
133 Out.makeUnique(true, NULL);
134 return Out;
135 }
132136 }
133137
134138 // Pass input file through the chain until we bump into a Join node or
169173 if (CurTool->GenerateAction(In, Out).Execute() != 0)
170174 throw std::runtime_error("Tool returned error code!");
171175
176 if (Last)
177 return;
178
172179 CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
173180 CurNode->Name())->ToolName());
174181 In = Out; Out.clear();
211218 }
212219
213220 // Find head of the toolchain corresponding to the given file.
214 const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
215 const std::string& InLanguage = getLanguage(In);
221 const Node* CompilationGraph::
222 FindToolChain(const sys::Path& In, const std::string* forceLanguage) const {
223 const std::string& InLanguage =
224 forceLanguage ? *forceLanguage : getLanguage(In);
216225 const tools_vector_type& TV = getToolsVector(InLanguage);
217226 if (TV.empty())
218227 throw std::runtime_error("No toolchain corresponding to language"
224233 // temporary variables.
225234 int CompilationGraph::Build (const sys::Path& TempDir) {
226235
236 // This is related to -x option handling.
237 cl::list::const_iterator xIter = Languages.begin(),
238 xBegin = xIter, xEnd = Languages.end();
239 bool xEmpty = true;
240 const std::string* xLanguage = 0;
241 unsigned xPos = 0, xPosNext = 0, filePos = 0;
242
243 if (xIter != xEnd) {
244 xEmpty = false;
245 xPos = Languages.getPosition(xIter - xBegin);
246 cl::list::const_iterator xNext = llvm::next(xIter);
247 xPosNext = (xNext == xEnd) ? std::numeric_limits::max()
248 : Languages.getPosition(xNext - xBegin);
249 xLanguage = (*xIter == "none") ? 0 : &(*xIter);
250 }
251
227252 // For each input file:
228253 for (cl::list::const_iterator B = InputFilenames.begin(),
229 E = InputFilenames.end(); B != E; ++B) {
254 CB = B, E = InputFilenames.end(); B != E; ++B) {
230255 sys::Path In = sys::Path(*B);
231256
257 // Code for handling the -x option.
258 // Output: std::string* xLanguage (can be NULL).
259 if (!xEmpty) {
260 filePos = InputFilenames.getPosition(B - CB);
261
262 if (xPos < filePos) {
263 if (filePos < xPosNext) {
264 xLanguage = (*xIter == "none") ? 0 : &(*xIter);
265 }
266 else { // filePos >= xPosNext
267 // Skip xIters while filePos > xPosNext
268 while (filePos > xPosNext) {
269 ++xIter;
270 xPos = xPosNext;
271
272 cl::list::const_iterator xNext = llvm::next(xIter);
273 if (xNext == xEnd)
274 xPosNext = std::numeric_limits::max();
275 else
276 xPosNext = Languages.getPosition(xNext - xBegin);
277 xLanguage = (*xIter == "none") ? 0 : &(*xIter);
278 }
279 }
280 }
281 }
282
232283 // Find the toolchain corresponding to this file.
233 const Node* N = FindToolChain(In);
284 const Node* N = FindToolChain(In, xLanguage);
234285 // Pass file through the chain starting at head.
235286 PassThroughGraph(In, N, TempDir);
236287 }
164164 const llvm::sys::Path& TempDir) const;
165165
166166 // Find head of the toolchain corresponding to the given file.
167 const Node* FindToolChain(const llvm::sys::Path& In) const;
167 const Node* FindToolChain(const llvm::sys::Path& In,
168 const std::string* forceLanguage) const;
168169
169170 // Sort the nodes in topological order.
170171 void TopologicalSort(std::vector& Out);
5555 [(in_language "llvm-bitcode"),
5656 (out_language "assembler"),
5757 (output_suffix "s"),
58 (cmd_line "llc $INFILE -o $OUTFILE")
58 (cmd_line "llc -f $INFILE -o $OUTFILE")
5959 ]>;
6060
6161 def llvm_gcc_assembler : Tool<
6767 (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
6868 ]>;
6969
70 // Default linker
7071 def llvm_gcc_linker : Tool<
7172 [(in_language "object-code"),
7273 (out_language "executable"),
7778 (prefix_list_option "l", (forward), (help "search a library when linking")),
7879 (prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
7980 ]>;
81
82 // Alternative linker for C++
83 // TOTHINK: how to implement this best?
84 // Something like input_file_language can only choose between two languages.
85 // def llvm_gcc_cpp_linker : Tool<
86 // [(in_language "object-code"),
87 // (out_language "executable"),
88 // (output_suffix "out"),
89 // (cmd_line "llvm-g++ $INFILE -o $OUTFILE"),
90 // (join),
91 // //(input_file_language "c++"),
92 // (prefix_list_option "L", (forward)),
93 // (prefix_list_option "l", (forward)),
94 // (prefix_list_option "Wl", (unpack_values))
95 // ]>;
8096
8197 // Language map
8298
3434 cl::ZeroOrMore);
3535 cl::opt OutputFilename("o", cl::desc("Output file name"),
3636 cl::value_desc("file"));
37 cl::list Languages("x",
38 cl::desc("Specify the language of the following input files"),
39 cl::ZeroOrMore);
3740 cl::opt VerboseMode("v",
3841 cl::desc("Enable verbose mode"));
3942 cl::opt WriteGraph("write-graph",