diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index acc363bf979..452259c324e 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -83,8 +83,10 @@ public: int LLI::ExecuteProgram(const std::string &Bytecode, const std::string &OutputFile) { const char *Args[] = { + "lli", "-abort-on-exception", "-quiet", + "-force-interpreter=true", Bytecode.c_str(), 0 }; @@ -93,6 +95,159 @@ int LLI::ExecuteProgram(const std::string &Bytecode, InputFile, OutputFile, OutputFile); } +//===----------------------------------------------------------------------===// +// JIT Implementation of AbstractIntepreter interface +// +class JIT : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable +public: + JIT(const std::string &Path) : LLIPath(Path) { } + + // JIT create method - Try to find the LLI executable + static JIT *create(BugDriver *BD, std::string &Message) { + std::string LLIPath = FindExecutable("lli", BD->getToolName()); + if (!LLIPath.empty()) { + Message = "Found lli: " + LLIPath + "\n"; + return new JIT(LLIPath); + } + + Message = "Cannot find 'lli' in bugpoint executable directory or PATH!\n"; + return 0; + } + virtual int ExecuteProgram(const std::string &Bytecode, + const std::string &OutputFile); +}; + +int JIT::ExecuteProgram(const std::string &Bytecode, + const std::string &OutputFile) { + const char *Args[] = { + "-lli", + "-quiet", + "-force-interpreter=false", + Bytecode.c_str(), + 0 + }; + + return RunProgramWithTimeout(LLIPath, Args, + InputFile, OutputFile, OutputFile); +} + +//===----------------------------------------------------------------------===// +// CBE Implementation of AbstractIntepreter interface +// +class CBE : public AbstractInterpreter { + std::string DISPath; // The path to the LLVM 'dis' executable + std::string GCCPath; // The path to the gcc executable +public: + CBE(const std::string &disPath, const std::string &gccPath) + : DISPath(disPath), GCCPath(gccPath) { } + + // CBE create method - Try to find the 'dis' executable + static CBE *create(BugDriver *BD, std::string &Message) { + std::string DISPath = FindExecutable("dis", BD->getToolName()); + if (DISPath.empty()) { + Message = "Cannot find 'dis' in bugpoint executable directory or PATH!\n"; + return 0; + } + + Message = "Found dis: " + DISPath + "\n"; + + std::string GCCPath = FindExecutable("gcc", BD->getToolName()); + if (GCCPath.empty()) { + Message = "Cannot find 'gcc' in bugpoint executable directory or PATH!\n"; + return 0; + } + + Message += "Found gcc: " + GCCPath + "\n"; + return new CBE(DISPath, GCCPath); + } + virtual int ExecuteProgram(const std::string &Bytecode, + const std::string &OutputFile); +}; + +int CBE::ExecuteProgram(const std::string &Bytecode, + const std::string &OutputFile) { + std::string OutputCFile = getUniqueFilename("bugpoint.cbe.c"); + const char *DisArgs[] = { + DISPath.c_str(), + "-o", OutputCFile.c_str(), // Output to the C file + "-c", // Output to C + "-f", // Overwrite as necessary... + Bytecode.c_str(), // This is the input bytecode + 0 + }; + + std::cout << ""; + if (RunProgramWithTimeout(DISPath, DisArgs, "/dev/null", "/dev/null", + "/dev/null")) { + // If dis failed on the bytecode, print error... + std::cerr << "bugpoint error: dis -c failed!?\n"; + removeFile(OutputCFile); + return 1; + } + + // Assuming the c backend worked, compile the result with GCC... + std::string OutputBinary = getUniqueFilename("bugpoint.cbe.exe"); + const char *GCCArgs[] = { + GCCPath.c_str(), + "-x", "c", // Force recognition as a C file + "-o", OutputBinary.c_str(), // Output to the right filename... + OutputCFile.c_str(), // Specify the input filename... + "-O2", // Optimize the program a bit... + 0 + }; + + // FIXME: Eventually the CC program and arguments for it should be settable on + // the bugpoint command line! + + std::cout << ""; + + // Run the C compiler on the output of the C backend... + if (RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", "/dev/null", + "/dev/null")) { + std::cerr << "\n*** bugpoint error: invocation of the C compiler " + "failed on CBE result!\n"; + for (const char **Arg = DisArgs; *Arg; ++Arg) + std::cerr << " " << *Arg; + std::cerr << "\n"; + for (const char **Arg = GCCArgs; *Arg; ++Arg) + std::cerr << " " << *Arg; + std::cerr << "\n"; + + // Rerun the compiler, capturing any error messages to print them. + std::string ErrorFilename = getUniqueFilename("bugpoint.cbe.errors"); + RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", ErrorFilename.c_str(), + ErrorFilename.c_str()); + + // Read the error message into a string. + std::ifstream ErrorFile(ErrorFilename.c_str()); + if (ErrorFile) { + std::copy(std::istreambuf_iterator(ErrorFile), + std::istreambuf_iterator(), + std::ostreambuf_iterator(std::cerr)); + ErrorFile.close(); + std::cerr << "\n"; + } + + removeFile(ErrorFilename); + exit(1); // Leave stuff around for the user to inspect or debug the CBE + } + + const char *ProgramArgs[] = { + OutputBinary.c_str(), + 0 + }; + + std::cout << ""; + + // Now that we have a binary, run it! + int Result = RunProgramWithTimeout(OutputBinary, ProgramArgs, + InputFile, OutputFile, OutputFile); + std::cout << " "; + removeFile(OutputCFile); + removeFile(OutputBinary); + return Result; +} //===----------------------------------------------------------------------===// // BugDriver method implementation @@ -110,10 +265,13 @@ bool BugDriver::initializeExecutionEnvironment() { // Create an instance of the AbstractInterpreter interface as specified on the // command line std::string Message; - if (InterpreterSel == RunLLI) { - Interpreter = LLI::create(this, Message); - } else { - Message = " Sorry, only LLI is supported right now!"; + switch (InterpreterSel) { + case RunLLI: Interpreter = LLI::create(this, Message); break; + case RunJIT: Interpreter = JIT::create(this, Message); break; + case RunCBE: Interpreter = CBE::create(this, Message); break; + default: + Message = " Sorry, this back-end is not supported by bugpoint right now!\n"; + break; } std::cout << Message;