From f73311bb646bf970806ba7caba220e6bffff7b49 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 8 Feb 2011 18:20:48 +0000 Subject: [PATCH] Added bugpoint options: -compile-custom and -compile-command=... I've been using this mode to narrow down llc unit tests. Example custom compile script: llc "$@" not pygrep.py 'mul\s+r([0-9]), r\1,' < bugpoint-test-program.s git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125096 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/bugpoint/ExecutionDriver.cpp | 22 ++++- tools/bugpoint/ToolRunner.cpp | 132 +++++++++++++++++++++++------ tools/bugpoint/ToolRunner.h | 9 +- 3 files changed, 133 insertions(+), 30 deletions(-) diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index 103002d915a..f1601cdb845 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 @@ -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."), @@ -90,6 +94,11 @@ namespace { AdditionalLinkerArgs("Xlinker", cl::desc("Additional arguments to pass to the linker")); + cl::opt + CustomCompileCommand("compile-command", cl::init("llc"), + cl::desc("Command to compile the bitcode (use with -compile-custom) " + "(default: llc)")); + cl::opt CustomExecCommand("exec-command", cl::init("simulate"), cl::desc("Command to execute the bitcode (use with -run-custom) " @@ -192,8 +201,13 @@ bool BugDriver::initializeExecutionEnvironment() { 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"; @@ -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 " diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 829f108d8cb..37cc9028e07 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -249,6 +249,67 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 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 CompilerArgs; + public: + CustomCompiler( + 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) { + *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 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 // @@ -305,51 +366,74 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, 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 Args) { std::string Command = ""; - std::vector 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 PATH!\n"; - return 0; + 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 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 Args; + lexCommand(Message, ExecCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; return new CustomExecutor(CmdPath, Args); } diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index c127f9982b6..cfa8acf6b24 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -103,8 +103,13 @@ public: static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, const std::vector *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() {}