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