diff options
Diffstat (limited to 'tools/bugpoint')
-rw-r--r-- | tools/bugpoint/BugDriver.cpp | 2 | ||||
-rw-r--r-- | tools/bugpoint/BugDriver.h | 3 | ||||
-rw-r--r-- | tools/bugpoint/CrashDebugger.cpp | 8 | ||||
-rw-r--r-- | tools/bugpoint/ExecutionDriver.cpp | 44 | ||||
-rw-r--r-- | tools/bugpoint/ExtractFunction.cpp | 12 | ||||
-rw-r--r-- | tools/bugpoint/Miscompilation.cpp | 12 | ||||
-rw-r--r-- | tools/bugpoint/OptimizerDriver.cpp | 28 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.cpp | 206 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.h | 13 | ||||
-rw-r--r-- | tools/bugpoint/bugpoint.cpp | 31 |
10 files changed, 247 insertions, 112 deletions
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index 6966671..1cbf632 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -23,7 +23,7 @@ #include "llvm/Support/FileUtilities.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Host.h" +#include "llvm/Support/Host.h" #include <memory> using namespace llvm; diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index e48806a..cc78489 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -17,6 +17,7 @@ #define BUGDRIVER_H #include "llvm/ADT/ValueMap.h" +#include "llvm/Transforms/Utils/ValueMapper.h" #include <vector> #include <string> @@ -322,7 +323,7 @@ void DeleteFunctionBody(Function *F); /// module, split the functions OUT of the specified module, and place them in /// the new module. Module *SplitFunctionsOutOfModule(Module *M, const std::vector<Function*> &F, - ValueMap<const Value*, Value*> &VMap); + ValueToValueMapTy &VMap); } // End llvm namespace diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 57dc1c8..f19ef62 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -130,7 +130,7 @@ bool ReduceCrashingGlobalVariables::TestGlobalVariables( std::vector<GlobalVariable*> &GVs) { // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... @@ -204,7 +204,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { return false; // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... @@ -271,7 +271,7 @@ namespace { bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... @@ -381,7 +381,7 @@ namespace { bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> &Insts) { // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index 7312484..f1601cd 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -28,7 +28,8 @@ namespace { // for miscompilation. // enum OutputType { - AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe,Custom + AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe, + CompileCustom, Custom }; cl::opt<double> @@ -50,6 +51,9 @@ namespace { clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"), clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), + clEnumValN(CompileCustom, "compile-custom", + "Use -compile-command to define a command to " + "compile the bitcode. Useful to avoid linking."), clEnumValN(Custom, "run-custom", "Use -exec-command to define a command to execute " "the bitcode. Useful for cross-compilation."), @@ -87,10 +91,15 @@ namespace { "into executing programs")); cl::list<std::string> - AdditionalLinkerArgs("Xlinker", + AdditionalLinkerArgs("Xlinker", cl::desc("Additional arguments to pass to the linker")); cl::opt<std::string> + CustomCompileCommand("compile-command", cl::init("llc"), + cl::desc("Command to compile the bitcode (use with -compile-custom) " + "(default: llc)")); + + cl::opt<std::string> CustomExecCommand("exec-command", cl::init("simulate"), cl::desc("Command to execute the bitcode (use with -run-custom) " "(default: simulate)")); @@ -119,7 +128,7 @@ namespace { cl::ZeroOrMore, cl::PositionalEatsArgs); cl::opt<std::string> - GCCBinary("gcc", cl::init("gcc"), + GCCBinary("gcc", cl::init("gcc"), cl::desc("The gcc binary to use. (default 'gcc')")); cl::list<std::string> @@ -157,7 +166,7 @@ bool BugDriver::initializeExecutionEnvironment() { if (!Interpreter) { InterpreterSel = RunLLC; Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, + GCCBinary, &ToolArgv, &GCCToolArgv); } if (!Interpreter) { @@ -178,7 +187,7 @@ bool BugDriver::initializeExecutionEnvironment() { case RunLLCIA: case LLC_Safe: Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, + GCCBinary, &ToolArgv, &GCCToolArgv, InterpreterSel == RunLLCIA); break; @@ -189,11 +198,16 @@ bool BugDriver::initializeExecutionEnvironment() { case RunCBE: case CBE_bug: Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, - GCCBinary, &ToolArgv, + GCCBinary, &ToolArgv, &GCCToolArgv); break; + case CompileCustom: + Interpreter = + AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand); + break; case Custom: - Interpreter = AbstractInterpreter::createCustom(Message, CustomExecCommand); + Interpreter = + AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); break; default: Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; @@ -216,7 +230,7 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + GCCBinary, &SafeToolArgs, &GCCToolArgv); } @@ -227,7 +241,7 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + GCCBinary, &SafeToolArgs, &GCCToolArgv); } @@ -249,7 +263,7 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + GCCBinary, &SafeToolArgs, &GCCToolArgv); } @@ -272,8 +286,8 @@ bool BugDriver::initializeExecutionEnvironment() { &GCCToolArgv); break; case Custom: - SafeInterpreter = AbstractInterpreter::createCustom(Message, - CustomExecCommand); + SafeInterpreter = + AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); break; default: Message = "Sorry, this back-end is not supported by bugpoint as the " @@ -281,7 +295,7 @@ bool BugDriver::initializeExecutionEnvironment() { break; } if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } - + gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } @@ -298,7 +312,7 @@ void BugDriver::compileProgram(Module *M, std::string *Error) const { sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); std::string ErrMsg; if (BitcodeFile.makeUnique(true, &ErrMsg)) { - errs() << ToolName << ": Error making unique filename: " << ErrMsg + errs() << ToolName << ": Error making unique filename: " << ErrMsg << "\n"; exit(1); } @@ -432,7 +446,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, } /// createReferenceFile - calls compileProgram and then records the output -/// into ReferenceOutputFile. Returns true if reference file created, false +/// into ReferenceOutputFile. Returns true if reference file created, false /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE /// this function. /// diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 524f130..593765c 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -29,9 +29,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Signals.h" #include <set> using namespace llvm; @@ -193,7 +193,7 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) { /// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and /// prune appropriate entries out of M1s list. static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, - ValueMap<const Value*, Value*> &VMap) { + ValueToValueMapTy &VMap) { GlobalVariable *GV = M1->getNamedGlobal(GlobalName); if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty()) return; @@ -256,7 +256,7 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, Module * llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function*> &F, - ValueMap<const Value*, Value*> &VMap) { + ValueToValueMapTy &VMap) { // Make sure functions & globals are all external so that linkage // between the two modules will work. for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) @@ -268,7 +268,7 @@ llvm::SplitFunctionsOutOfModule(Module *M, I->setLinkage(GlobalValue::ExternalLinkage); } - ValueMap<const Value*, Value*> NewVMap; + ValueToValueMapTy NewVMap; Module *New = CloneModule(M, NewVMap); // Make sure global initializers exist only in the safe module (CBE->.so) diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 3f2b696..3a5f143 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -261,7 +261,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs, // a function, we want to continue with the original function. Otherwise // we can conclude that a function triggers the bug when in fact one // needs a larger set of original functions to do so. - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *Clone = CloneModule(BD.getProgram(), VMap); Module *Orig = BD.swapProgramIn(Clone); @@ -310,7 +310,7 @@ static bool ExtractLoops(BugDriver &BD, while (1) { if (BugpointIsInterrupted) return MadeChange; - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, @@ -476,7 +476,7 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs, outs() << '\n'; // Split the module into the two halves of the program we want. - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *Clone = CloneModule(BD.getProgram(), VMap); Module *Orig = BD.swapProgramIn(Clone); std::vector<Function*> FuncsOnClone; @@ -551,7 +551,7 @@ static bool ExtractBlocks(BugDriver &BD, return false; } - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *ProgClone = CloneModule(BD.getProgram(), VMap); Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, @@ -738,7 +738,7 @@ void BugDriver::debugMiscompilation(std::string *Error) { // Output a bunch of bitcode files for the user... outs() << "Outputting reduced bitcode files which expose the problem:\n"; - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(getProgram(), VMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, @@ -1011,7 +1011,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { return true; // Split the module into the two halves of the program we want. - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; Module *ToNotCodeGen = CloneModule(getProgram(), VMap); Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap); diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 3600ca6..2471cc1 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -15,10 +15,6 @@ // //===----------------------------------------------------------------------===// -// Note: as a short term hack, the old Unix-specific code and platform- -// independent code co-exist via conditional compilation until it is verified -// that the new code works correctly on Unix. - #include "BugDriver.h" #include "llvm/Module.h" #include "llvm/PassManager.h" @@ -29,9 +25,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #define DONT_GET_PLUGIN_LOADER_OPTION #include "llvm/Support/PluginLoader.h" @@ -130,12 +126,12 @@ bool BugDriver::runPasses(Module *Program, << ErrMsg << "\n"; return(1); } - + std::string ErrInfo; tool_output_file InFile(inputFilename.c_str(), ErrInfo, raw_fd_ostream::F_Binary); - - + + if (!ErrInfo.empty()) { errs() << "Error opening bitcode file: " << inputFilename.str() << "\n"; return 1; @@ -147,11 +143,19 @@ bool BugDriver::runPasses(Module *Program, InFile.os().clear_error(); return 1; } + + sys::Path tool = PrependMainExecutablePath("opt", getToolName(), + (void*)"opt"); + if (tool.empty()) { + errs() << "Cannot find `opt' in executable directory!\n"; + return 1; + } + + // Ok, everything that could go wrong before running opt is done. InFile.keep(); // setup the child process' arguments SmallVector<const char*, 8> Args; - sys::Path tool = FindExecutable("opt", getToolName(), (void*)"opt"); std::string Opt = tool.str(); if (UseValgrind) { Args.push_back("valgrind"); @@ -192,7 +196,7 @@ bool BugDriver::runPasses(Module *Program, prog = sys::Program::FindProgramByName("valgrind"); else prog = tool; - + // Redirect stdout and stderr to nowhere if SilencePasses is given sys::Path Nowhere; const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere}; diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 36dbe14..37cc902 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -13,7 +13,7 @@ #define DEBUG_TYPE "toolrunner" #include "ToolRunner.h" -#include "llvm/System/Program.h" +#include "llvm/Support/Program.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" @@ -59,7 +59,8 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, const sys::Path &StdOutFile, const sys::Path &StdErrFile, unsigned NumSeconds = 0, - unsigned MemoryLimit = 0) { + unsigned MemoryLimit = 0, + std::string *ErrMsg = 0) { const sys::Path* redirects[3]; redirects[0] = &StdInFile; redirects[1] = &StdOutFile; @@ -76,7 +77,7 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, return sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, - NumSeconds, MemoryLimit); + NumSeconds, MemoryLimit, ErrMsg); } /// RunProgramRemotelyWithTimeout - This function runs the given program @@ -141,7 +142,7 @@ static std::string ProcessFailure(sys::Path ProgPath, const char** Args, for (const char **Arg = Args; *Arg; ++Arg) OS << " " << *Arg; OS << "\n"; - + // Rerun the compiler, capturing any error messages to print them. sys::Path ErrorFilename("bugpoint.program_error_messages"); std::string ErrMsg; @@ -206,7 +207,8 @@ int LLI::ExecuteProgram(const std::string &Bitcode, LLIArgs.push_back(LLIPath.c_str()); LLIArgs.push_back("-force-interpreter=true"); - for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), e = SharedLibs.end(); i != e; ++i) { + for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), + e = SharedLibs.end(); i != e; ++i) { LLIArgs.push_back("-load"); LLIArgs.push_back((*i).c_str()); } @@ -229,7 +231,7 @@ int LLI::ExecuteProgram(const std::string &Bitcode, ); return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + Timeout, MemoryLimit, Error); } // LLI create method - Try to find the LLI executable @@ -237,21 +239,82 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, const std::vector<std::string> *ToolArgs) { std::string LLIPath = - FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new LLI(LLIPath, ToolArgs); } - Message = "Cannot find `lli' in executable directory or PATH!\n"; + Message = "Cannot find `lli' in executable directory!\n"; return 0; } //===---------------------------------------------------------------------===// +// Custom compiler command implementation of AbstractIntepreter interface +// +// Allows using a custom command for compiling the bitcode, thus allows, for +// example, to compile a bitcode fragment without linking or executing, then +// using a custom wrapper script to check for compiler errors. +namespace { + class CustomCompiler : public AbstractInterpreter { + std::string CompilerCommand; + std::vector<std::string> CompilerArgs; + public: + CustomCompiler( + const std::string &CompilerCmd, std::vector<std::string> 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<std::string> &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector<std::string> &GCCArgs = + std::vector<std::string>(), + const std::vector<std::string> &SharedLibs = + std::vector<std::string>(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) { + *Error = "Execution not supported with -compile-custom"; + return -1; + } + }; +} + +void CustomCompiler::compileProgram(const std::string &Bitcode, + std::string *Error, + unsigned Timeout, + unsigned MemoryLimit) { + + std::vector<const char*> ProgramArgs; + ProgramArgs.push_back(CompilerCommand.c_str()); + + for (std::size_t i = 0; i < CompilerArgs.size(); ++i) + ProgramArgs.push_back(CompilerArgs.at(i).c_str()); + ProgramArgs.push_back(Bitcode.c_str()); + ProgramArgs.push_back(0); + + // Add optional parameters to the running program from Argv + 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(), + Timeout, MemoryLimit, Error)) + *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], + Timeout, MemoryLimit); +} + +//===---------------------------------------------------------------------===// // Custom execution command implementation of AbstractIntepreter interface // // Allows using a custom command for executing the bitcode, thus allows, -// for example, to invoke a cross compiler for code generation followed by +// for example, to invoke a cross compiler for code generation followed by // a simulator that executes the generated binary. namespace { class CustomExecutor : public AbstractInterpreter { @@ -299,55 +362,78 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, return RunProgramWithTimeout( sys::Path(ExecutionCommand), - &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), - sys::Path(OutputFile), Timeout, MemoryLimit); + &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), + sys::Path(OutputFile), Timeout, MemoryLimit, Error); } -// Custom execution environment create method, takes the execution command -// as arguments -AbstractInterpreter *AbstractInterpreter::createCustom( - std::string &Message, - const std::string &ExecCommandLine) { +// Tokenize the CommandLine to the command and the args to allow +// defining a full command line as the command instead of just the +// executed program. We cannot just pass the whole string after the command +// as a single argument because then program sees only a single +// command line argument (with spaces in it: "foo bar" instead +// of "foo" and "bar"). +// +// 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<std::string> Args) { std::string Command = ""; - std::vector<std::string> Args; std::string delimiters = " "; - // Tokenize the ExecCommandLine to the command and the args to allow - // defining a full command line as the command instead of just the - // executed program. We cannot just pass the whole string after the command - // as a single argument because then program sees only a single - // command line argument (with spaces in it: "foo bar" instead - // of "foo" and "bar"). - - // code borrowed from: - // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html - std::string::size_type lastPos = - ExecCommandLine.find_first_not_of(delimiters, 0); - std::string::size_type pos = - ExecCommandLine.find_first_of(delimiters, lastPos); + std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); + std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); while (std::string::npos != pos || std::string::npos != lastPos) { - std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); + std::string token = CommandLine.substr(lastPos, pos - lastPos); if (Command == "") Command = token; else Args.push_back(token); // Skip delimiters. Note the "not_of" - lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); + lastPos = CommandLine.find_first_not_of(delimiters, pos); // Find next "non-delimiter" - pos = ExecCommandLine.find_first_of(delimiters, lastPos); + pos = CommandLine.find_first_of(delimiters, lastPos); } - std::string CmdPath = sys::Program::FindProgramByName(Command).str(); + CmdPath = sys::Program::FindProgramByName(Command).str(); if (CmdPath.empty()) { - Message = - std::string("Cannot find '") + Command + - "' in executable directory or PATH!\n"; - return 0; + Message = + std::string("Cannot find '") + Command + + "' in PATH!\n"; + return; } Message = "Found command in: " + CmdPath + "\n"; +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustomCompiler( + std::string &Message, + const std::string &CompileCommandLine) { + + std::string CmdPath; + std::vector<std::string> Args; + lexCommand(Message, CompileCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; + + return new CustomCompiler(CmdPath, Args); +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustomExecutor( + std::string &Message, + const std::string &ExecCommandLine) { + + + std::string CmdPath; + std::vector<std::string> Args; + lexCommand(Message, ExecCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; return new CustomExecutor(CmdPath, Args); } @@ -355,7 +441,7 @@ AbstractInterpreter *AbstractInterpreter::createCustom( //===----------------------------------------------------------------------===// // LLC Implementation of AbstractIntepreter interface // -GCC::FileType LLC::OutputCode(const std::string &Bitcode, +GCC::FileType LLC::OutputCode(const std::string &Bitcode, sys::Path &OutputAsmFile, std::string &Error, unsigned Timeout, unsigned MemoryLimit) { const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); @@ -376,10 +462,10 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, LLCArgs.push_back("-o"); LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode - + if (UseIntegratedAssembler) LLCArgs.push_back("-filetype=obj"); - + LLCArgs.push_back (0); outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); @@ -394,7 +480,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, Timeout, MemoryLimit)) Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], Timeout, MemoryLimit); - return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; + return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; } void LLC::compileProgram(const std::string &Bitcode, std::string *Error, @@ -437,9 +523,9 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, const std::vector<std::string> *GCCArgs, bool UseIntegratedAssembler) { std::string LLCPath = - FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); if (LLCPath.empty()) { - Message = "Cannot find `llc' in executable directory or PATH!\n"; + Message = "Cannot find `llc' in executable directory!\n"; return 0; } @@ -474,7 +560,7 @@ namespace { const std::vector<std::string> &GCCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), + std::vector<std::string>(), unsigned Timeout = 0, unsigned MemoryLimit = 0); }; @@ -517,7 +603,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode, DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + Timeout, MemoryLimit, Error); } /// createJIT - Try to find the LLI executable @@ -525,13 +611,13 @@ int JIT::ExecuteProgram(const std::string &Bitcode, AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, const std::vector<std::string> *Args) { std::string LLIPath = - FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new JIT(LLIPath, Args); } - Message = "Cannot find `lli' in executable directory or PATH!\n"; + Message = "Cannot find `lli' in executable directory!\n"; return 0; } @@ -603,14 +689,14 @@ int CBE::ExecuteProgram(const std::string &Bitcode, /// CBE *AbstractInterpreter::createCBE(const char *Argv0, std::string &Message, - const std::string &GCCBinary, + const std::string &GCCBinary, const std::vector<std::string> *Args, const std::vector<std::string> *GCCArgs) { sys::Path LLCPath = - FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); if (LLCPath.isEmpty()) { Message = - "Cannot find `llc' in executable directory or PATH!\n"; + "Cannot find `llc' in executable directory!\n"; return 0; } @@ -677,9 +763,9 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, GCCArgs.push_back("-force_cpusubtype_ALL"); } } - + GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. - + GCCArgs.push_back("-x"); GCCArgs.push_back("none"); GCCArgs.push_back("-o"); @@ -771,7 +857,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, DEBUG(errs() << "<run locally>"); return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + Timeout, MemoryLimit, Error); } else { outs() << "<run remotely>"; outs().flush(); return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), @@ -793,7 +879,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, OutputFile = uniqueFilename.str(); std::vector<const char*> GCCArgs; - + GCCArgs.push_back(GCCPath.c_str()); if (TargetTriple.getArch() == Triple::x86) @@ -816,7 +902,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc else if (TargetTriple.getOS() == Triple::Darwin) { // link all source files into a single module in data segment, rather than - // generating blocks. dynamic_lookup requires that you set + // generating blocks. dynamic_lookup requires that you set // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for // bugpoint to just pass that in the environment of GCC. GCCArgs.push_back("-single_module"); @@ -837,8 +923,8 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. GCCArgs.push_back("-O2"); // Optimize the program a bit. - - + + // Add any arguments intended for GCC. We locate them here because this is // most likely -L and -l options that need to come before other libraries but // after the source. Other options won't be sensitive to placement on the @@ -847,7 +933,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(ArgsForGCC[i].c_str()); GCCArgs.push_back(0); // NULL terminator - + outs() << "<gcc>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; @@ -870,7 +956,7 @@ GCC *GCC::create(std::string &Message, const std::vector<std::string> *Args) { sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); if (GCCPath.isEmpty()) { - Message = "Cannot find `"+ GCCBinary +"' in executable directory or PATH!\n"; + Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; return 0; } diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index cda0ddf..cfa8acf 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -21,7 +21,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <exception> #include <vector> @@ -66,7 +66,7 @@ public: const std::string &OutputFile, std::string *Error = 0, const std::vector<std::string> &GCCArgs = - std::vector<std::string>(), + std::vector<std::string>(), unsigned Timeout = 0, unsigned MemoryLimit = 0); @@ -103,8 +103,13 @@ public: static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, const std::vector<std::string> *Args=0); - static AbstractInterpreter* createCustom(std::string &Message, - const std::string &ExecCommandLine); + static AbstractInterpreter* + createCustomCompiler(std::string &Message, + const std::string &CompileCommandLine); + + static AbstractInterpreter* + createCustomExecutor(std::string &Message, + const std::string &ExecCommandLine); virtual ~AbstractInterpreter() {} diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 79cf563..f9c9e18 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -23,10 +23,14 @@ #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/StandardPasses.h" -#include "llvm/System/Process.h" -#include "llvm/System/Signals.h" -#include "llvm/System/Valgrind.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Valgrind.h" #include "llvm/LinkAllVMCore.h" + +//Enable this macro to debug bugpoint itself. +//#define DEBUG_BUGPOINT 1 + using namespace llvm; static cl::opt<bool> @@ -71,9 +75,11 @@ OverrideTriple("mtriple", cl::desc("Override target triple for module")); /// BugpointIsInterrupted - Set to true when the user presses ctrl-c. bool llvm::BugpointIsInterrupted = false; +#ifndef DEBUG_BUGPOINT static void BugpointInterruptFunction() { BugpointIsInterrupted = true; } +#endif // Hack to capture a pass list. namespace { @@ -91,14 +97,31 @@ namespace { } int main(int argc, char **argv) { +#ifndef DEBUG_BUGPOINT llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +#endif + + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeInstrumentation(Registry); + initializeTarget(Registry); + cl::ParseCommandLineOptions(argc, argv, "LLVM automatic testcase reducer. See\nhttp://" "llvm.org/cmds/bugpoint.html" " for more information.\n"); +#ifndef DEBUG_BUGPOINT sys::SetInterruptFunction(BugpointInterruptFunction); +#endif LLVMContext& Context = getGlobalContext(); // If we have an override, set it and then track the triple we want Modules @@ -147,7 +170,9 @@ int main(int argc, char **argv) { // Bugpoint has the ability of generating a plethora of core files, so to // avoid filling up the disk, we prevent it +#ifndef DEBUG_BUGPOINT sys::Process::PreventCoreFiles(); +#endif std::string Error; bool Failure = D.run(Error); |