ExecutionDriver.cpp revision f73311bb646bf970806ba7caba220e6bffff7b49
1//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains code used to execute the program utilizing one of the
11// various ways of running LLVM bitcode.
12//
13//===----------------------------------------------------------------------===//
14
15#include "BugDriver.h"
16#include "ToolRunner.h"
17#include "llvm/Support/CommandLine.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/FileUtilities.h"
20#include "llvm/Support/SystemUtils.h"
21#include "llvm/Support/raw_ostream.h"
22#include <fstream>
23
24using namespace llvm;
25
26namespace {
27  // OutputType - Allow the user to specify the way code should be run, to test
28  // for miscompilation.
29  //
30  enum OutputType {
31    AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe,
32    CompileCustom, Custom
33  };
34
35  cl::opt<double>
36  AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
37               cl::init(0.0));
38  cl::opt<double>
39  RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
40               cl::init(0.0));
41
42  cl::opt<OutputType>
43  InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"),
44                 cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
45                            clEnumValN(RunLLI, "run-int",
46                                       "Execute with the interpreter"),
47                            clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
48                            clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
49                            clEnumValN(RunLLCIA, "run-llc-ia",
50                                  "Compile with LLC with integrated assembler"),
51                            clEnumValN(RunCBE, "run-cbe", "Compile with CBE"),
52                            clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"),
53                            clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"),
54                            clEnumValN(CompileCustom, "compile-custom",
55                            "Use -compile-command to define a command to "
56                            "compile the bitcode. Useful to avoid linking."),
57                            clEnumValN(Custom, "run-custom",
58                            "Use -exec-command to define a command to execute "
59                            "the bitcode. Useful for cross-compilation."),
60                            clEnumValEnd),
61                 cl::init(AutoPick));
62
63  cl::opt<OutputType>
64  SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"),
65              cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"),
66                         clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"),
67                         clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"),
68                         clEnumValN(Custom, "safe-run-custom",
69                         "Use -exec-command to define a command to execute "
70                         "the bitcode. Useful for cross-compilation."),
71                         clEnumValEnd),
72                     cl::init(AutoPick));
73
74  cl::opt<std::string>
75  SafeInterpreterPath("safe-path",
76                   cl::desc("Specify the path to the \"safe\" backend program"),
77                   cl::init(""));
78
79  cl::opt<bool>
80  AppendProgramExitCode("append-exit-code",
81      cl::desc("Append the exit code to the output so it gets diff'd too"),
82      cl::init(false));
83
84  cl::opt<std::string>
85  InputFile("input", cl::init("/dev/null"),
86            cl::desc("Filename to pipe in as stdin (default: /dev/null)"));
87
88  cl::list<std::string>
89  AdditionalSOs("additional-so",
90                cl::desc("Additional shared objects to load "
91                         "into executing programs"));
92
93  cl::list<std::string>
94  AdditionalLinkerArgs("Xlinker",
95      cl::desc("Additional arguments to pass to the linker"));
96
97  cl::opt<std::string>
98  CustomCompileCommand("compile-command", cl::init("llc"),
99      cl::desc("Command to compile the bitcode (use with -compile-custom) "
100               "(default: llc)"));
101
102  cl::opt<std::string>
103  CustomExecCommand("exec-command", cl::init("simulate"),
104      cl::desc("Command to execute the bitcode (use with -run-custom) "
105               "(default: simulate)"));
106}
107
108namespace llvm {
109  // Anything specified after the --args option are taken as arguments to the
110  // program being debugged.
111  cl::list<std::string>
112  InputArgv("args", cl::Positional, cl::desc("<program arguments>..."),
113            cl::ZeroOrMore, cl::PositionalEatsArgs);
114
115  cl::opt<std::string>
116  OutputPrefix("output-prefix", cl::init("bugpoint"),
117            cl::desc("Prefix to use for outputs (default: 'bugpoint')"));
118}
119
120namespace {
121  cl::list<std::string>
122  ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."),
123           cl::ZeroOrMore, cl::PositionalEatsArgs);
124
125  cl::list<std::string>
126  SafeToolArgv("safe-tool-args", cl::Positional,
127               cl::desc("<safe-tool arguments>..."),
128               cl::ZeroOrMore, cl::PositionalEatsArgs);
129
130  cl::opt<std::string>
131  GCCBinary("gcc", cl::init("gcc"),
132              cl::desc("The gcc binary to use. (default 'gcc')"));
133
134  cl::list<std::string>
135  GCCToolArgv("gcc-tool-args", cl::Positional,
136              cl::desc("<gcc-tool arguments>..."),
137              cl::ZeroOrMore, cl::PositionalEatsArgs);
138}
139
140//===----------------------------------------------------------------------===//
141// BugDriver method implementation
142//
143
144/// initializeExecutionEnvironment - This method is used to set up the
145/// environment for executing LLVM programs.
146///
147bool BugDriver::initializeExecutionEnvironment() {
148  outs() << "Initializing execution environment: ";
149
150  // Create an instance of the AbstractInterpreter interface as specified on
151  // the command line
152  SafeInterpreter = 0;
153  std::string Message;
154
155  switch (InterpreterSel) {
156  case AutoPick:
157    InterpreterSel = RunCBE;
158    Interpreter =
159      AbstractInterpreter::createCBE(getToolName(), Message, GCCBinary,
160                                     &ToolArgv, &GCCToolArgv);
161    if (!Interpreter) {
162      InterpreterSel = RunJIT;
163      Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
164                                                   &ToolArgv);
165    }
166    if (!Interpreter) {
167      InterpreterSel = RunLLC;
168      Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
169                                                   GCCBinary, &ToolArgv,
170                                                   &GCCToolArgv);
171    }
172    if (!Interpreter) {
173      InterpreterSel = RunLLI;
174      Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
175                                                   &ToolArgv);
176    }
177    if (!Interpreter) {
178      InterpreterSel = AutoPick;
179      Message = "Sorry, I can't automatically select an interpreter!\n";
180    }
181    break;
182  case RunLLI:
183    Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
184                                                 &ToolArgv);
185    break;
186  case RunLLC:
187  case RunLLCIA:
188  case LLC_Safe:
189    Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
190                                                 GCCBinary, &ToolArgv,
191                                                 &GCCToolArgv,
192                                                 InterpreterSel == RunLLCIA);
193    break;
194  case RunJIT:
195    Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
196                                                 &ToolArgv);
197    break;
198  case RunCBE:
199  case CBE_bug:
200    Interpreter = AbstractInterpreter::createCBE(getToolName(), Message,
201                                                 GCCBinary, &ToolArgv,
202                                                 &GCCToolArgv);
203    break;
204  case CompileCustom:
205    Interpreter =
206      AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand);
207    break;
208  case Custom:
209    Interpreter =
210      AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand);
211    break;
212  default:
213    Message = "Sorry, this back-end is not supported by bugpoint right now!\n";
214    break;
215  }
216  if (!Interpreter)
217    errs() << Message;
218  else // Display informational messages on stdout instead of stderr
219    outs() << Message;
220
221  std::string Path = SafeInterpreterPath;
222  if (Path.empty())
223    Path = getToolName();
224  std::vector<std::string> SafeToolArgs = SafeToolArgv;
225  switch (SafeInterpreterSel) {
226  case AutoPick:
227    // In "cbe-bug" mode, default to using LLC as the "safe" backend.
228    if (!SafeInterpreter &&
229        InterpreterSel == CBE_bug) {
230      SafeInterpreterSel = RunLLC;
231      SafeToolArgs.push_back("--relocation-model=pic");
232      SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
233                                                       GCCBinary,
234                                                       &SafeToolArgs,
235                                                       &GCCToolArgv);
236    }
237
238    // In "llc-safe" mode, default to using LLC as the "safe" backend.
239    if (!SafeInterpreter &&
240        InterpreterSel == LLC_Safe) {
241      SafeInterpreterSel = RunLLC;
242      SafeToolArgs.push_back("--relocation-model=pic");
243      SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
244                                                       GCCBinary,
245                                                       &SafeToolArgs,
246                                                       &GCCToolArgv);
247    }
248
249    // Pick a backend that's different from the test backend. The JIT and
250    // LLC backends share a lot of code, so prefer to use the CBE as the
251    // safe back-end when testing them.
252    if (!SafeInterpreter &&
253        InterpreterSel != RunCBE) {
254      SafeInterpreterSel = RunCBE;
255      SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message,
256                                                       GCCBinary,
257                                                       &SafeToolArgs,
258                                                       &GCCToolArgv);
259    }
260    if (!SafeInterpreter &&
261        InterpreterSel != RunLLC &&
262        InterpreterSel != RunJIT) {
263      SafeInterpreterSel = RunLLC;
264      SafeToolArgs.push_back("--relocation-model=pic");
265      SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
266                                                       GCCBinary,
267                                                       &SafeToolArgs,
268                                                       &GCCToolArgv);
269    }
270    if (!SafeInterpreter) {
271      SafeInterpreterSel = AutoPick;
272      Message = "Sorry, I can't automatically select an interpreter!\n";
273    }
274    break;
275  case RunLLC:
276  case RunLLCIA:
277    SafeToolArgs.push_back("--relocation-model=pic");
278    SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
279                                                     GCCBinary, &SafeToolArgs,
280                                                     &GCCToolArgv,
281                                                SafeInterpreterSel == RunLLCIA);
282    break;
283  case RunCBE:
284    SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message,
285                                                     GCCBinary, &SafeToolArgs,
286                                                     &GCCToolArgv);
287    break;
288  case Custom:
289    SafeInterpreter =
290      AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand);
291    break;
292  default:
293    Message = "Sorry, this back-end is not supported by bugpoint as the "
294              "\"safe\" backend right now!\n";
295    break;
296  }
297  if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); }
298
299  gcc = GCC::create(Message, GCCBinary, &GCCToolArgv);
300  if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); }
301
302  // If there was an error creating the selected interpreter, quit with error.
303  return Interpreter == 0;
304}
305
306/// compileProgram - Try to compile the specified module, returning false and
307/// setting Error if an error occurs.  This is used for code generation
308/// crash testing.
309///
310void BugDriver::compileProgram(Module *M, std::string *Error) const {
311  // Emit the program to a bitcode file...
312  sys::Path BitcodeFile (OutputPrefix + "-test-program.bc");
313  std::string ErrMsg;
314  if (BitcodeFile.makeUnique(true, &ErrMsg)) {
315    errs() << ToolName << ": Error making unique filename: " << ErrMsg
316           << "\n";
317    exit(1);
318  }
319  if (writeProgramToFile(BitcodeFile.str(), M)) {
320    errs() << ToolName << ": Error emitting bitcode to file '"
321           << BitcodeFile.str() << "'!\n";
322    exit(1);
323  }
324
325  // Remove the temporary bitcode file when we are done.
326  FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps);
327
328  // Actually compile the program!
329  Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit);
330}
331
332
333/// executeProgram - This method runs "Program", capturing the output of the
334/// program to a file, returning the filename of the file.  A recommended
335/// filename may be optionally specified.
336///
337std::string BugDriver::executeProgram(const Module *Program,
338                                      std::string OutputFile,
339                                      std::string BitcodeFile,
340                                      const std::string &SharedObj,
341                                      AbstractInterpreter *AI,
342                                      std::string *Error) const {
343  if (AI == 0) AI = Interpreter;
344  assert(AI && "Interpreter should have been created already!");
345  bool CreatedBitcode = false;
346  std::string ErrMsg;
347  if (BitcodeFile.empty()) {
348    // Emit the program to a bitcode file...
349    sys::Path uniqueFilename(OutputPrefix + "-test-program.bc");
350    if (uniqueFilename.makeUnique(true, &ErrMsg)) {
351      errs() << ToolName << ": Error making unique filename: "
352             << ErrMsg << "!\n";
353      exit(1);
354    }
355    BitcodeFile = uniqueFilename.str();
356
357    if (writeProgramToFile(BitcodeFile, Program)) {
358      errs() << ToolName << ": Error emitting bitcode to file '"
359             << BitcodeFile << "'!\n";
360      exit(1);
361    }
362    CreatedBitcode = true;
363  }
364
365  // Remove the temporary bitcode file when we are done.
366  sys::Path BitcodePath(BitcodeFile);
367  FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps);
368
369  if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output";
370
371  // Check to see if this is a valid output filename...
372  sys::Path uniqueFile(OutputFile);
373  if (uniqueFile.makeUnique(true, &ErrMsg)) {
374    errs() << ToolName << ": Error making unique filename: "
375           << ErrMsg << "\n";
376    exit(1);
377  }
378  OutputFile = uniqueFile.str();
379
380  // Figure out which shared objects to run, if any.
381  std::vector<std::string> SharedObjs(AdditionalSOs);
382  if (!SharedObj.empty())
383    SharedObjs.push_back(SharedObj);
384
385  int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile,
386                                  Error, AdditionalLinkerArgs, SharedObjs,
387                                  Timeout, MemoryLimit);
388  if (!Error->empty())
389    return OutputFile;
390
391  if (RetVal == -1) {
392    errs() << "<timeout>";
393    static bool FirstTimeout = true;
394    if (FirstTimeout) {
395      outs() << "\n"
396 "*** Program execution timed out!  This mechanism is designed to handle\n"
397 "    programs stuck in infinite loops gracefully.  The -timeout option\n"
398 "    can be used to change the timeout threshold or disable it completely\n"
399 "    (with -timeout=0).  This message is only displayed once.\n";
400      FirstTimeout = false;
401    }
402  }
403
404  if (AppendProgramExitCode) {
405    std::ofstream outFile(OutputFile.c_str(), std::ios_base::app);
406    outFile << "exit " << RetVal << '\n';
407    outFile.close();
408  }
409
410  // Return the filename we captured the output to.
411  return OutputFile;
412}
413
414/// executeProgramSafely - Used to create reference output with the "safe"
415/// backend, if reference output is not provided.
416///
417std::string BugDriver::executeProgramSafely(const Module *Program,
418                                            std::string OutputFile,
419                                            std::string *Error) const {
420  return executeProgram(Program, OutputFile, "", "", SafeInterpreter, Error);
421}
422
423std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
424                                           std::string &Error) {
425  assert(Interpreter && "Interpreter should have been created already!");
426  sys::Path OutputFile;
427
428  // Using the known-good backend.
429  GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile,
430                                                 Error);
431  if (!Error.empty())
432    return "";
433
434  std::string SharedObjectFile;
435  bool Failure = gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile,
436                                       AdditionalLinkerArgs, Error);
437  if (!Error.empty())
438    return "";
439  if (Failure)
440    exit(1);
441
442  // Remove the intermediate C file
443  OutputFile.eraseFromDisk();
444
445  return "./" + SharedObjectFile;
446}
447
448/// createReferenceFile - calls compileProgram and then records the output
449/// into ReferenceOutputFile. Returns true if reference file created, false
450/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
451/// this function.
452///
453bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
454  std::string Error;
455  compileProgram(Program, &Error);
456  if (!Error.empty())
457    return false;
458
459  ReferenceOutputFile = executeProgramSafely(Program, Filename, &Error);
460  if (!Error.empty()) {
461    errs() << Error;
462    if (Interpreter != SafeInterpreter) {
463      errs() << "*** There is a bug running the \"safe\" backend.  Either"
464             << " debug it (for example with the -run-cbe bugpoint option,"
465             << " if CBE is being used as the \"safe\" backend), or fix the"
466             << " error some other way.\n";
467    }
468    return false;
469  }
470  outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n";
471  return true;
472}
473
474/// diffProgram - This method executes the specified module and diffs the
475/// output against the file specified by ReferenceOutputFile.  If the output
476/// is different, 1 is returned.  If there is a problem with the code
477/// generator (e.g., llc crashes), this will return -1 and set Error.
478///
479bool BugDriver::diffProgram(const Module *Program,
480                            const std::string &BitcodeFile,
481                            const std::string &SharedObject,
482                            bool RemoveBitcode,
483                            std::string *ErrMsg) const {
484  // Execute the program, generating an output file...
485  sys::Path Output(executeProgram(Program, "", BitcodeFile, SharedObject, 0,
486                                  ErrMsg));
487  if (!ErrMsg->empty())
488    return false;
489
490  std::string Error;
491  bool FilesDifferent = false;
492  if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
493                                        sys::Path(Output.str()),
494                                        AbsTolerance, RelTolerance, &Error)) {
495    if (Diff == 2) {
496      errs() << "While diffing output: " << Error << '\n';
497      exit(1);
498    }
499    FilesDifferent = true;
500  }
501  else {
502    // Remove the generated output if there are no differences.
503    Output.eraseFromDisk();
504  }
505
506  // Remove the bitcode file if we are supposed to.
507  if (RemoveBitcode)
508    sys::Path(BitcodeFile).eraseFromDisk();
509  return FilesDifferent;
510}
511
512bool BugDriver::isExecutingJIT() {
513  return InterpreterSel == RunJIT;
514}
515
516