ExecutionDriver.cpp revision 51c5a286bae5ad27ddc49602f44b7ea7253a4cc9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file was developed by the LLVM research group and is distributed under
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the University of Illinois Open Source License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// This file contains code used to execute the program utilizing one of the
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various ways of running LLVM bytecode.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "BugDriver.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ToolRunner.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/CommandLine.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/Debug.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/FileUtilities.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/Support/SystemUtils.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream>
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace llvm;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OutputType - Allow the user to specify the way code should be run, to test
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for miscompilation.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum OutputType {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutoPick, RunLLI, RunJIT, RunLLC, RunCBE
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<double>
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               cl::init(0.0));
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<double>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               cl::init(0.0));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<OutputType>
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InterpreterSel(cl::desc("Specify how LLVM code should be executed:"),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            clEnumValN(RunLLI, "run-int",
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       "Execute with the interpreter"),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunCBE, "run-cbe", "Compile with CBE"),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValEnd),
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 cl::init(AutoPick));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<bool>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckProgramExitCode("check-exit-code",
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   cl::desc("Assume nonzero exit code is failure (default on)"),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       cl::init(true));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<std::string>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InputFile("input", cl::init("/dev/null"),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            cl::desc("Filename to pipe in as stdin (default: /dev/null)"));
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cl::list<std::string>
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AdditionalSOs("additional-so",
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                cl::desc("Additional shared objects to load "
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         "into executing programs"));
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cl::list<std::string>
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AdditionalLinkerArgs("Xlinker",
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cl::desc("Additional arguments to pass to the linker"));
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace llvm {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Anything specified after the --args option are taken as arguments to the
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // program being debugged.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::list<std::string>
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InputArgv("args", cl::Positional, cl::desc("<program arguments>..."),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cl::ZeroOrMore, cl::PositionalEatsArgs);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::list<std::string>
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           cl::ZeroOrMore, cl::PositionalEatsArgs);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BugDriver method implementation
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// initializeExecutionEnvironment - This method is used to set up the
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// environment for executing LLVM programs.
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)///
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool BugDriver::initializeExecutionEnvironment() {
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::cout << "Initializing execution environment: ";
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Create an instance of the AbstractInterpreter interface as specified on
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // the command line
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cbe = 0;
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string Message;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (InterpreterSel) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case AutoPick:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InterpreterSel = RunCBE;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       &ToolArgv);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Interpreter) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InterpreterSel = RunJIT;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                   &ToolArgv);
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!Interpreter) {
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      InterpreterSel = RunLLC;
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                   &ToolArgv);
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!Interpreter) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InterpreterSel = RunLLI;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &ToolArgv);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Interpreter) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InterpreterSel = AutoPick;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Message = "Sorry, I can't automatically select an interpreter!\n";
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunLLI:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &ToolArgv);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunLLC:
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &ToolArgv);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunJIT:
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &ToolArgv);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunCBE:
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       &ToolArgv);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default:
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Message = "Sorry, this back-end is not supported by bugpoint right now!\n";
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::cerr << Message;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize auxiliary tools for debugging
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cbe) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cbe = AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gcc = GCC::create(getToolName(), Message);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there was an error creating the selected interpreter, quit with error.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Interpreter == 0;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// compileProgram - Try to compile the specified module, throwing an exception
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// if an error occurs, or returning normally if not.  This is used for code
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// generation crash testing.
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)///
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void BugDriver::compileProgram(Module *M) {
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Emit the program to a bytecode file...
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  sys::Path BytecodeFile ("bugpoint-test-program.bc");
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string ErrMsg;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (BytecodeFile.makeUnique(true,&ErrMsg)) {
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::cerr << ToolName << ": Error making unique filename: " << ErrMsg
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << "\n";
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    exit(1);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (writeProgramToFile(BytecodeFile.toString(), M)) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::cerr << ToolName << ": Error emitting bytecode to file '"
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << BytecodeFile << "'!\n";
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Remove the temporary bytecode file when we are done.
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FileRemover BytecodeFileRemover(BytecodeFile);
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Actually compile the program!
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Interpreter->compileProgram(BytecodeFile.toString());
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// executeProgram - This method runs "Program", capturing the output of the
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// program to a file, returning the filename of the file.  A recommended
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// filename may be optionally specified.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BugDriver::executeProgram(std::string OutputFile,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string BytecodeFile,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string &SharedObj,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      AbstractInterpreter *AI,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool *ProgramExitedNonzero) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (AI == 0) AI = Interpreter;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(AI && "Interpreter should have been created already!");
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CreatedBytecode = false;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string ErrMsg;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BytecodeFile.empty()) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Emit the program to a bytecode file...
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sys::Path uniqueFilename("bugpoint-test-program.bc");
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (uniqueFilename.makeUnique(true, &ErrMsg)) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::cerr << ToolName << ": Error making unique filename: "
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << ErrMsg << "!\n";
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exit(1);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BytecodeFile = uniqueFilename.toString();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (writeProgramToFile(BytecodeFile, Program)) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::cerr << ToolName << ": Error emitting bytecode to file '"
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                << BytecodeFile << "'!\n";
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      exit(1);
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CreatedBytecode = true;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Remove the temporary bytecode file when we are done.
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  sys::Path BytecodePath (BytecodeFile);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileRemover BytecodeFileRemover(BytecodePath, CreatedBytecode);
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Check to see if this is a valid output filename...
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  sys::Path uniqueFile(OutputFile);
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (uniqueFile.makeUnique(true, &ErrMsg)) {
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::cerr << ToolName << ": Error making unique filename: "
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              << ErrMsg << "\n";
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    exit(1);
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OutputFile = uniqueFile.toString();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Figure out which shared objects to run, if any.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> SharedObjs(AdditionalSOs);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SharedObj.empty())
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedObjs.push_back(SharedObj);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is an LLC or CBE run, then the GCC compiler might get run to
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compile the program. If so, we should pass the user's -Xlinker options
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as the GCCArgs.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int RetVal = 0;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (InterpreterSel == RunLLC || InterpreterSel == RunCBE)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                OutputFile, AdditionalLinkerArgs, SharedObjs,
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                Timeout);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                OutputFile, std::vector<std::string>(),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SharedObjs, Timeout);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (RetVal == -1) {
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::cerr << "<timeout>";
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static bool FirstTimeout = true;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (FirstTimeout) {
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      std::cout << "\n"
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "*** Program execution timed out!  This mechanism is designed to handle\n"
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "    programs stuck in infinite loops gracefully.  The -timeout option\n"
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "    can be used to change the timeout threshold or disable it completely\n"
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "    (with -timeout=0).  This message is only displayed once.\n";
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FirstTimeout = false;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ProgramExitedNonzero != 0)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ProgramExitedNonzero = (RetVal != 0);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the filename we captured the output to.
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return OutputFile;
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// executeProgramWithCBE - Used to create reference output with the C
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// backend, if reference output is not provided.
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)///
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string BugDriver::executeProgramWithCBE(std::string OutputFile) {
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool ProgramExitedNonzero;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string outFN = executeProgram(OutputFile, "", "",
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     (AbstractInterpreter*)cbe,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &ProgramExitedNonzero);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ProgramExitedNonzero) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::cerr
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Warning: While generating reference output, program exited with\n"
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "non-zero exit code. This will NOT be treated as a failure.\n";
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckProgramExitCode = false;
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return outFN;
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::string BugDriver::compileSharedObject(const std::string &BytecodeFile) {
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  assert(Interpreter && "Interpreter should have been created already!");
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sys::Path OutputCFile;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using CBE
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cbe->OutputC(BytecodeFile, OutputCFile);
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 /* This is an alternative, as yet unimplemented */
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using LLC
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Message;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LLC *llc = createLLCtool(Message);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (llc->OutputAsm(BytecodeFile, OutputFile)) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::cerr << "Could not generate asm code with `llc', exiting.\n";
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    exit(1);
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string SharedObjectFile;
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile,
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            SharedObjectFile, AdditionalLinkerArgs))
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    exit(1);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the intermediate C file
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OutputCFile.eraseFromDisk();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "./" + SharedObjectFile;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// createReferenceFile - calls compileProgram and then records the output
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// into ReferenceOutputFile. Returns true if reference file created, false
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// this function.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::createReferenceFile(Module *M, const std::string &Filename){
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  try {
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    compileProgram(Program);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } catch (ToolExecutionError &TEE) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  try {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReferenceOutputFile = executeProgramWithCBE(Filename);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::cout << "Reference output is: " << ReferenceOutputFile << "\n\n";
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } catch (ToolExecutionError &TEE) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::cerr << TEE.what();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Interpreter != cbe) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::cerr << "*** There is a bug running the C backend.  Either debug"
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " it (use the -run-cbe bugpoint option), or fix the error"
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " some other way.\n";
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// diffProgram - This method executes the specified module and diffs the
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// output against the file specified by ReferenceOutputFile.  If the output
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// is different, true is returned.  If there is a problem with the code
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// generator (e.g., llc crashes), this will throw an exception.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::diffProgram(const std::string &BytecodeFile,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const std::string &SharedObject,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool RemoveBytecode) {
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ProgramExitedNonzero;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Execute the program, generating an output file...
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys::Path Output(executeProgram("", BytecodeFile, SharedObject, 0,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &ProgramExitedNonzero));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we're checking the program exit code, assume anything nonzero is bad.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CheckProgramExitCode && ProgramExitedNonzero) {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Output.eraseFromDisk();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (RemoveBytecode)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sys::Path(BytecodeFile).eraseFromDisk();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string Error;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool FilesDifferent = false;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        sys::Path(Output.toString()),
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        AbsTolerance, RelTolerance, &Error)) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Diff == 2) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::cerr << "While diffing output: " << Error << '\n';
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exit(1);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilesDifferent = true;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the generated output.
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Output.eraseFromDisk();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Remove the bytecode file if we are supposed to.
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (RemoveBytecode)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sys::Path(BytecodeFile).eraseFromDisk();
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return FilesDifferent;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BugDriver::isExecutingJIT() {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return InterpreterSel == RunJIT;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)