diff --git a/include/llvm/Support/ToolRunner.h b/include/llvm/Support/ToolRunner.h index d5c82f4da4c..097fc6aed03 100644 --- a/include/llvm/Support/ToolRunner.h +++ b/include/llvm/Support/ToolRunner.h @@ -25,6 +25,19 @@ namespace llvm { class CBE; class LLC; + +/// ToolExecutionError - An instance of this class is thrown by the +/// AbstractInterpreter instances if there is an error running a tool (e.g., LLC +/// crashes) which prevents execution of the program. +/// +class ToolExecutionError { + std::string Message; +public: + ToolExecutionError(const std::string &M) : Message(M) {} + const std::string getMessage() const { return Message; } +}; + + //===---------------------------------------------------------------------===// // GCC abstraction // @@ -108,10 +121,11 @@ public: const std::vector &SharedLibs = std::vector()); - // Sometimes we just want to go half-way and only generate the .c file, - // not necessarily compile it with GCC and run the program. + // Sometimes we just want to go half-way and only generate the .c file, not + // necessarily compile it with GCC and run the program. This throws an + // exception if LLC crashes. // - virtual int OutputC(const std::string &Bytecode, std::string &OutputCFile); + virtual void OutputC(const std::string &Bytecode, std::string &OutputCFile); }; @@ -134,9 +148,10 @@ public: std::vector()); // Sometimes we just want to go half-way and only generate the .s file, - // not necessarily compile it all the way and run the program. + // not necessarily compile it all the way and run the program. This throws + // an exception if execution of LLC fails. // - int OutputAsm(const std::string &Bytecode, std::string &OutputAsmFile); + void OutputAsm(const std::string &Bytecode, std::string &OutputAsmFile); }; } // End llvm namespace diff --git a/lib/Support/ToolRunner.cpp b/lib/Support/ToolRunner.cpp index 3d16a0f827e..a441b2caeb1 100644 --- a/lib/Support/ToolRunner.cpp +++ b/lib/Support/ToolRunner.cpp @@ -44,11 +44,9 @@ int LLI::ExecuteProgram(const std::string &Bytecode, const std::string &InputFile, const std::string &OutputFile, const std::vector &SharedLibs) { - if (!SharedLibs.empty()) { - std::cerr << "LLI currently does not support loading shared libraries.\n" - << "Exiting.\n"; - exit(1); - } + if (!SharedLibs.empty()) + throw ToolExecutionError("LLI currently does not support " + "loading shared libraries."); std::vector LLIArgs; LLIArgs.push_back(LLIPath.c_str()); @@ -86,7 +84,7 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath, //===----------------------------------------------------------------------===// // LLC Implementation of AbstractIntepreter interface // -int LLC::OutputAsm(const std::string &Bytecode, std::string &OutputAsmFile) { +void LLC::OutputAsm(const std::string &Bytecode, std::string &OutputAsmFile) { OutputAsmFile = getUniqueFilename(Bytecode+".llc.s"); const char *LLCArgs[] = { LLCPath.c_str(), @@ -98,14 +96,8 @@ int LLC::OutputAsm(const std::string &Bytecode, std::string &OutputAsmFile) { std::cout << "" << std::flush; if (RunProgramWithTimeout(LLCPath, LLCArgs, "/dev/null", "/dev/null", - "/dev/null")) { - // If LLC failed on the bytecode, print error... - std::cerr << "Error: `llc' failed!\n"; - removeFile(OutputAsmFile); - return 1; - } - - return 0; + "/dev/null")) + throw ToolExecutionError("LLC failed to compile the program."); } int LLC::ExecuteProgram(const std::string &Bytecode, @@ -115,16 +107,12 @@ int LLC::ExecuteProgram(const std::string &Bytecode, const std::vector &SharedLibs) { std::string OutputAsmFile; - if (OutputAsm(Bytecode, OutputAsmFile)) { - std::cerr << "Could not generate asm code with `llc', exiting.\n"; - exit(1); - } + OutputAsm(Bytecode, OutputAsmFile); + FileRemover OutFileRemover(OutputAsmFile); // Assuming LLC worked, compile the result with GCC and run it. - int Result = gcc->ExecuteProgram(OutputAsmFile, Args, GCC::AsmFile, - InputFile, OutputFile, SharedLibs); - removeFile(OutputAsmFile); - return Result; + return gcc->ExecuteProgram(OutputAsmFile, Args, GCC::AsmFile, + InputFile, OutputFile, SharedLibs); } /// createLLC - Try to find the LLC executable @@ -211,7 +199,7 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath, return 0; } -int CBE::OutputC(const std::string &Bytecode, +void CBE::OutputC(const std::string &Bytecode, std::string &OutputCFile) { OutputCFile = getUniqueFilename(Bytecode+".cbe.c"); const char *DisArgs[] = { @@ -225,13 +213,8 @@ int CBE::OutputC(const std::string &Bytecode, std::cout << "" << std::flush; if (RunProgramWithTimeout(LLCPath, DisArgs, "/dev/null", "/dev/null", - "/dev/null")) { - // If dis failed on the bytecode, print error... - std::cerr << "Error: `llc -march=c' failed!\n"; - return 1; - } - - return 0; + "/dev/null")) + throw ToolExecutionError("llc -march=c failed!"); } int CBE::ExecuteProgram(const std::string &Bytecode, @@ -240,16 +223,12 @@ int CBE::ExecuteProgram(const std::string &Bytecode, const std::string &OutputFile, const std::vector &SharedLibs) { std::string OutputCFile; - if (OutputC(Bytecode, OutputCFile)) { - std::cerr << "Could not generate C code with `llc', exiting.\n"; - exit(1); - } + OutputC(Bytecode, OutputCFile); - int Result = gcc->ExecuteProgram(OutputCFile, Args, GCC::CFile, - InputFile, OutputFile, SharedLibs); - removeFile(OutputCFile); + FileRemover CFileRemove(OutputCFile); - return Result; + return gcc->ExecuteProgram(OutputCFile, Args, GCC::CFile, + InputFile, OutputFile, SharedLibs); } /// createCBE - Try to find the 'llc' executable @@ -329,10 +308,10 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, std::cerr << " " << ProgramArgs[i]; std::cerr << "\n"; ); - int ProgramResult = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], - InputFile, OutputFile, OutputFile); - removeFile(OutputBinary); - return ProgramResult; + + FileRemover OutputBinaryRemover(OutputBinary); + return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], + InputFile, OutputFile, OutputFile); } int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, @@ -364,7 +343,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, } void GCC::ProcessFailure(const char** GCCArgs) { - std::cerr << "\n*** Error: invocation of the C compiler failed!\n"; + std::cerr << "\n*** Error: program invocation!\n"; for (const char **Arg = GCCArgs; *Arg; ++Arg) std::cerr << " " << *Arg; std::cerr << "\n";