Add possibility of using arbitrary to to execute stuff from bugpoint.
authorAnton Korobeynikov <asl@math.spbu.ru>
Mon, 28 Apr 2008 20:53:48 +0000 (20:53 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Mon, 28 Apr 2008 20:53:48 +0000 (20:53 +0000)
Patch by Pekka Jääskeläinen!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50373 91177308-0d34-0410-b5e6-96231b3b80d8

tools/bugpoint/ExecutionDriver.cpp
tools/bugpoint/ToolRunner.cpp
tools/bugpoint/ToolRunner.h

index c65d97607e2c5a5d7428ebeb3dc0af072478150b..49480efb63663c91324f7d0ae6991930c235a8c9 100644 (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;
index d1e058e3ceb95aec3fcee6dd1eb664b8c3f3bed9..d25ce6c306f1a0ba5339e0e52614233e32564e92 100644 (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
 //
index 020234ecac7193ca0f9d477b9dd58f27e1c32d52..0cc5426b083fa7ad914f4cf355742362a813a884 100644 (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() {}