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