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