diff options
-rw-r--r-- | tools/bugpoint/ExecutionDriver.cpp | 16 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.cpp | 104 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.h | 4 |
3 files changed, 122 insertions, 2 deletions
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index c65d976..49480ef 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -28,7 +28,7 @@ namespace { // for miscompilation. // enum OutputType { - AutoPick, RunLLI, RunJIT, RunLLC, RunCBE, CBE_bug, LLC_Safe + AutoPick, RunLLI, RunJIT, RunLLC, RunCBE, CBE_bug, LLC_Safe, Custom }; cl::opt<double> @@ -48,6 +48,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(Custom, "run-custom", + "Use -exec-command to define a command to execute " + "the bitcode. Useful for cross-compilation."), clEnumValEnd), cl::init(AutoPick)); @@ -71,8 +74,13 @@ 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> + CustomExecCommand("exec-command", cl::init("simulate"), + cl::desc("Command to execute the bitcode (use with -run-custom) " + "(default: simulate)")); } namespace llvm { @@ -148,6 +156,10 @@ bool BugDriver::initializeExecutionEnvironment() { Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv); break; + case Custom: + Interpreter = AbstractInterpreter::createCustom(getToolName(), Message, + CustomExecCommand); + break; default: Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; break; diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index d1e058e..d25ce6c 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -174,6 +174,110 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath, return 0; } +//===---------------------------------------------------------------------===// +// 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 +// a simulator that executes the generated binary. +namespace { + class CustomExecutor : public AbstractInterpreter { + std::string ExecutionCommand; + std::vector<std::string> ExecutorArgs; + public: + CustomExecutor( + const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : + ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector<std::string> &Args, + const std::string &InputFile, + const std::string &OutputFile, + const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &SharedLibs = + std::vector<std::string>(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + }; +} + +int CustomExecutor::ExecuteProgram(const std::string &Bitcode, + const std::vector<std::string> &Args, + const std::string &InputFile, + const std::string &OutputFile, + const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &SharedLibs, + unsigned Timeout, + unsigned MemoryLimit) { + + std::vector<const char*> ProgramArgs; + ProgramArgs.push_back(ExecutionCommand.c_str()); + + for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) + ProgramArgs.push_back(ExecutorArgs.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 = Args.size(); i != e; ++i) + 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); +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustom( + const std::string &ProgramPath, + std::string &Message, + const std::string &ExecCommandLine) { + + 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); + + while (std::string::npos != pos || std::string::npos != lastPos) { + std::string token = ExecCommandLine.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); + // Find next "non-delimiter" + pos = ExecCommandLine.find_first_of(delimiters, lastPos); + } + + std::string CmdPath = FindExecutable(Command, ProgramPath).toString(); + if (CmdPath.empty()) { + Message = + std::string("Cannot find '") + Command + + "' in executable directory or PATH!\n"; + return 0; + } + + Message = "Found command in: " + CmdPath + "\n"; + + return new CustomExecutor(CmdPath, Args); +} + //===----------------------------------------------------------------------===// // LLC Implementation of AbstractIntepreter interface // diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index 020234e..0cc5426 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -98,6 +98,10 @@ public: std::string &Message, const std::vector<std::string> *Args=0); + static AbstractInterpreter* createCustom(const std::string &ProgramPath, + std::string &Message, + const std::string &ExecCommandLine); + virtual ~AbstractInterpreter() {} |