Rename bugpoint's error message file so that if it somehow
[oota-llvm.git] / tools / bugpoint / ToolRunner.cpp
index cc726676a31fdd1b4e00993fe2f8ac3e28cbca06..f6a151c337144450dd86e61595da9a186abe1842 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -25,12 +25,20 @@ using namespace llvm;
 
 namespace {
   cl::opt<std::string>
-  RSHHost("rsh-host",
-          cl::desc("Remote execution (rsh) host"));
+  RemoteClient("remote-client",
+               cl::desc("Remote execution client (rsh/ssh)"));
 
   cl::opt<std::string>
-  RSHUser("rsh-user",
-          cl::desc("Remote execution (rsh) user id"));
+  RemoteHost("remote-host",
+             cl::desc("Remote execution (rsh/ssh) host"));
+
+  cl::opt<std::string>
+  RemoteUser("remote-user",
+             cl::desc("Remote execution (rsh/ssh) user id"));
+
+  cl::opt<std::string>
+  RemoteExtra("remote-extra-options",
+          cl::desc("Remote execution (rsh/ssh) extra options"));
 }
 
 ToolExecutionError::~ToolExecutionError() throw() { }
@@ -72,7 +80,7 @@ static void ProcessFailure(sys::Path ProgPath, const char** Args) {
   OS << "\n";
 
   // Rerun the compiler, capturing any error messages to print them.
-  sys::Path ErrorFilename("error_messages");
+  sys::Path ErrorFilename("bugpoint.program_error_messages");
   std::string ErrMsg;
   if (ErrorFilename.makeUnique(true, &ErrMsg)) {
     std::cerr << "Error making unique filename: " << ErrMsg << "\n";
@@ -108,7 +116,7 @@ namespace {
       if (Args) { ToolArgs = *Args; }
     }
 
-    virtual int ExecuteProgram(const std::string &Bytecode,
+    virtual int ExecuteProgram(const std::string &Bitcode,
                                const std::vector<std::string> &Args,
                                const std::string &InputFile,
                                const std::string &OutputFile,
@@ -120,7 +128,7 @@ namespace {
   };
 }
 
-int LLI::ExecuteProgram(const std::string &Bytecode,
+int LLI::ExecuteProgram(const std::string &Bitcode,
                         const std::vector<std::string> &Args,
                         const std::string &InputFile,
                         const std::string &OutputFile,
@@ -143,7 +151,7 @@ int LLI::ExecuteProgram(const std::string &Bytecode,
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
     LLIArgs.push_back(ToolArgs[i].c_str());
 
-  LLIArgs.push_back(Bytecode.c_str());
+  LLIArgs.push_back(Bitcode.c_str());
   // Add optional parameters to the running program from Argv
   for (unsigned i=0, e = Args.size(); i != e; ++i)
     LLIArgs.push_back(Args[i].c_str());
@@ -174,12 +182,116 @@ 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
 //
-GCC::FileType LLC::OutputCode(const std::string &Bytecode, 
+GCC::FileType LLC::OutputCode(const std::string &Bitcode, 
                               sys::Path &OutputAsmFile) {
-  sys::Path uniqueFile(Bytecode+".llc.s");
+  sys::Path uniqueFile(Bitcode+".llc.s");
   std::string ErrMsg;
   if (uniqueFile.makeUnique(true, &ErrMsg)) {
     std::cerr << "Error making unique filename: " << ErrMsg << "\n";
@@ -196,7 +308,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bytecode,
   LLCArgs.push_back ("-o");
   LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
   LLCArgs.push_back ("-f");                  // Overwrite as necessary...
-  LLCArgs.push_back (Bytecode.c_str());      // This is the input bytecode
+  LLCArgs.push_back (Bitcode.c_str());      // This is the input bitcode
   LLCArgs.push_back (0);
 
   std::cout << "<llc>" << std::flush;
@@ -212,13 +324,13 @@ GCC::FileType LLC::OutputCode(const std::string &Bytecode,
   return GCC::AsmFile;                              
 }
 
-void LLC::compileProgram(const std::string &Bytecode) {
+void LLC::compileProgram(const std::string &Bitcode) {
   sys::Path OutputAsmFile;
-  OutputCode(Bytecode, OutputAsmFile);
+  OutputCode(Bitcode, OutputAsmFile);
   OutputAsmFile.eraseFromDisk();
 }
 
-int LLC::ExecuteProgram(const std::string &Bytecode,
+int LLC::ExecuteProgram(const std::string &Bitcode,
                         const std::vector<std::string> &Args,
                         const std::string &InputFile,
                         const std::string &OutputFile,
@@ -228,7 +340,7 @@ int LLC::ExecuteProgram(const std::string &Bytecode,
                         unsigned MemoryLimit) {
 
   sys::Path OutputAsmFile;
-  OutputCode(Bytecode, OutputAsmFile);
+  OutputCode(Bitcode, OutputAsmFile);
   FileRemover OutFileRemover(OutputAsmFile);
 
   std::vector<std::string> GCCArgs(ArgsForGCC);
@@ -274,7 +386,7 @@ namespace {
       if (Args) { ToolArgs = *Args; }
     }
 
-    virtual int ExecuteProgram(const std::string &Bytecode,
+    virtual int ExecuteProgram(const std::string &Bitcode,
                                const std::vector<std::string> &Args,
                                const std::string &InputFile,
                                const std::string &OutputFile,
@@ -287,7 +399,7 @@ namespace {
   };
 }
 
-int JIT::ExecuteProgram(const std::string &Bytecode,
+int JIT::ExecuteProgram(const std::string &Bitcode,
                         const std::vector<std::string> &Args,
                         const std::string &InputFile,
                         const std::string &OutputFile,
@@ -310,7 +422,7 @@ int JIT::ExecuteProgram(const std::string &Bytecode,
     JITArgs.push_back("-load");
     JITArgs.push_back(SharedLibs[i].c_str());
   }
-  JITArgs.push_back(Bytecode.c_str());
+  JITArgs.push_back(Bitcode.c_str());
   // Add optional parameters to the running program from Argv
   for (unsigned i=0, e = Args.size(); i != e; ++i)
     JITArgs.push_back(Args[i].c_str());
@@ -342,9 +454,9 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
   return 0;
 }
 
-GCC::FileType CBE::OutputCode(const std::string &Bytecode,
+GCC::FileType CBE::OutputCode(const std::string &Bitcode,
                               sys::Path &OutputCFile) {
-  sys::Path uniqueFile(Bytecode+".cbe.c");
+  sys::Path uniqueFile(Bitcode+".cbe.c");
   std::string ErrMsg;
   if (uniqueFile.makeUnique(true, &ErrMsg)) {
     std::cerr << "Error making unique filename: " << ErrMsg << "\n";
@@ -362,7 +474,7 @@ GCC::FileType CBE::OutputCode(const std::string &Bytecode,
   LLCArgs.push_back (OutputCFile.c_str());   // Output to the C file
   LLCArgs.push_back ("-march=c");            // Output C language
   LLCArgs.push_back ("-f");                  // Overwrite as necessary...
-  LLCArgs.push_back (Bytecode.c_str());      // This is the input bytecode
+  LLCArgs.push_back (Bitcode.c_str());      // This is the input bitcode
   LLCArgs.push_back (0);
 
   std::cout << "<cbe>" << std::flush;
@@ -377,13 +489,13 @@ GCC::FileType CBE::OutputCode(const std::string &Bytecode,
   return GCC::CFile;
 }
 
-void CBE::compileProgram(const std::string &Bytecode) {
+void CBE::compileProgram(const std::string &Bitcode) {
   sys::Path OutputCFile;
-  OutputCode(Bytecode, OutputCFile);
+  OutputCode(Bitcode, OutputCFile);
   OutputCFile.eraseFromDisk();
 }
 
-int CBE::ExecuteProgram(const std::string &Bytecode,
+int CBE::ExecuteProgram(const std::string &Bitcode,
                         const std::vector<std::string> &Args,
                         const std::string &InputFile,
                         const std::string &OutputFile,
@@ -392,7 +504,7 @@ int CBE::ExecuteProgram(const std::string &Bytecode,
                         unsigned Timeout,
                         unsigned MemoryLimit) {
   sys::Path OutputCFile;
-  OutputCode(Bytecode, OutputCFile);
+  OutputCode(Bitcode, OutputCFile);
 
   FileRemover CFileRemove(OutputCFile);
 
@@ -493,13 +605,16 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
 
   std::vector<const char*> ProgramArgs;
 
-  if (RSHPath.isEmpty())
+  if (RemoteClientPath.isEmpty())
     ProgramArgs.push_back(OutputBinary.c_str());
   else {
-    ProgramArgs.push_back(RSHPath.c_str());
-    ProgramArgs.push_back(RSHHost.c_str());
+    ProgramArgs.push_back(RemoteClientPath.c_str());
+    ProgramArgs.push_back(RemoteHost.c_str());
     ProgramArgs.push_back("-l");
-    ProgramArgs.push_back(RSHUser.c_str());
+    ProgramArgs.push_back(RemoteUser.c_str());
+    if (!RemoteExtra.empty()) {
+      ProgramArgs.push_back(RemoteExtra.c_str());
+    }
 
     char* env_pwd = getenv("PWD");
     std::string Exec = "cd ";
@@ -524,12 +639,12 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
 
   FileRemover OutputBinaryRemover(OutputBinary);
 
-  if (RSHPath.isEmpty())
+  if (RemoteClientPath.isEmpty())
     return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
         sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
         Timeout, MemoryLimit);
   else
-    return RunProgramWithTimeout(sys::Path(RSHPath), &ProgramArgs[0],
+    return RunProgramWithTimeout(sys::Path(RemoteClientPath), &ProgramArgs[0],
         sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
         Timeout, MemoryLimit);
 }
@@ -555,6 +670,8 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
   GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
   GCCArgs.push_back("-fno-strict-aliasing");
   GCCArgs.push_back(InputFile.c_str());   // Specify the input filename.
+  GCCArgs.push_back("-x");
+  GCCArgs.push_back("none");
 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
   GCCArgs.push_back("-G");       // Compile a shared library, `-G' for Sparc
 #elif defined(__APPLE__)
@@ -570,7 +687,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
   GCCArgs.push_back("-shared");  // `-shared' for Linux/X86, maybe others
 #endif
 
-#if defined(__ia64__) || defined(__alpha__)
+#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__)
   GCCArgs.push_back("-fPIC");   // Requires shared objs to contain PIC
 #endif
 #ifdef __sparc__
@@ -615,10 +732,10 @@ GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {
     return 0;
   }
 
-  sys::Path RSHPath;
-  if (!RSHHost.empty())
-    RSHPath = FindExecutable("rsh", ProgramPath);
+  sys::Path RemoteClientPath;
+  if (!RemoteClient.empty())
+    RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath);
 
   Message = "Found gcc: " + GCCPath.toString() + "\n";
-  return new GCC(GCCPath, RSHPath);
+  return new GCC(GCCPath, RemoteClientPath);
 }