ExecutionDriver.cpp revision a328c51bb99666ee0c045a57ea6d6ce2b0198f9b
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// This file was developed by the LLVM research group and is distributed under
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the University of Illinois Open Source License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (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)//
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//===----------------------------------------------------------------------===//
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "BugDriver.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "llvm/Support/ToolRunner.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/CommandLine.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/Debug.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/FileUtilities.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/Support/SystemUtils.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace llvm;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OutputType - Allow the user to specify the way code should be run, to test
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // for miscompilation.
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  enum OutputType {
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    AutoPick, RunLLI, RunJIT, RunLLC, RunCBE
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<double>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               cl::init(0.0));
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<double>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               cl::init(0.0));
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<OutputType>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterpreterSel(cl::desc("Specify how LLVM code should be executed:"),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunLLI, "run-int",
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       "Execute with the interpreter"),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValN(RunCBE, "run-cbe", "Compile with CBE"),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            clEnumValEnd),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 cl::init(AutoPick));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<bool>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckProgramExitCode("check-exit-code",
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   cl::desc("Assume nonzero exit code is failure (default on)"),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       cl::init(true));
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<std::string>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InputFile("input", cl::init("/dev/null"),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cl::desc("Filename to pipe in as stdin (default: /dev/null)"));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::list<std::string>
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdditionalSOs("additional-so",
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                cl::desc("Additional shared objects to load "
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "into executing programs"));
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::opt<unsigned>
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               cl::desc("Number of seconds program is allowed to run before it "
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "is killed (default is 300s), 0 disables timeout"));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace llvm {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Anything specified after the --args option are taken as arguments to the
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // program being debugged.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::list<std::string>
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InputArgv("args", cl::Positional, cl::desc("<program arguments>..."),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cl::ZeroOrMore, cl::PositionalEatsArgs);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl::list<std::string>
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           cl::ZeroOrMore, cl::PositionalEatsArgs);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//===----------------------------------------------------------------------===//
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BugDriver method implementation
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// initializeExecutionEnvironment - This method is used to set up the
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// environment for executing LLVM programs.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::initializeExecutionEnvironment() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::cout << "Initializing execution environment: ";
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an instance of the AbstractInterpreter interface as specified on
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the command line
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cbe = 0;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Message;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (InterpreterSel) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case AutoPick:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InterpreterSel = RunCBE;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       &ToolArgv);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Interpreter) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InterpreterSel = RunJIT;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &ToolArgv);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!Interpreter) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InterpreterSel = RunLLC;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &ToolArgv);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Interpreter) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InterpreterSel = RunLLI;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &ToolArgv);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Interpreter) {
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      InterpreterSel = AutoPick;
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      Message = "Sorry, I can't automatically select an interpreter!\n";
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunLLI:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &ToolArgv);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunLLC:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &ToolArgv);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunJIT:
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &ToolArgv);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RunCBE:
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       &ToolArgv);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default:
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message = "Sorry, this back-end is not supported by bugpoint right now!\n";
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::cerr << Message;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize auxiliary tools for debugging
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cbe) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cbe = AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gcc = GCC::create(getToolName(), Message);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there was an error creating the selected interpreter, quit with error.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Interpreter == 0;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// compileProgram - Try to compile the specified module, throwing an exception
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// if an error occurs, or returning normally if not.  This is used for code
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// generation crash testing.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BugDriver::compileProgram(Module *M) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Emit the program to a bytecode file...
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys::Path BytecodeFile ("bugpoint-test-program.bc");
163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  BytecodeFile.makeUnique();
164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (writeProgramToFile(BytecodeFile.toString(), M)) {
165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    std::cerr << ToolName << ": Error emitting bytecode to file '"
166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              << BytecodeFile << "'!\n";
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    exit(1);
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Remove the temporary bytecode file when we are done.
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileRemover BytecodeFileRemover(BytecodeFile);
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Actually compile the program!
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Interpreter->compileProgram(BytecodeFile.toString());
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// executeProgram - This method runs "Program", capturing the output of the
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// program to a file, returning the filename of the file.  A recommended
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// filename may be optionally specified.
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch///
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::string BugDriver::executeProgram(std::string OutputFile,
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                      std::string BytecodeFile,
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                      const std::string &SharedObj,
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                      AbstractInterpreter *AI,
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                      bool *ProgramExitedNonzero) {
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (AI == 0) AI = Interpreter;
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  assert(AI && "Interpreter should have been created already!");
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool CreatedBytecode = false;
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (BytecodeFile.empty()) {
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Emit the program to a bytecode file...
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    sys::Path uniqueFilename("bugpoint-test-program.bc");
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uniqueFilename.makeUnique();
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    BytecodeFile = uniqueFilename.toString();
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (writeProgramToFile(BytecodeFile, Program)) {
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      std::cerr << ToolName << ": Error emitting bytecode to file '"
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                << BytecodeFile << "'!\n";
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      exit(1);
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreatedBytecode = true;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the temporary bytecode file when we are done.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys::Path BytecodePath (BytecodeFile);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileRemover BytecodeFileRemover(BytecodePath, CreatedBytecode);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if this is a valid output filename...
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys::Path uniqueFile(OutputFile);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uniqueFile.makeUnique();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OutputFile = uniqueFile.toString();
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Figure out which shared objects to run, if any.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> SharedObjs(AdditionalSOs);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SharedObj.empty())
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedObjs.push_back(SharedObj);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Actually execute the program!
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  OutputFile, SharedObjs, TimeoutValue);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (RetVal == -1) {
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::cerr << "<timeout>";
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static bool FirstTimeout = true;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FirstTimeout) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::cout << "\n"
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "*** Program execution timed out!  This mechanism is designed to handle\n"
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "    programs stuck in infinite loops gracefully.  The -timeout option\n"
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "    can be used to change the timeout threshold or disable it completely\n"
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "    (with -timeout=0).  This message is only displayed once.\n";
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FirstTimeout = false;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ProgramExitedNonzero != 0)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ProgramExitedNonzero = (RetVal != 0);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the filename we captured the output to.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OutputFile;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// executeProgramWithCBE - Used to create reference output with the C
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// backend, if reference output is not provided.
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch///
2472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochstd::string BugDriver::executeProgramWithCBE(std::string OutputFile) {
2482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  bool ProgramExitedNonzero;
2492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string outFN = executeProgram(OutputFile, "", "",
2502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     (AbstractInterpreter*)cbe,
2512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     &ProgramExitedNonzero);
2522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (ProgramExitedNonzero) {
2532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    std::cerr
2542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      << "Warning: While generating reference output, program exited with\n"
2552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      << "non-zero exit code. This will NOT be treated as a failure.\n";
2562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    CheckProgramExitCode = false;
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return outFN;
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BugDriver::compileSharedObject(const std::string &BytecodeFile) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(Interpreter && "Interpreter should have been created already!");
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys::Path OutputCFile;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using CBE
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cbe->OutputC(BytecodeFile, OutputCFile);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 /* This is an alternative, as yet unimplemented */
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using LLC
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Message;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LLC *llc = createLLCtool(Message);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (llc->OutputAsm(BytecodeFile, OutputFile)) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::cerr << "Could not generate asm code with `llc', exiting.\n";
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string SharedObjectFile;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SharedObjectFile))
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the intermediate C file
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OutputCFile.destroyFile();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "./" + SharedObjectFile;
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/// diffProgram - This method executes the specified module and diffs the output
291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// against the file specified by ReferenceOutputFile.  If the output is
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// different, true is returned.
293c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch///
294c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool BugDriver::diffProgram(const std::string &BytecodeFile,
295c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                            const std::string &SharedObject,
296c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                            bool RemoveBytecode) {
297c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  bool ProgramExitedNonzero;
298c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
299c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // Execute the program, generating an output file...
300c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  sys::Path Output (executeProgram("", BytecodeFile, SharedObject, 0,
301c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                                      &ProgramExitedNonzero));
302c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
303c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // If we're checking the program exit code, assume anything nonzero is bad.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CheckProgramExitCode && ProgramExitedNonzero) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Output.destroyFile();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (RemoveBytecode)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sys::Path(BytecodeFile).destroyFile();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string Error;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool FilesDifferent = false;
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        sys::Path(Output.toString()),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        AbsTolerance, RelTolerance, &Error)) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Diff == 2) {
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::cerr << "While diffing output: " << Error << '\n';
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exit(1);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FilesDifferent = true;
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Remove the generated output.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Output.destroyFile();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the bytecode file if we are supposed to.
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (RemoveBytecode) sys::Path(BytecodeFile).destroyFile();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FilesDifferent;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::isExecutingJIT() {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InterpreterSel == RunJIT;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)