X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fbugpoint%2FToolRunner.cpp;h=f0fb4bf6f53b2aa924735d29e4ed4f1c11bb8d94;hb=b9a65fd0028acd588f8382a50f7271e332fc363d;hp=37cc9028e073d40012b23fc0c1116eaa89d23ab8;hpb=f73311bb646bf970806ba7caba220e6bffff7b49;p=oota-llvm.git diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 37cc9028e07..f0fb4bf6f53 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -13,12 +13,13 @@ #define DEBUG_TYPE "toolrunner" #include "ToolRunner.h" -#include "llvm/Support/Program.h" +#include "llvm/Config/config.h" // for HAVE_LINK_R #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R #include #include using namespace llvm; @@ -53,18 +54,15 @@ namespace { /// RunProgramWithTimeout - This function provides an alternate interface /// to the sys::Program::ExecuteAndWait interface. /// @see sys::Program::ExecuteAndWait -static int RunProgramWithTimeout(const sys::Path &ProgramPath, +static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args, - const sys::Path &StdInFile, - const sys::Path &StdOutFile, - const sys::Path &StdErrFile, + StringRef StdInFile, + StringRef StdOutFile, + StringRef StdErrFile, unsigned NumSeconds = 0, unsigned MemoryLimit = 0, std::string *ErrMsg = 0) { - const sys::Path* redirects[3]; - redirects[0] = &StdInFile; - redirects[1] = &StdOutFile; - redirects[2] = &StdErrFile; + const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; #if 0 // For debug purposes { @@ -75,9 +73,8 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, } #endif - return - sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, - NumSeconds, MemoryLimit, ErrMsg); + return sys::ExecuteAndWait(ProgramPath, Args, 0, Redirects, + NumSeconds, MemoryLimit, ErrMsg); } /// RunProgramRemotelyWithTimeout - This function runs the given program @@ -86,17 +83,14 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, /// fails. Remote client is required to return 255 if it failed or program exit /// code otherwise. /// @see sys::Program::ExecuteAndWait -static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, +static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, const char **Args, - const sys::Path &StdInFile, - const sys::Path &StdOutFile, - const sys::Path &StdErrFile, + StringRef StdInFile, + StringRef StdOutFile, + StringRef StdErrFile, unsigned NumSeconds = 0, unsigned MemoryLimit = 0) { - const sys::Path* redirects[3]; - redirects[0] = &StdInFile; - redirects[1] = &StdOutFile; - redirects[2] = &StdErrFile; + const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; #if 0 // For debug purposes { @@ -108,8 +102,8 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, #endif // Run the program remotely with the remote client - int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, - 0, redirects, NumSeconds, MemoryLimit); + int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, 0, + Redirects, NumSeconds, MemoryLimit); // Has the remote client fail? if (255 == ReturnCode) { @@ -120,7 +114,8 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, OS << "\n"; // The error message is in the output file, let's print it out from there. - std::ifstream ErrorFile(StdOutFile.c_str()); + std::string StdOutFileName = StdOutFile.str(); + std::ifstream ErrorFile(StdOutFileName.c_str()); if (ErrorFile) { std::copy(std::istreambuf_iterator(ErrorFile), std::istreambuf_iterator(), @@ -128,13 +123,13 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, ErrorFile.close(); } - errs() << OS; + errs() << OS.str(); } return ReturnCode; } -static std::string ProcessFailure(sys::Path ProgPath, const char** Args, +static std::string ProcessFailure(StringRef ProgPath, const char** Args, unsigned Timeout = 0, unsigned MemoryLimit = 0) { std::ostringstream OS; @@ -144,14 +139,16 @@ static std::string ProcessFailure(sys::Path ProgPath, const char** Args, OS << "\n"; // Rerun the compiler, capturing any error messages to print them. - sys::Path ErrorFilename("bugpoint.program_error_messages"); - std::string ErrMsg; - if (ErrorFilename.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; + SmallString<128> ErrorFilename; + int ErrorFD; + error_code EC = sys::fs::createTemporaryFile( + "bugpoint.program_error_messages", "", ErrorFD, ErrorFilename); + if (EC) { + errs() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } - RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, - ErrorFilename, Timeout, MemoryLimit); + RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(), + ErrorFilename.str(), Timeout, MemoryLimit); // FIXME: check return code ? // Print out the error messages generated by GCC if possible... @@ -163,7 +160,7 @@ static std::string ProcessFailure(sys::Path ProgPath, const char** Args, ErrorFile.close(); } - ErrorFilename.eraseFromDisk(); + sys::fs::remove(ErrorFilename.c_str()); return OS.str(); } @@ -181,16 +178,16 @@ namespace { if (Args) { ToolArgs = *Args; } } - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs, - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); + int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) override; }; } @@ -229,17 +226,50 @@ int LLI::ExecuteProgram(const std::string &Bitcode, errs() << " " << LLIArgs[i]; errs() << "\n"; ); - return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), + return RunProgramWithTimeout(LLIPath, &LLIArgs[0], + InputFile, OutputFile, OutputFile, Timeout, MemoryLimit, Error); } +void AbstractInterpreter::anchor() { } + +#if defined(LLVM_ON_UNIX) +const char EXESuffix[] = ""; +#elif defined (LLVM_ON_WIN32) +const char EXESuffix[] = "exe"; +#endif + +/// Prepend the path to the program being executed +/// to \p ExeName, given the value of argv[0] and the address of main() +/// itself. This allows us to find another LLVM tool if it is built in the same +/// directory. An empty string is returned on error; note that this function +/// just mainpulates the path and doesn't check for executability. +/// @brief Find a named executable. +static std::string PrependMainExecutablePath(const std::string &ExeName, + const char *Argv0, + void *MainAddr) { + // Check the directory that the calling program is in. We can do + // this if ProgramPath contains at least one / character, indicating that it + // is a relative path to the executable itself. + std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr); + StringRef Result = sys::path::parent_path(Main); + + if (!Result.empty()) { + SmallString<128> Storage = Result; + sys::path::append(Storage, ExeName); + sys::path::replace_extension(Storage, EXESuffix); + return Storage.str(); + } + + return Result.str(); +} + // LLI create method - Try to find the LLI executable AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, const std::vector *ToolArgs) { std::string LLIPath = - PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createLLI); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new LLI(LLIPath, ToolArgs); @@ -264,22 +294,22 @@ namespace { const std::string &CompilerCmd, std::vector CompArgs) : CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} - virtual void compileProgram(const std::string &Bitcode, - std::string *Error, - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs = - std::vector(), - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) { + void compileProgram(const std::string &Bitcode, + std::string *Error, + unsigned Timeout = 0, + unsigned MemoryLimit = 0) override; + + int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) override { *Error = "Execution not supported with -compile-custom"; return -1; } @@ -303,10 +333,10 @@ void CustomCompiler::compileProgram(const std::string &Bitcode, for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) ProgramArgs.push_back(CompilerArgs[i].c_str()); - if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0], - sys::Path(), sys::Path(), sys::Path(), + if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], + "", "", "", Timeout, MemoryLimit, Error)) - *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], + *Error = ProcessFailure(CompilerCommand, &ProgramArgs[0], Timeout, MemoryLimit); } @@ -325,16 +355,16 @@ namespace { const std::string &ExecutionCmd, std::vector ExecArgs) : ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs, - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); + int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) override; }; } @@ -361,9 +391,9 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, ProgramArgs.push_back(Args[i].c_str()); return RunProgramWithTimeout( - sys::Path(ExecutionCommand), - &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), - sys::Path(OutputFile), Timeout, MemoryLimit, Error); + ExecutionCommand, + &ProgramArgs[0], InputFile, OutputFile, + OutputFile, Timeout, MemoryLimit, Error); } // Tokenize the CommandLine to the command and the args to allow @@ -376,7 +406,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, // code borrowed from: // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html static void lexCommand(std::string &Message, const std::string &CommandLine, - std::string &CmdPath, std::vector Args) { + std::string &CmdPath, std::vector &Args) { std::string Command = ""; std::string delimiters = " "; @@ -396,7 +426,7 @@ static void lexCommand(std::string &Message, const std::string &CommandLine, pos = CommandLine.find_first_of(delimiters, lastPos); } - CmdPath = sys::Program::FindProgramByName(Command).str(); + CmdPath = sys::FindProgramByName(Command); if (CmdPath.empty()) { Message = std::string("Cannot find '") + Command + @@ -442,16 +472,18 @@ AbstractInterpreter *AbstractInterpreter::createCustomExecutor( // LLC Implementation of AbstractIntepreter interface // GCC::FileType LLC::OutputCode(const std::string &Bitcode, - sys::Path &OutputAsmFile, std::string &Error, + std::string &OutputAsmFile, std::string &Error, unsigned Timeout, unsigned MemoryLimit) { const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); - sys::Path uniqueFile(Bitcode + Suffix); - std::string ErrMsg; - if (uniqueFile.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; + + SmallString<128> UniqueFile; + error_code EC = + sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile); + if (EC) { + errs() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } - OutputAsmFile = uniqueFile; + OutputAsmFile = UniqueFile.str(); std::vector LLCArgs; LLCArgs.push_back(LLCPath.c_str()); @@ -475,19 +507,19 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, errs() << " " << LLCArgs[i]; errs() << "\n"; ); - if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], - sys::Path(), sys::Path(), sys::Path(), + if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], + "", "", "", Timeout, MemoryLimit)) - Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], + Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; } void LLC::compileProgram(const std::string &Bitcode, std::string *Error, unsigned Timeout, unsigned MemoryLimit) { - sys::Path OutputAsmFile; + std::string OutputAsmFile; OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); - OutputAsmFile.eraseFromDisk(); + sys::fs::remove(OutputAsmFile); } int LLC::ExecuteProgram(const std::string &Bitcode, @@ -500,7 +532,7 @@ int LLC::ExecuteProgram(const std::string &Bitcode, unsigned Timeout, unsigned MemoryLimit) { - sys::Path OutputAsmFile; + std::string OutputAsmFile; GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); @@ -509,7 +541,7 @@ int LLC::ExecuteProgram(const std::string &Bitcode, GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); // Assuming LLC worked, compile the result with GCC and run it. - return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, + return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind, InputFile, OutputFile, Error, GCCArgs, Timeout, MemoryLimit); } @@ -523,18 +555,18 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, const std::vector *GCCArgs, bool UseIntegratedAssembler) { std::string LLCPath = - PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC); if (LLCPath.empty()) { Message = "Cannot find `llc' in executable directory!\n"; return 0; } - Message = "Found llc: " + LLCPath + "\n"; GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); if (!gcc) { errs() << Message << "\n"; exit(1); } + Message = "Found llc: " + LLCPath + "\n"; return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); } @@ -552,17 +584,17 @@ namespace { if (Args) { ToolArgs = *Args; } } - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs = - std::vector(), - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); + int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) override; }; } @@ -601,8 +633,8 @@ int JIT::ExecuteProgram(const std::string &Bitcode, errs() << "\n"; ); DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); - return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), + return RunProgramWithTimeout(LLIPath, &JITArgs[0], + InputFile, OutputFile, OutputFile, Timeout, MemoryLimit, Error); } @@ -611,7 +643,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode, AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, const std::vector *Args) { std::string LLIPath = - PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createJIT); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new JIT(LLIPath, Args); @@ -621,94 +653,6 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, return 0; } -GCC::FileType CBE::OutputCode(const std::string &Bitcode, - sys::Path &OutputCFile, std::string &Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path uniqueFile(Bitcode+".cbe.c"); - std::string ErrMsg; - if (uniqueFile.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - OutputCFile = uniqueFile; - std::vector LLCArgs; - LLCArgs.push_back(LLCPath.c_str()); - - // Add any extra LLC args. - for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) - LLCArgs.push_back(ToolArgs[i].c_str()); - - LLCArgs.push_back("-o"); - LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file - LLCArgs.push_back("-march=c"); // Output C language - LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode - LLCArgs.push_back(0); - - outs() << ""; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) - errs() << " " << LLCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), - sys::Path(), Timeout, MemoryLimit)) - Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); - return GCC::CFile; -} - -void CBE::compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); - OutputCFile.eraseFromDisk(); -} - -int CBE::ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &ArgsForGCC, - const std::vector &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); - - FileRemover CFileRemove(OutputCFile, !SaveTemps); - - std::vector GCCArgs(ArgsForGCC); - GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); - - return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, - InputFile, OutputFile, Error, GCCArgs, - Timeout, MemoryLimit); -} - -/// createCBE - Try to find the 'llc' executable -/// -CBE *AbstractInterpreter::createCBE(const char *Argv0, - std::string &Message, - const std::string &GCCBinary, - const std::vector *Args, - const std::vector *GCCArgs) { - sys::Path LLCPath = - PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); - if (LLCPath.isEmpty()) { - Message = - "Cannot find `llc' in executable directory!\n"; - return 0; - } - - Message = "Found llc: " + LLCPath.str() + "\n"; - GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); - if (!gcc) { - errs() << Message << "\n"; - exit(1); - } - return new CBE(LLCPath, gcc, Args); -} - //===---------------------------------------------------------------------===// // GCC abstraction // @@ -718,7 +662,7 @@ static bool IsARMArchitecture(std::vector Args) { I = Args.begin(), E = Args.end(); I != E; ++I) { if (StringRef(*I).equals_lower("-arch")) { ++I; - if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) + if (I != E && StringRef(*I).startswith_lower("arm")) return true; } } @@ -758,8 +702,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, // For ARM architectures we don't want this flag. bugpoint isn't // explicitly told what architecture it is working on, so we get // it from gcc flags - if ((TargetTriple.getOS() == Triple::Darwin) && - !IsARMArchitecture(GCCArgs)) + if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) GCCArgs.push_back("-force_cpusubtype_ALL"); } } @@ -769,10 +712,12 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, GCCArgs.push_back("-x"); GCCArgs.push_back("none"); GCCArgs.push_back("-o"); - sys::Path OutputBinary (ProgramFile+".gcc.exe"); - std::string ErrMsg; - if (OutputBinary.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; + + SmallString<128> OutputBinary; + error_code EC = + sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.gcc.exe", OutputBinary); + if (EC) { + errs() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... @@ -799,8 +744,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, errs() << " " << GCCArgs[i]; errs() << "\n"; ); - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), - sys::Path())) { + if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { *Error = ProcessFailure(GCCPath, &GCCArgs[0]); return -1; } @@ -811,7 +755,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, // ProgramArgs is used. std::string Exec; - if (RemoteClientPath.isEmpty()) + if (RemoteClientPath.empty()) ProgramArgs.push_back(OutputBinary.c_str()); else { ProgramArgs.push_back(RemoteClientPath.c_str()); @@ -851,18 +795,27 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, errs() << "\n"; ); - FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); + FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); - if (RemoteClientPath.isEmpty()) { + if (RemoteClientPath.empty()) { DEBUG(errs() << ""); - return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit, Error); + int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0], + InputFile, OutputFile, OutputFile, + Timeout, MemoryLimit, Error); + // Treat a signal (usually SIGSEGV) or timeout as part of the program output + // so that crash-causing miscompilation is handled seamlessly. + if (ExitCode < -1) { + std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); + outFile << *Error << '\n'; + outFile.close(); + Error->clear(); + } + return ExitCode; } else { outs() << ""; outs().flush(); - return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), - &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), - sys::Path(OutputFile), Timeout, MemoryLimit); + return RunProgramRemotelyWithTimeout(RemoteClientPath, + &ProgramArgs[0], InputFile, OutputFile, + OutputFile, Timeout, MemoryLimit); } } @@ -870,13 +823,14 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, std::string &OutputFile, const std::vector &ArgsForGCC, std::string &Error) { - sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); - std::string ErrMsg; - if (uniqueFilename.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; + SmallString<128> UniqueFilename; + error_code EC = sys::fs::createUniqueFile( + InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename); + if (EC) { + errs() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } - OutputFile = uniqueFilename.str(); + OutputFile = UniqueFilename.str(); std::vector GCCArgs; @@ -900,7 +854,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back("none"); if (TargetTriple.getArch() == Triple::sparc) GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc - else if (TargetTriple.getOS() == Triple::Darwin) { + else if (TargetTriple.isOSDarwin()) { // link all source files into a single module in data segment, rather than // generating blocks. dynamic_lookup requires that you set // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for @@ -912,8 +866,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, } else GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others - if ((TargetTriple.getArch() == Triple::alpha) || - (TargetTriple.getArch() == Triple::x86_64)) + if (TargetTriple.getArch() == Triple::x86_64) GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC if (TargetTriple.getArch() == Triple::sparc) @@ -941,8 +894,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, errs() << " " << GCCArgs[i]; errs() << "\n"; ); - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), - sys::Path())) { + if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { Error = ProcessFailure(GCCPath, &GCCArgs[0]); return 1; } @@ -954,16 +906,16 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCC *GCC::create(std::string &Message, const std::string &GCCBinary, const std::vector *Args) { - sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); - if (GCCPath.isEmpty()) { + std::string GCCPath = sys::FindProgramByName(GCCBinary); + if (GCCPath.empty()) { Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; return 0; } - sys::Path RemoteClientPath; + std::string RemoteClientPath; if (!RemoteClient.empty()) - RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); + RemoteClientPath = sys::FindProgramByName(RemoteClient); - Message = "Found gcc: " + GCCPath.str() + "\n"; + Message = "Found gcc: " + GCCPath + "\n"; return new GCC(GCCPath, RemoteClientPath, Args); }