Move ToolRunner.(cpp|h) into the bugpoint directory
[oota-llvm.git] / tools / bugpoint / 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 "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> &GCCArgs,
92                                const std::vector<std::string> &SharedLibs =
93                                std::vector<std::string>(),
94                                unsigned Timeout = 0);
95   };
96 }
97
98 int LLI::ExecuteProgram(const std::string &Bytecode,
99                         const std::vector<std::string> &Args,
100                         const std::string &InputFile,
101                         const std::string &OutputFile,
102                         const std::vector<std::string> &GCCArgs,
103                         const std::vector<std::string> &SharedLibs,
104                         unsigned Timeout) {
105   if (!SharedLibs.empty())
106     throw ToolExecutionError("LLI currently does not support "
107                              "loading shared libraries.");
108
109   if (!GCCArgs.empty())
110     throw ToolExecutionError("LLI currently does not support "
111                              "GCC Arguments.");
112   std::vector<const char*> LLIArgs;
113   LLIArgs.push_back(LLIPath.c_str());
114   LLIArgs.push_back("-force-interpreter=true");
115
116   // Add any extra LLI args.
117   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
118     LLIArgs.push_back(ToolArgs[i].c_str());
119
120   LLIArgs.push_back(Bytecode.c_str());
121   // Add optional parameters to the running program from Argv
122   for (unsigned i=0, e = Args.size(); i != e; ++i)
123     LLIArgs.push_back(Args[i].c_str());
124   LLIArgs.push_back(0);
125
126   std::cout << "<lli>" << std::flush;
127   DEBUG(std::cerr << "\nAbout to run:\t";
128         for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
129           std::cerr << " " << LLIArgs[i];
130         std::cerr << "\n";
131         );
132   return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
133       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
134       Timeout);
135 }
136
137 // LLI create method - Try to find the LLI executable
138 AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
139                                                     std::string &Message,
140                                      const std::vector<std::string> *ToolArgs) {
141   std::string LLIPath = FindExecutable("lli", ProgPath).toString();
142   if (!LLIPath.empty()) {
143     Message = "Found lli: " + LLIPath + "\n";
144     return new LLI(LLIPath, ToolArgs);
145   }
146
147   Message = "Cannot find `lli' in executable directory or PATH!\n";
148   return 0;
149 }
150
151 //===----------------------------------------------------------------------===//
152 // LLC Implementation of AbstractIntepreter interface
153 //
154 void LLC::OutputAsm(const std::string &Bytecode, sys::Path &OutputAsmFile) {
155   sys::Path uniqueFile(Bytecode+".llc.s");
156   uniqueFile.makeUnique();
157   OutputAsmFile = uniqueFile;
158   std::vector<const char *> LLCArgs;
159   LLCArgs.push_back (LLCPath.c_str());
160
161   // Add any extra LLC args.
162   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
163     LLCArgs.push_back(ToolArgs[i].c_str());
164
165   LLCArgs.push_back ("-o");
166   LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
167   LLCArgs.push_back ("-f");                  // Overwrite as necessary...
168   LLCArgs.push_back (Bytecode.c_str());      // This is the input bytecode
169   LLCArgs.push_back (0);
170
171   std::cout << "<llc>" << std::flush;
172   DEBUG(std::cerr << "\nAbout to run:\t";
173         for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
174           std::cerr << " " << LLCArgs[i];
175         std::cerr << "\n";
176         );
177   if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
178                             sys::Path(), sys::Path(), sys::Path()))
179     ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
180 }
181
182 void LLC::compileProgram(const std::string &Bytecode) {
183   sys::Path OutputAsmFile;
184   OutputAsm(Bytecode, OutputAsmFile);
185   OutputAsmFile.eraseFromDisk();
186 }
187
188 int LLC::ExecuteProgram(const std::string &Bytecode,
189                         const std::vector<std::string> &Args,
190                         const std::string &InputFile,
191                         const std::string &OutputFile,
192                         const std::vector<std::string> &ArgsForGCC,
193                         const std::vector<std::string> &SharedLibs,
194                         unsigned Timeout) {
195
196   sys::Path OutputAsmFile;
197   OutputAsm(Bytecode, OutputAsmFile);
198   FileRemover OutFileRemover(OutputAsmFile);
199
200   std::vector<std::string> GCCArgs(ArgsForGCC);
201   GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
202
203   // Assuming LLC worked, compile the result with GCC and run it.
204   return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
205                              InputFile, OutputFile, GCCArgs, Timeout);
206 }
207
208 /// createLLC - Try to find the LLC executable
209 ///
210 LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
211                                     std::string &Message,
212                                     const std::vector<std::string> *Args) {
213   std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
214   if (LLCPath.empty()) {
215     Message = "Cannot find `llc' in executable directory or PATH!\n";
216     return 0;
217   }
218
219   Message = "Found llc: " + LLCPath + "\n";
220   GCC *gcc = GCC::create(ProgramPath, Message);
221   if (!gcc) {
222     std::cerr << Message << "\n";
223     exit(1);
224   }
225   return new LLC(LLCPath, gcc, Args);
226 }
227
228 //===---------------------------------------------------------------------===//
229 // JIT Implementation of AbstractIntepreter interface
230 //
231 namespace {
232   class JIT : public AbstractInterpreter {
233     std::string LLIPath;          // The path to the LLI executable
234     std::vector<std::string> ToolArgs; // Args to pass to LLI
235   public:
236     JIT(const std::string &Path, const std::vector<std::string> *Args)
237       : LLIPath(Path) {
238       ToolArgs.clear ();
239       if (Args) { ToolArgs = *Args; }
240     }
241
242     virtual int 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> &GCCArgs =
247                                  std::vector<std::string>(),
248                                const std::vector<std::string> &SharedLibs =
249                                  std::vector<std::string>(), 
250                                unsigned Timeout =0 );
251   };
252 }
253
254 int JIT::ExecuteProgram(const std::string &Bytecode,
255                         const std::vector<std::string> &Args,
256                         const std::string &InputFile,
257                         const std::string &OutputFile,
258                         const std::vector<std::string> &GCCArgs,
259                         const std::vector<std::string> &SharedLibs,
260                         unsigned Timeout) {
261   if (!GCCArgs.empty())
262     throw ToolExecutionError("JIT does not support GCC Arguments.");
263   // Construct a vector of parameters, incorporating those from the command-line
264   std::vector<const char*> JITArgs;
265   JITArgs.push_back(LLIPath.c_str());
266   JITArgs.push_back("-force-interpreter=false");
267
268   // Add any extra LLI args.
269   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
270     JITArgs.push_back(ToolArgs[i].c_str());
271
272   for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
273     JITArgs.push_back("-load");
274     JITArgs.push_back(SharedLibs[i].c_str());
275   }
276   JITArgs.push_back(Bytecode.c_str());
277   // Add optional parameters to the running program from Argv
278   for (unsigned i=0, e = Args.size(); i != e; ++i)
279     JITArgs.push_back(Args[i].c_str());
280   JITArgs.push_back(0);
281
282   std::cout << "<jit>" << std::flush;
283   DEBUG(std::cerr << "\nAbout to run:\t";
284         for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
285           std::cerr << " " << JITArgs[i];
286         std::cerr << "\n";
287         );
288   DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
289   return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
290       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
291       Timeout);
292 }
293
294 /// createJIT - Try to find the LLI executable
295 ///
296 AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
297                    std::string &Message, const std::vector<std::string> *Args) {
298   std::string LLIPath = FindExecutable("lli", ProgPath).toString();
299   if (!LLIPath.empty()) {
300     Message = "Found lli: " + LLIPath + "\n";
301     return new JIT(LLIPath, Args);
302   }
303
304   Message = "Cannot find `lli' in executable directory or PATH!\n";
305   return 0;
306 }
307
308 void CBE::OutputC(const std::string &Bytecode, sys::Path& OutputCFile) {
309   sys::Path uniqueFile(Bytecode+".cbe.c");
310   uniqueFile.makeUnique();
311   OutputCFile = uniqueFile;
312   std::vector<const char *> LLCArgs;
313   LLCArgs.push_back (LLCPath.c_str());
314
315   // Add any extra LLC args.
316   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
317     LLCArgs.push_back(ToolArgs[i].c_str());
318
319   LLCArgs.push_back ("-o");
320   LLCArgs.push_back (OutputCFile.c_str());   // Output to the C file
321   LLCArgs.push_back ("-march=c");            // Output C language
322   LLCArgs.push_back ("-f");                  // Overwrite as necessary...
323   LLCArgs.push_back (Bytecode.c_str());      // This is the input bytecode
324   LLCArgs.push_back (0);
325
326   std::cout << "<cbe>" << std::flush;
327   DEBUG(std::cerr << "\nAbout to run:\t";
328         for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
329           std::cerr << " " << LLCArgs[i];
330         std::cerr << "\n";
331         );
332   if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
333                             sys::Path()))
334     ProcessFailure(LLCPath, &LLCArgs[0]);
335 }
336
337 void CBE::compileProgram(const std::string &Bytecode) {
338   sys::Path OutputCFile;
339   OutputC(Bytecode, OutputCFile);
340   OutputCFile.eraseFromDisk();
341 }
342
343 int CBE::ExecuteProgram(const std::string &Bytecode,
344                         const std::vector<std::string> &Args,
345                         const std::string &InputFile,
346                         const std::string &OutputFile,
347                         const std::vector<std::string> &ArgsForGCC,
348                         const std::vector<std::string> &SharedLibs,
349                         unsigned Timeout) {
350   sys::Path OutputCFile;
351   OutputC(Bytecode, OutputCFile);
352
353   FileRemover CFileRemove(OutputCFile);
354
355   std::vector<std::string> GCCArgs(ArgsForGCC);
356   GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
357   return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
358                              InputFile, OutputFile, GCCArgs, Timeout);
359 }
360
361 /// createCBE - Try to find the 'llc' executable
362 ///
363 CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
364                                     std::string &Message,
365                                     const std::vector<std::string> *Args) {
366   sys::Path LLCPath = FindExecutable("llc", ProgramPath);
367   if (LLCPath.isEmpty()) {
368     Message =
369       "Cannot find `llc' in executable directory or PATH!\n";
370     return 0;
371   }
372
373   Message = "Found llc: " + LLCPath.toString() + "\n";
374   GCC *gcc = GCC::create(ProgramPath, Message);
375   if (!gcc) {
376     std::cerr << Message << "\n";
377     exit(1);
378   }
379   return new CBE(LLCPath, gcc, Args);
380 }
381
382 //===---------------------------------------------------------------------===//
383 // GCC abstraction
384 //
385 int GCC::ExecuteProgram(const std::string &ProgramFile,
386                         const std::vector<std::string> &Args,
387                         FileType fileType,
388                         const std::string &InputFile,
389                         const std::string &OutputFile,
390                         const std::vector<std::string> &ArgsForGCC,
391                         unsigned Timeout ) {
392   std::vector<const char*> GCCArgs;
393
394   GCCArgs.push_back(GCCPath.c_str());
395
396   // Specify -x explicitly in case the extension is wonky
397   GCCArgs.push_back("-x");
398   if (fileType == CFile) {
399     GCCArgs.push_back("c");
400     GCCArgs.push_back("-fno-strict-aliasing");
401   } else {
402     GCCArgs.push_back("assembler");
403 #ifdef __APPLE__
404     GCCArgs.push_back("-force_cpusubtype_ALL");
405 #endif
406   }
407   GCCArgs.push_back(ProgramFile.c_str());  // Specify the input filename...
408   GCCArgs.push_back("-o");
409   sys::Path OutputBinary (ProgramFile+".gcc.exe");
410   OutputBinary.makeUnique();
411   GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
412
413   // Add any arguments intended for GCC. We locate them here because this is
414   // most likely -L and -l options that need to come before other libraries but
415   // after the source. Other options won't be sensitive to placement on the
416   // command line, so this should be safe.
417   for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
418     GCCArgs.push_back(ArgsForGCC[i].c_str());
419
420   GCCArgs.push_back("-lm");                // Hard-code the math library...
421   GCCArgs.push_back("-O2");                // Optimize the program a bit...
422 #if defined (HAVE_LINK_R)
423   GCCArgs.push_back("-Wl,-R.");            // Search this dir for .so files
424 #endif
425 #ifdef __sparc__
426   GCCArgs.push_back("-mcpu=v9");
427 #endif
428   GCCArgs.push_back(0);                    // NULL terminator
429
430   std::cout << "<gcc>" << std::flush;
431   if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
432         sys::Path())) {
433     ProcessFailure(GCCPath, &GCCArgs[0]);
434     exit(1);
435   }
436
437   std::vector<const char*> ProgramArgs;
438
439   ProgramArgs.push_back(OutputBinary.c_str());
440   // Add optional parameters to the running program from Argv
441   for (unsigned i=0, e = Args.size(); i != e; ++i)
442     ProgramArgs.push_back(Args[i].c_str());
443   ProgramArgs.push_back(0);                // NULL terminator
444
445   // Now that we have a binary, run it!
446   std::cout << "<program>" << std::flush;
447   DEBUG(std::cerr << "\nAbout to run:\t";
448         for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
449           std::cerr << " " << ProgramArgs[i];
450         std::cerr << "\n";
451         );
452
453   FileRemover OutputBinaryRemover(OutputBinary);
454   return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
455       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
456       Timeout);
457 }
458
459 int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
460                           std::string &OutputFile) {
461   sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
462   uniqueFilename.makeUnique();
463   OutputFile = uniqueFilename.toString();
464
465   // Compile the C/asm file into a shared object
466   const char* GCCArgs[] = {
467     GCCPath.c_str(),
468     "-x", (fileType == AsmFile) ? "assembler" : "c",
469     "-fno-strict-aliasing",
470     InputFile.c_str(),           // Specify the input filename...
471 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
472     "-G",                        // Compile a shared library, `-G' for Sparc
473 #elif defined(__APPLE__)
474     "-single_module",            // link all source files into a single module
475     "-dynamiclib",               // `-dynamiclib' for MacOS X/PowerPC
476     "-undefined",                // in data segment, rather than generating
477     "dynamic_lookup",            // blocks. dynamic_lookup requires that you set
478                                  // MACOSX_DEPLOYMENT_TARGET=10.3 in your env.
479 #else
480     "-shared",                   // `-shared' for Linux/X86, maybe others
481 #endif
482
483 #if defined(__ia64__) || defined(__alpha__)
484     "-fPIC",                     // IA64 requires shared objs to contain PIC
485 #endif
486 #ifdef __sparc__
487     "-mcpu=v9",
488 #endif
489     "-o", OutputFile.c_str(),    // Output to the right filename...
490     "-O2",                       // Optimize the program a bit...
491     0
492   };
493
494   std::cout << "<gcc>" << std::flush;
495   if (RunProgramWithTimeout(GCCPath, GCCArgs, sys::Path(), sys::Path(),
496                             sys::Path())) {
497     ProcessFailure(GCCPath, GCCArgs);
498     return 1;
499   }
500   return 0;
501 }
502
503 /// create - Try to find the `gcc' executable
504 ///
505 GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {
506   sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
507   if (GCCPath.isEmpty()) {
508     Message = "Cannot find `gcc' in executable directory or PATH!\n";
509     return 0;
510   }
511
512   Message = "Found gcc: " + GCCPath.toString() + "\n";
513   return new GCC(GCCPath);
514 }