correct an opcode
[oota-llvm.git] / lib / Support / ToolRunner.cpp
1 //===-- ToolRunner.cpp ----------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the interfaces described in the ToolRunner.h file.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "toolrunner"
15 #include "llvm/Support/ToolRunner.h"
16 #include "llvm/Config/config.h"   // for HAVE_LINK_R
17 #include "llvm/System/Program.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/FileUtilities.h"
20 #include <fstream>
21 #include <sstream>
22 #include <iostream>
23 using namespace llvm;
24
25 ToolExecutionError::~ToolExecutionError() throw() { }
26
27 /// RunProgramWithTimeout - This function provides an alternate interface to the
28 /// sys::Program::ExecuteAndWait interface.
29 /// @see sys:Program::ExecuteAndWait
30 static int RunProgramWithTimeout(const sys::Path &ProgramPath,
31                                  const char **Args,
32                                  const sys::Path &StdInFile,
33                                  const sys::Path &StdOutFile,
34                                  const sys::Path &StdErrFile,
35                                  unsigned NumSeconds = 0) {
36   const sys::Path* redirects[3];
37   redirects[0] = &StdInFile;
38   redirects[1] = &StdOutFile;
39   redirects[2] = &StdErrFile;
40
41   return
42     sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, NumSeconds);
43 }
44
45
46
47 static void ProcessFailure(sys::Path ProgPath, const char** Args) {
48   std::ostringstream OS;
49   OS << "\nError running tool:\n ";
50   for (const char **Arg = Args; *Arg; ++Arg)
51     OS << " " << *Arg;
52   OS << "\n";
53
54   // Rerun the compiler, capturing any error messages to print them.
55   sys::Path ErrorFilename("error_messages");
56   ErrorFilename.makeUnique();
57   RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
58                         ErrorFilename);
59
60   // Print out the error messages generated by GCC if possible...
61   std::ifstream ErrorFile(ErrorFilename.c_str());
62   if (ErrorFile) {
63     std::copy(std::istreambuf_iterator<char>(ErrorFile),
64               std::istreambuf_iterator<char>(),
65               std::ostreambuf_iterator<char>(OS));
66     ErrorFile.close();
67   }
68
69   ErrorFilename.eraseFromDisk();
70   throw ToolExecutionError(OS.str());
71 }
72
73 //===---------------------------------------------------------------------===//
74 // LLI Implementation of AbstractIntepreter interface
75 //
76 namespace {
77   class LLI : public AbstractInterpreter {
78     std::string LLIPath;          // The path to the LLI executable
79     std::vector<std::string> ToolArgs; // Args to pass to LLI
80   public:
81     LLI(const std::string &Path, const std::vector<std::string> *Args)
82       : LLIPath(Path) {
83       ToolArgs.clear ();
84       if (Args) { ToolArgs = *Args; }
85     }
86
87     virtual int ExecuteProgram(const std::string &Bytecode,
88                                const std::vector<std::string> &Args,
89                                const std::string &InputFile,
90                                const std::string &OutputFile,
91                                const std::vector<std::string> &SharedLibs =
92                                std::vector<std::string>(),
93                                unsigned Timeout = 0);
94   };
95 }
96
97 int LLI::ExecuteProgram(const std::string &Bytecode,
98                         const std::vector<std::string> &Args,
99                         const std::string &InputFile,
100                         const std::string &OutputFile,
101                         const std::vector<std::string> &SharedLibs,
102                         unsigned Timeout) {
103   if (!SharedLibs.empty())
104     throw ToolExecutionError("LLI currently does not support "
105                              "loading shared libraries.");
106
107   std::vector<const char*> LLIArgs;
108   LLIArgs.push_back(LLIPath.c_str());
109   LLIArgs.push_back("-force-interpreter=true");
110
111   // Add any extra LLI args.
112   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
113     LLIArgs.push_back(ToolArgs[i].c_str());
114
115   LLIArgs.push_back(Bytecode.c_str());
116   // Add optional parameters to the running program from Argv
117   for (unsigned i=0, e = Args.size(); i != e; ++i)
118     LLIArgs.push_back(Args[i].c_str());
119   LLIArgs.push_back(0);
120
121   std::cout << "<lli>" << std::flush;
122   DEBUG(std::cerr << "\nAbout to run:\t";
123         for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
124           std::cerr << " " << LLIArgs[i];
125         std::cerr << "\n";
126         );
127   return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
128       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
129       Timeout);
130 }
131
132 // LLI create method - Try to find the LLI executable
133 AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
134                                                     std::string &Message,
135                                      const std::vector<std::string> *ToolArgs) {
136   std::string LLIPath = FindExecutable("lli", ProgPath).toString();
137   if (!LLIPath.empty()) {
138     Message = "Found lli: " + LLIPath + "\n";
139     return new LLI(LLIPath, ToolArgs);
140   }
141
142   Message = "Cannot find `lli' in executable directory or PATH!\n";
143   return 0;
144 }
145
146 //===----------------------------------------------------------------------===//
147 // LLC Implementation of AbstractIntepreter interface
148 //
149 void LLC::OutputAsm(const std::string &Bytecode, sys::Path &OutputAsmFile) {
150   sys::Path uniqueFile(Bytecode+".llc.s");
151   uniqueFile.makeUnique();
152   OutputAsmFile = uniqueFile;
153   std::vector<const char *> LLCArgs;
154   LLCArgs.push_back (LLCPath.c_str());
155
156   // Add any extra LLC args.
157   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
158     LLCArgs.push_back(ToolArgs[i].c_str());
159
160   LLCArgs.push_back ("-o");
161   LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
162   LLCArgs.push_back ("-f");                  // Overwrite as necessary...
163   LLCArgs.push_back (Bytecode.c_str());      // This is the input bytecode
164   LLCArgs.push_back (0);
165
166   std::cout << "<llc>" << std::flush;
167   DEBUG(std::cerr << "\nAbout to run:\t";
168         for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
169           std::cerr << " " << LLCArgs[i];
170         std::cerr << "\n";
171         );
172   if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
173                             sys::Path(), sys::Path(), sys::Path()))
174     ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
175 }
176
177 void LLC::compileProgram(const std::string &Bytecode) {
178   sys::Path OutputAsmFile;
179   OutputAsm(Bytecode, OutputAsmFile);
180   OutputAsmFile.eraseFromDisk();
181 }
182
183 int LLC::ExecuteProgram(const std::string &Bytecode,
184                         const std::vector<std::string> &Args,
185                         const std::string &InputFile,
186                         const std::string &OutputFile,
187                         const std::vector<std::string> &SharedLibs,
188                         unsigned Timeout) {
189
190   sys::Path OutputAsmFile;
191   OutputAsm(Bytecode, OutputAsmFile);
192   FileRemover OutFileRemover(OutputAsmFile);
193
194   // Assuming LLC worked, compile the result with GCC and run it.
195   return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
196                              InputFile, OutputFile, SharedLibs, Timeout);
197 }
198
199 /// createLLC - Try to find the LLC executable
200 ///
201 LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
202                                     std::string &Message,
203                                     const std::vector<std::string> *Args) {
204   std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
205   if (LLCPath.empty()) {
206     Message = "Cannot find `llc' in executable directory or PATH!\n";
207     return 0;
208   }
209
210   Message = "Found llc: " + LLCPath + "\n";
211   GCC *gcc = GCC::create(ProgramPath, Message);
212   if (!gcc) {
213     std::cerr << Message << "\n";
214     exit(1);
215   }
216   return new LLC(LLCPath, gcc, Args);
217 }
218
219 //===---------------------------------------------------------------------===//
220 // JIT Implementation of AbstractIntepreter interface
221 //
222 namespace {
223   class JIT : public AbstractInterpreter {
224     std::string LLIPath;          // The path to the LLI executable
225     std::vector<std::string> ToolArgs; // Args to pass to LLI
226   public:
227     JIT(const std::string &Path, const std::vector<std::string> *Args)
228       : LLIPath(Path) {
229       ToolArgs.clear ();
230       if (Args) { ToolArgs = *Args; }
231     }
232
233     virtual int ExecuteProgram(const std::string &Bytecode,
234                                const std::vector<std::string> &Args,
235                                const std::string &InputFile,
236                                const std::string &OutputFile,
237                                const std::vector<std::string> &SharedLibs =
238                                std::vector<std::string>(), unsigned Timeout =0);
239   };
240 }
241
242 int JIT::ExecuteProgram(const std::string &Bytecode,
243                         const std::vector<std::string> &Args,
244                         const std::string &InputFile,
245                         const std::string &OutputFile,
246                         const std::vector<std::string> &SharedLibs,
247                         unsigned Timeout) {
248   // Construct a vector of parameters, incorporating those from the command-line
249   std::vector<const char*> JITArgs;
250   JITArgs.push_back(LLIPath.c_str());
251   JITArgs.push_back("-force-interpreter=false");
252
253   // Add any extra LLI args.
254   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
255     JITArgs.push_back(ToolArgs[i].c_str());
256
257   for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
258     JITArgs.push_back("-load");
259     JITArgs.push_back(SharedLibs[i].c_str());
260   }
261   JITArgs.push_back(Bytecode.c_str());
262   // Add optional parameters to the running program from Argv
263   for (unsigned i=0, e = Args.size(); i != e; ++i)
264     JITArgs.push_back(Args[i].c_str());
265   JITArgs.push_back(0);
266
267   std::cout << "<jit>" << std::flush;
268   DEBUG(std::cerr << "\nAbout to run:\t";
269         for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
270           std::cerr << " " << JITArgs[i];
271         std::cerr << "\n";
272         );
273   DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
274   return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
275       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
276       Timeout);
277 }
278
279 /// createJIT - Try to find the LLI executable
280 ///
281 AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
282                    std::string &Message, const std::vector<std::string> *Args) {
283   std::string LLIPath = FindExecutable("lli", ProgPath).toString();
284   if (!LLIPath.empty()) {
285     Message = "Found lli: " + LLIPath + "\n";
286     return new JIT(LLIPath, Args);
287   }
288
289   Message = "Cannot find `lli' in executable directory or PATH!\n";
290   return 0;
291 }
292
293 void CBE::OutputC(const std::string &Bytecode, sys::Path& OutputCFile) {
294   sys::Path uniqueFile(Bytecode+".cbe.c");
295   uniqueFile.makeUnique();
296   OutputCFile = uniqueFile;
297   std::vector<const char *> LLCArgs;
298   LLCArgs.push_back (LLCPath.c_str());
299
300   // Add any extra LLC args.
301   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
302     LLCArgs.push_back(ToolArgs[i].c_str());
303
304   LLCArgs.push_back ("-o");
305   LLCArgs.push_back (OutputCFile.c_str());   // Output to the C file
306   LLCArgs.push_back ("-march=c");            // Output C language
307   LLCArgs.push_back ("-f");                  // Overwrite as necessary...
308   LLCArgs.push_back (Bytecode.c_str());      // This is the input bytecode
309   LLCArgs.push_back (0);
310
311   std::cout << "<cbe>" << std::flush;
312   DEBUG(std::cerr << "\nAbout to run:\t";
313         for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
314           std::cerr << " " << LLCArgs[i];
315         std::cerr << "\n";
316         );
317   if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
318                             sys::Path()))
319     ProcessFailure(LLCPath, &LLCArgs[0]);
320 }
321
322 void CBE::compileProgram(const std::string &Bytecode) {
323   sys::Path OutputCFile;
324   OutputC(Bytecode, OutputCFile);
325   OutputCFile.eraseFromDisk();
326 }
327
328 int CBE::ExecuteProgram(const std::string &Bytecode,
329                         const std::vector<std::string> &Args,
330                         const std::string &InputFile,
331                         const std::string &OutputFile,
332                         const std::vector<std::string> &SharedLibs,
333                         unsigned Timeout) {
334   sys::Path OutputCFile;
335   OutputC(Bytecode, OutputCFile);
336
337   FileRemover CFileRemove(OutputCFile);
338
339   return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
340                              InputFile, OutputFile, SharedLibs, Timeout);
341 }
342
343 /// createCBE - Try to find the 'llc' executable
344 ///
345 CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
346                                     std::string &Message,
347                                     const std::vector<std::string> *Args) {
348   sys::Path LLCPath = FindExecutable("llc", ProgramPath);
349   if (LLCPath.isEmpty()) {
350     Message =
351       "Cannot find `llc' in executable directory or PATH!\n";
352     return 0;
353   }
354
355   Message = "Found llc: " + LLCPath.toString() + "\n";
356   GCC *gcc = GCC::create(ProgramPath, Message);
357   if (!gcc) {
358     std::cerr << Message << "\n";
359     exit(1);
360   }
361   return new CBE(LLCPath, gcc, Args);
362 }
363
364 //===---------------------------------------------------------------------===//
365 // GCC abstraction
366 //
367 int GCC::ExecuteProgram(const std::string &ProgramFile,
368                         const std::vector<std::string> &Args,
369                         FileType fileType,
370                         const std::string &InputFile,
371                         const std::string &OutputFile,
372                         const std::vector<std::string> &SharedLibs,
373                         unsigned Timeout) {
374   std::vector<const char*> GCCArgs;
375
376   GCCArgs.push_back(GCCPath.c_str());
377
378   // Specify the shared libraries to link in...
379   for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i)
380     GCCArgs.push_back(SharedLibs[i].c_str());
381
382   // Specify -x explicitly in case the extension is wonky
383   GCCArgs.push_back("-x");
384   if (fileType == CFile) {
385     GCCArgs.push_back("c");
386     GCCArgs.push_back("-fno-strict-aliasing");
387   } else {
388     GCCArgs.push_back("assembler");
389 #ifdef __APPLE__
390     GCCArgs.push_back("-force_cpusubtype_ALL");
391 #endif
392   }
393   GCCArgs.push_back(ProgramFile.c_str());  // Specify the input filename...
394   GCCArgs.push_back("-o");
395   sys::Path OutputBinary (ProgramFile+".gcc.exe");
396   OutputBinary.makeUnique();
397   GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
398   GCCArgs.push_back("-lm");                // Hard-code the math library...
399   GCCArgs.push_back("-O2");                // Optimize the program a bit...
400 #if defined (HAVE_LINK_R)
401   GCCArgs.push_back("-Wl,-R.");            // Search this dir for .so files
402 #endif
403   GCCArgs.push_back(0);                    // NULL terminator
404
405   std::cout << "<gcc>" << std::flush;
406   if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
407         sys::Path())) {
408     ProcessFailure(GCCPath, &GCCArgs[0]);
409     exit(1);
410   }
411
412   std::vector<const char*> ProgramArgs;
413
414   ProgramArgs.push_back(OutputBinary.c_str());
415   // Add optional parameters to the running program from Argv
416   for (unsigned i=0, e = Args.size(); i != e; ++i)
417     ProgramArgs.push_back(Args[i].c_str());
418   ProgramArgs.push_back(0);                // NULL terminator
419
420   // Now that we have a binary, run it!
421   std::cout << "<program>" << std::flush;
422   DEBUG(std::cerr << "\nAbout to run:\t";
423         for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
424           std::cerr << " " << ProgramArgs[i];
425         std::cerr << "\n";
426         );
427
428   FileRemover OutputBinaryRemover(OutputBinary);
429   return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
430       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
431       Timeout);
432 }
433
434 int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
435                           std::string &OutputFile) {
436   sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
437   uniqueFilename.makeUnique();
438   OutputFile = uniqueFilename.toString();
439
440   // Compile the C/asm file into a shared object
441   const char* GCCArgs[] = {
442     GCCPath.c_str(),
443     "-x", (fileType == AsmFile) ? "assembler" : "c",
444     "-fno-strict-aliasing",
445     InputFile.c_str(),           // Specify the input filename...
446 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
447     "-G",                        // Compile a shared library, `-G' for Sparc
448 #elif defined(__APPLE__)
449     "-single_module",            // link all source files into a single module
450     "-dynamiclib",               // `-dynamiclib' for MacOS X/PowerPC
451     "-undefined",                // in data segment, rather than generating
452     "dynamic_lookup",            // blocks. dynamic_lookup requires that you set
453                                  // MACOSX_DEPLOYMENT_TARGET=10.3 in your env.
454 #else
455     "-shared",                   // `-shared' for Linux/X86, maybe others
456 #endif
457
458 #if defined(__ia64__) || defined(__alpha__)
459     "-fPIC",                     // IA64 requires shared objs to contain PIC
460 #endif
461     "-o", OutputFile.c_str(),    // Output to the right filename...
462     "-O2",                       // Optimize the program a bit...
463     0
464   };
465
466   std::cout << "<gcc>" << std::flush;
467   if (RunProgramWithTimeout(GCCPath, GCCArgs, sys::Path(), sys::Path(),
468                             sys::Path())) {
469     ProcessFailure(GCCPath, GCCArgs);
470     return 1;
471   }
472   return 0;
473 }
474
475 /// create - Try to find the `gcc' executable
476 ///
477 GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {
478   sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
479   if (GCCPath.isEmpty()) {
480     Message = "Cannot find `gcc' in executable directory or PATH!\n";
481     return 0;
482   }
483
484   Message = "Found gcc: " + GCCPath.toString() + "\n";
485   return new GCC(GCCPath);
486 }