Added bugpoint options: -compile-custom and -compile-command=...
authorAndrew Trick <atrick@apple.com>
Tue, 8 Feb 2011 18:20:48 +0000 (18:20 +0000)
committerAndrew Trick <atrick@apple.com>
Tue, 8 Feb 2011 18:20:48 +0000 (18:20 +0000)
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
tools/bugpoint/ToolRunner.cpp
tools/bugpoint/ToolRunner.h

index 103002d915a1ba83ae77d3138f458407a8931e8c..f1601cdb84577c467fa5b848689399b85f7e60f8 100644 (file)
@@ -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."),
@@ -90,6 +94,11 @@ namespace {
   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) "
@@ -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 "
index 829f108d8cbeb4dd56d7a609ed4e0f95b6bbd9cd..37cc9028e073d40012b23fc0c1116eaa89d23ab8 100644 (file)
@@ -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<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
 //
@@ -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<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 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<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);
 }
index c127f9982b6d0f40c13b1d7a4dae1e26c83072c6..cfa8acf6b24043ba74f573e66211e4d7d85b3365 100644 (file)
@@ -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() {}