aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp16
-rw-r--r--tools/bugpoint/ToolRunner.cpp104
-rw-r--r--tools/bugpoint/ToolRunner.h4
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() {}