ExecutionDriver.cpp revision 4a10645c70199c8d8567fbc46312158c419720ab
14a10645c70199c8d8567fbc46312158c419720abChris Lattner//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===//
24a10645c70199c8d8567fbc46312158c419720abChris Lattner//
34a10645c70199c8d8567fbc46312158c419720abChris Lattner// This file contains code used to execute the program utilizing one of the
44a10645c70199c8d8567fbc46312158c419720abChris Lattner// various ways of running LLVM bytecode.
54a10645c70199c8d8567fbc46312158c419720abChris Lattner//
64a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===//
74a10645c70199c8d8567fbc46312158c419720abChris Lattner
84a10645c70199c8d8567fbc46312158c419720abChris Lattner/*
94a10645c70199c8d8567fbc46312158c419720abChris LattnerBUGPOINT NOTES:
104a10645c70199c8d8567fbc46312158c419720abChris Lattner
114a10645c70199c8d8567fbc46312158c419720abChris Lattner1. Bugpoint should not leave any files behind if the program works properly
124a10645c70199c8d8567fbc46312158c419720abChris Lattner2. There should be an option to specify the program name, which specifies a
134a10645c70199c8d8567fbc46312158c419720abChris Lattner   unique string to put into output files.  This allows operation in the
144a10645c70199c8d8567fbc46312158c419720abChris Lattner   SingleSource directory f.e.  Default to the first input filename.
154a10645c70199c8d8567fbc46312158c419720abChris Lattner*/
164a10645c70199c8d8567fbc46312158c419720abChris Lattner
174a10645c70199c8d8567fbc46312158c419720abChris Lattner#include "BugDriver.h"
184a10645c70199c8d8567fbc46312158c419720abChris Lattner#include "SystemUtils.h"
194a10645c70199c8d8567fbc46312158c419720abChris Lattner#include "Support/CommandLine.h"
204a10645c70199c8d8567fbc46312158c419720abChris Lattner#include <fstream>
214a10645c70199c8d8567fbc46312158c419720abChris Lattner
224a10645c70199c8d8567fbc46312158c419720abChris Lattnernamespace {
234a10645c70199c8d8567fbc46312158c419720abChris Lattner  // OutputType - Allow the user to specify the way code should be run, to test
244a10645c70199c8d8567fbc46312158c419720abChris Lattner  // for miscompilation.
254a10645c70199c8d8567fbc46312158c419720abChris Lattner  //
264a10645c70199c8d8567fbc46312158c419720abChris Lattner  enum OutputType {
274a10645c70199c8d8567fbc46312158c419720abChris Lattner    RunLLI, RunJIT, RunLLC, RunCBE
284a10645c70199c8d8567fbc46312158c419720abChris Lattner  };
294a10645c70199c8d8567fbc46312158c419720abChris Lattner  cl::opt<OutputType>
304a10645c70199c8d8567fbc46312158c419720abChris Lattner  InterpreterSel(cl::desc("Specify how LLVM code should be executed:"),
314a10645c70199c8d8567fbc46312158c419720abChris Lattner		 cl::values(clEnumValN(RunLLI, "run-lli", "Execute with LLI"),
324a10645c70199c8d8567fbc46312158c419720abChris Lattner			    clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
334a10645c70199c8d8567fbc46312158c419720abChris Lattner			    clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
344a10645c70199c8d8567fbc46312158c419720abChris Lattner			    clEnumValN(RunCBE, "run-cbe", "Compile with CBE"),
354a10645c70199c8d8567fbc46312158c419720abChris Lattner			    0));
364a10645c70199c8d8567fbc46312158c419720abChris Lattner}
374a10645c70199c8d8567fbc46312158c419720abChris Lattner
384a10645c70199c8d8567fbc46312158c419720abChris Lattner/// AbstractInterpreter Class - Subclasses of this class are used to execute
394a10645c70199c8d8567fbc46312158c419720abChris Lattner/// LLVM bytecode in a variety of ways.  This abstract interface hides this
404a10645c70199c8d8567fbc46312158c419720abChris Lattner/// complexity behind a simple interface.
414a10645c70199c8d8567fbc46312158c419720abChris Lattner///
424a10645c70199c8d8567fbc46312158c419720abChris Lattnerstruct AbstractInterpreter {
434a10645c70199c8d8567fbc46312158c419720abChris Lattner
444a10645c70199c8d8567fbc46312158c419720abChris Lattner  virtual ~AbstractInterpreter() {}
454a10645c70199c8d8567fbc46312158c419720abChris Lattner
464a10645c70199c8d8567fbc46312158c419720abChris Lattner  /// ExecuteProgram - Run the specified bytecode file, emitting output to the
474a10645c70199c8d8567fbc46312158c419720abChris Lattner  /// specified filename.  This returns the exit code of the program.
484a10645c70199c8d8567fbc46312158c419720abChris Lattner  ///
494a10645c70199c8d8567fbc46312158c419720abChris Lattner  virtual int ExecuteProgram(const std::string &Bytecode,
504a10645c70199c8d8567fbc46312158c419720abChris Lattner			     const std::string &OutputFile) = 0;
514a10645c70199c8d8567fbc46312158c419720abChris Lattner
524a10645c70199c8d8567fbc46312158c419720abChris Lattner};
534a10645c70199c8d8567fbc46312158c419720abChris Lattner
544a10645c70199c8d8567fbc46312158c419720abChris Lattner
554a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===//
564a10645c70199c8d8567fbc46312158c419720abChris Lattner// LLI Implementation of AbstractIntepreter interface
574a10645c70199c8d8567fbc46312158c419720abChris Lattner//
584a10645c70199c8d8567fbc46312158c419720abChris Lattnerclass LLI : public AbstractInterpreter {
594a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::string LLIPath;          // The path to the LLI executable
604a10645c70199c8d8567fbc46312158c419720abChris Lattnerpublic:
614a10645c70199c8d8567fbc46312158c419720abChris Lattner  LLI(const std::string &Path) : LLIPath(Path) { }
624a10645c70199c8d8567fbc46312158c419720abChris Lattner
634a10645c70199c8d8567fbc46312158c419720abChris Lattner  // LLI create method - Try to find the LLI executable
644a10645c70199c8d8567fbc46312158c419720abChris Lattner  static LLI *create(BugDriver *BD, std::string &Message) {
654a10645c70199c8d8567fbc46312158c419720abChris Lattner    std::string LLIPath = FindExecutable("lli", BD->getToolName());
664a10645c70199c8d8567fbc46312158c419720abChris Lattner    if (!LLIPath.empty()) {
674a10645c70199c8d8567fbc46312158c419720abChris Lattner      Message = "Found lli: " + LLIPath + "\n";
684a10645c70199c8d8567fbc46312158c419720abChris Lattner      return new LLI(LLIPath);
694a10645c70199c8d8567fbc46312158c419720abChris Lattner    }
704a10645c70199c8d8567fbc46312158c419720abChris Lattner
714a10645c70199c8d8567fbc46312158c419720abChris Lattner    Message = "Cannot find 'lli' in bugpoint executable directory or PATH!\n";
724a10645c70199c8d8567fbc46312158c419720abChris Lattner    return 0;
734a10645c70199c8d8567fbc46312158c419720abChris Lattner  }
744a10645c70199c8d8567fbc46312158c419720abChris Lattner  virtual int ExecuteProgram(const std::string &Bytecode,
754a10645c70199c8d8567fbc46312158c419720abChris Lattner			     const std::string &OutputFile);
764a10645c70199c8d8567fbc46312158c419720abChris Lattner};
774a10645c70199c8d8567fbc46312158c419720abChris Lattner
784a10645c70199c8d8567fbc46312158c419720abChris Lattnerint LLI::ExecuteProgram(const std::string &Bytecode,
794a10645c70199c8d8567fbc46312158c419720abChris Lattner			const std::string &OutputFile) {
804a10645c70199c8d8567fbc46312158c419720abChris Lattner  const char *Args[] = {
814a10645c70199c8d8567fbc46312158c419720abChris Lattner    "-abort-on-exception",
824a10645c70199c8d8567fbc46312158c419720abChris Lattner    "-quiet",
834a10645c70199c8d8567fbc46312158c419720abChris Lattner    Bytecode.c_str(),
844a10645c70199c8d8567fbc46312158c419720abChris Lattner    0
854a10645c70199c8d8567fbc46312158c419720abChris Lattner  };
864a10645c70199c8d8567fbc46312158c419720abChris Lattner
874a10645c70199c8d8567fbc46312158c419720abChris Lattner  return RunProgramWithTimeout(LLIPath, Args,
884a10645c70199c8d8567fbc46312158c419720abChris Lattner			       "/dev/null", OutputFile, OutputFile);
894a10645c70199c8d8567fbc46312158c419720abChris Lattner}
904a10645c70199c8d8567fbc46312158c419720abChris Lattner
914a10645c70199c8d8567fbc46312158c419720abChris Lattner
924a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===//
934a10645c70199c8d8567fbc46312158c419720abChris Lattner// BugDriver method implementation
944a10645c70199c8d8567fbc46312158c419720abChris Lattner//
954a10645c70199c8d8567fbc46312158c419720abChris Lattner
964a10645c70199c8d8567fbc46312158c419720abChris Lattner/// initializeExecutionEnvironment - This method is used to set up the
974a10645c70199c8d8567fbc46312158c419720abChris Lattner/// environment for executing LLVM programs.
984a10645c70199c8d8567fbc46312158c419720abChris Lattner///
994a10645c70199c8d8567fbc46312158c419720abChris Lattnerbool BugDriver::initializeExecutionEnvironment() {
1004a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::cout << "Initializing execution environment: ";
1014a10645c70199c8d8567fbc46312158c419720abChris Lattner
1024a10645c70199c8d8567fbc46312158c419720abChris Lattner  // FIXME: This should default to searching for the best interpreter to use on
1034a10645c70199c8d8567fbc46312158c419720abChris Lattner  // this platform, which would be JIT, then LLC, then CBE, then LLI.
1044a10645c70199c8d8567fbc46312158c419720abChris Lattner
1054a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Create an instance of the AbstractInterpreter interface as specified on the
1064a10645c70199c8d8567fbc46312158c419720abChris Lattner  // command line
1074a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::string Message;
1084a10645c70199c8d8567fbc46312158c419720abChris Lattner  if (InterpreterSel == RunLLI) {
1094a10645c70199c8d8567fbc46312158c419720abChris Lattner    Interpreter = LLI::create(this, Message);
1104a10645c70199c8d8567fbc46312158c419720abChris Lattner  } else {
1114a10645c70199c8d8567fbc46312158c419720abChris Lattner    Message = " Sorry, only LLI is supported right now!";
1124a10645c70199c8d8567fbc46312158c419720abChris Lattner  }
1134a10645c70199c8d8567fbc46312158c419720abChris Lattner
1144a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::cout << Message;
1154a10645c70199c8d8567fbc46312158c419720abChris Lattner
1164a10645c70199c8d8567fbc46312158c419720abChris Lattner  // If there was an error creating the selected interpreter, quit with error.
1174a10645c70199c8d8567fbc46312158c419720abChris Lattner  return Interpreter == 0;
1184a10645c70199c8d8567fbc46312158c419720abChris Lattner}
1194a10645c70199c8d8567fbc46312158c419720abChris Lattner
1204a10645c70199c8d8567fbc46312158c419720abChris Lattner
1214a10645c70199c8d8567fbc46312158c419720abChris Lattner/// executeProgram - This method runs "Program", capturing the output of the
1224a10645c70199c8d8567fbc46312158c419720abChris Lattner/// program to a file, returning the filename of the file.  A recommended
1234a10645c70199c8d8567fbc46312158c419720abChris Lattner/// filename may be optionally specified.
1244a10645c70199c8d8567fbc46312158c419720abChris Lattner///
1254a10645c70199c8d8567fbc46312158c419720abChris Lattnerstd::string BugDriver::executeProgram(std::string OutputFile,
1264a10645c70199c8d8567fbc46312158c419720abChris Lattner				      std::string BytecodeFile) {
1274a10645c70199c8d8567fbc46312158c419720abChris Lattner  assert(Interpreter && "Interpreter should have been created already!");
1284a10645c70199c8d8567fbc46312158c419720abChris Lattner  bool CreatedBytecode = false;
1294a10645c70199c8d8567fbc46312158c419720abChris Lattner  if (BytecodeFile.empty()) {
1304a10645c70199c8d8567fbc46312158c419720abChris Lattner    // Emit the program to a bytecode file...
1314a10645c70199c8d8567fbc46312158c419720abChris Lattner    BytecodeFile = getUniqueFilename("bugpoint-test-program.bc");
1324a10645c70199c8d8567fbc46312158c419720abChris Lattner
1334a10645c70199c8d8567fbc46312158c419720abChris Lattner    if (writeProgramToFile(BytecodeFile, Program)) {
1344a10645c70199c8d8567fbc46312158c419720abChris Lattner      std::cerr << ToolName << ": Error emitting bytecode to file '"
1354a10645c70199c8d8567fbc46312158c419720abChris Lattner		<< BytecodeFile << "'!\n";
1364a10645c70199c8d8567fbc46312158c419720abChris Lattner      exit(1);
1374a10645c70199c8d8567fbc46312158c419720abChris Lattner    }
1384a10645c70199c8d8567fbc46312158c419720abChris Lattner    CreatedBytecode = true;
1394a10645c70199c8d8567fbc46312158c419720abChris Lattner  }
1404a10645c70199c8d8567fbc46312158c419720abChris Lattner
1414a10645c70199c8d8567fbc46312158c419720abChris Lattner  if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
1424a10645c70199c8d8567fbc46312158c419720abChris Lattner
1434a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Check to see if this is a valid output filename...
1444a10645c70199c8d8567fbc46312158c419720abChris Lattner  OutputFile = getUniqueFilename(OutputFile);
1454a10645c70199c8d8567fbc46312158c419720abChris Lattner
1464a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Actually execute the program!
1474a10645c70199c8d8567fbc46312158c419720abChris Lattner  int RetVal = Interpreter->ExecuteProgram(BytecodeFile, OutputFile);
1484a10645c70199c8d8567fbc46312158c419720abChris Lattner
1494a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Remove the temporary bytecode file.
1504a10645c70199c8d8567fbc46312158c419720abChris Lattner  if (CreatedBytecode)
1514a10645c70199c8d8567fbc46312158c419720abChris Lattner    removeFile(BytecodeFile);
1524a10645c70199c8d8567fbc46312158c419720abChris Lattner
1534a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Return the filename we captured the output to.
1544a10645c70199c8d8567fbc46312158c419720abChris Lattner  return OutputFile;
1554a10645c70199c8d8567fbc46312158c419720abChris Lattner}
1564a10645c70199c8d8567fbc46312158c419720abChris Lattner
1574a10645c70199c8d8567fbc46312158c419720abChris Lattner/// diffProgram - This method executes the specified module and diffs the output
1584a10645c70199c8d8567fbc46312158c419720abChris Lattner/// against the file specified by ReferenceOutputFile.  If the output is
1594a10645c70199c8d8567fbc46312158c419720abChris Lattner/// different, true is returned.
1604a10645c70199c8d8567fbc46312158c419720abChris Lattner///
1614a10645c70199c8d8567fbc46312158c419720abChris Lattnerbool BugDriver::diffProgram(const std::string &ReferenceOutputFile,
1624a10645c70199c8d8567fbc46312158c419720abChris Lattner			    const std::string &BytecodeFile) {
1634a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Execute the program, generating an output file...
1644a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::string Output = executeProgram("", BytecodeFile);
1654a10645c70199c8d8567fbc46312158c419720abChris Lattner
1664a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::ifstream ReferenceFile(ReferenceOutputFile.c_str());
1674a10645c70199c8d8567fbc46312158c419720abChris Lattner  if (!ReferenceFile) {
1684a10645c70199c8d8567fbc46312158c419720abChris Lattner    std::cerr << "Couldn't open reference output file '"
1694a10645c70199c8d8567fbc46312158c419720abChris Lattner	      << ReferenceOutputFile << "'\n";
1704a10645c70199c8d8567fbc46312158c419720abChris Lattner    exit(1);
1714a10645c70199c8d8567fbc46312158c419720abChris Lattner  }
1724a10645c70199c8d8567fbc46312158c419720abChris Lattner
1734a10645c70199c8d8567fbc46312158c419720abChris Lattner  std::ifstream OutputFile(Output.c_str());
1744a10645c70199c8d8567fbc46312158c419720abChris Lattner  if (!OutputFile) {
1754a10645c70199c8d8567fbc46312158c419720abChris Lattner    std::cerr << "Couldn't open output file: " << Output << "'!\n";
1764a10645c70199c8d8567fbc46312158c419720abChris Lattner    exit(1);
1774a10645c70199c8d8567fbc46312158c419720abChris Lattner  }
1784a10645c70199c8d8567fbc46312158c419720abChris Lattner
1794a10645c70199c8d8567fbc46312158c419720abChris Lattner  bool FilesDifferent = false;
1804a10645c70199c8d8567fbc46312158c419720abChris Lattner
1814a10645c70199c8d8567fbc46312158c419720abChris Lattner  // Compare the two files...
1824a10645c70199c8d8567fbc46312158c419720abChris Lattner  int C1, C2;
1834a10645c70199c8d8567fbc46312158c419720abChris Lattner  do {
1844a10645c70199c8d8567fbc46312158c419720abChris Lattner    C1 = ReferenceFile.get();
1854a10645c70199c8d8567fbc46312158c419720abChris Lattner    C2 = OutputFile.get();
1864a10645c70199c8d8567fbc46312158c419720abChris Lattner    if (C1 != C2) { FilesDifferent = true; break; }
1874a10645c70199c8d8567fbc46312158c419720abChris Lattner  } while (C1 != EOF);
1884a10645c70199c8d8567fbc46312158c419720abChris Lattner
1894a10645c70199c8d8567fbc46312158c419720abChris Lattner  removeFile(Output);
1904a10645c70199c8d8567fbc46312158c419720abChris Lattner  return FilesDifferent;
1914a10645c70199c8d8567fbc46312158c419720abChris Lattner}
192