X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fbugpoint%2FToolRunner.cpp;h=4a7be56461a5cb19053460bf9da34d2bc5bee9b7;hb=9d5968dd51c651570c37117cb03117f8526fd62a;hp=a66b868c22cdc5f064c888b2816b8f6810ea0e7a;hpb=b576c94c15af9a440f69d9d03c2afead7971118c;p=oota-llvm.git diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index a66b868c22c..4a7be56461a 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -13,38 +13,68 @@ #define DEBUG_TYPE "toolrunner" #include "llvm/Support/ToolRunner.h" +#include "Config/config.h" // for HAVE_LINK_R #include "Support/Debug.h" #include "Support/FileUtilities.h" #include #include +#include +using namespace llvm; + +ToolExecutionError::~ToolExecutionError() throw() { } + +static void ProcessFailure(std::string ProgPath, const char** Args) { + std::ostringstream OS; + OS << "\nError running tool:\n "; + for (const char **Arg = Args; *Arg; ++Arg) + OS << " " << *Arg; + OS << "\n"; + + // Rerun the compiler, capturing any error messages to print them. + std::string ErrorFilename = getUniqueFilename("error_messages"); + RunProgramWithTimeout(ProgPath, Args, "/dev/null", ErrorFilename.c_str(), + ErrorFilename.c_str()); + + // Print out the error messages generated by GCC if possible... + std::ifstream ErrorFile(ErrorFilename.c_str()); + if (ErrorFile) { + std::copy(std::istreambuf_iterator(ErrorFile), + std::istreambuf_iterator(), + std::ostreambuf_iterator(OS)); + ErrorFile.close(); + } + + removeFile(ErrorFilename); + throw ToolExecutionError(OS.str()); +} //===---------------------------------------------------------------------===// // LLI Implementation of AbstractIntepreter interface // -class LLI : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable -public: - LLI(const std::string &Path) : LLIPath(Path) { } - - - virtual int ExecuteProgram(const std::string &Bytecode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::vector &SharedLibs = +namespace { + class LLI : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable + public: + LLI(const std::string &Path) : LLIPath(Path) { } + + + virtual int ExecuteProgram(const std::string &Bytecode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + const std::vector &SharedLibs = std::vector()); -}; + }; +} int LLI::ExecuteProgram(const std::string &Bytecode, const std::vector &Args, 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()); @@ -82,7 +112,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(), @@ -94,14 +124,14 @@ 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; - } + "/dev/null")) + ProcessFailure(LLCPath, LLCArgs); +} - return 0; +void LLC::compileProgram(const std::string &Bytecode) { + std::string OutputAsmFile; + OutputAsm(Bytecode, OutputAsmFile); + removeFile(OutputAsmFile); } int LLC::ExecuteProgram(const std::string &Bytecode, @@ -111,16 +141,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 @@ -145,19 +171,21 @@ LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath, //===---------------------------------------------------------------------===// // 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) { } - - - virtual int ExecuteProgram(const std::string &Bytecode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::vector &SharedLibs = +namespace { + class JIT : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable + public: + JIT(const std::string &Path) : LLIPath(Path) { } + + + virtual int ExecuteProgram(const std::string &Bytecode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + const std::vector &SharedLibs = std::vector()); -}; + }; +} int JIT::ExecuteProgram(const std::string &Bytecode, const std::vector &Args, @@ -205,27 +233,28 @@ 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[] = { - DISPath.c_str(), + const char *LLCArgs[] = { + LLCPath.c_str(), "-o", OutputCFile.c_str(), // Output to the C file - "-c", // Output to C + "-march=c", // Output to C "-f", // Overwrite as necessary... Bytecode.c_str(), // This is the input bytecode 0 }; std::cout << "" << std::flush; - if (RunProgramWithTimeout(DISPath, DisArgs, "/dev/null", "/dev/null", - "/dev/null")) { - // If dis failed on the bytecode, print error... - std::cerr << "Error: `llvm-dis -c' failed!\n"; - return 1; - } + if (RunProgramWithTimeout(LLCPath, LLCArgs, "/dev/null", "/dev/null", + "/dev/null")) + ProcessFailure(LLCPath, LLCArgs); +} - return 0; +void CBE::compileProgram(const std::string &Bytecode) { + std::string OutputCFile; + OutputC(Bytecode, OutputCFile); + removeFile(OutputCFile); } int CBE::ExecuteProgram(const std::string &Bytecode, @@ -234,36 +263,32 @@ 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 `llvm-dis', 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 'llvm-dis' executable +/// createCBE - Try to find the 'llc' executable /// CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath, std::string &Message) { - std::string DISPath = FindExecutable("llvm-dis", ProgramPath); - if (DISPath.empty()) { + std::string LLCPath = FindExecutable("llc", ProgramPath); + if (LLCPath.empty()) { Message = - "Cannot find `llvm-dis' in executable directory or PATH!\n"; + "Cannot find `llc' in executable directory or PATH!\n"; return 0; } - Message = "Found llvm-dis: " + DISPath + "\n"; + Message = "Found llc: " + LLCPath + "\n"; GCC *gcc = GCC::create(ProgramPath, Message); if (!gcc) { std::cerr << Message << "\n"; exit(1); } - return new CBE(DISPath, gcc); + return new CBE(LLCPath, gcc); } //===---------------------------------------------------------------------===// @@ -297,13 +322,15 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... GCCArgs.push_back("-lm"); // Hard-code the math library... GCCArgs.push_back("-O2"); // Optimize the program a bit... +#if defined (HAVE_LINK_R) GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files +#endif GCCArgs.push_back(0); // NULL terminator std::cout << "" << std::flush; if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "/dev/null", "/dev/null", "/dev/null")) { - ProcessFailure(&GCCArgs[0]); + ProcessFailure(GCCPath, &GCCArgs[0]); exit(1); } @@ -321,15 +348,15 @@ 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, std::string &OutputFile) { - OutputFile = getUniqueFilename(InputFile+".so"); + OutputFile = getUniqueFilename(InputFile+SHLIBEXT); // Compile the C/asm file into a shared object const char* GCCArgs[] = { GCCPath.c_str(), @@ -349,36 +376,12 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, std::cout << "" << std::flush; if (RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", "/dev/null", "/dev/null")) { - ProcessFailure(GCCArgs); + ProcessFailure(GCCPath, GCCArgs); return 1; } return 0; } -void GCC::ProcessFailure(const char** GCCArgs) { - std::cerr << "\n*** Error: invocation of the C compiler failed!\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("gcc.errors"); - RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", ErrorFilename.c_str(), - ErrorFilename.c_str()); - - // Print out the error messages generated by GCC if possible... - 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); -} - /// create - Try to find the `gcc' executable /// GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {