Add possibility of using arbitrary to to execute stuff from bugpoint.

Patch by Pekka Jääskeläinen!

llvm-svn: 50373
This commit is contained in:
Anton Korobeynikov 2008-04-28 20:53:48 +00:00
parent f06226f506
commit c53565c479
3 changed files with 122 additions and 2 deletions

View File

@ -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;

View File

@ -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
//

View File

@ -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() {}