minor cleanups. Add provisions for a new standard BLOCKINFO_BLOCK
[oota-llvm.git] / tools / bugpoint / ToolRunner.cpp
index 067bf658c7329557fffe3654d90d64cc70c2b800..cc726676a31fdd1b4e00993fe2f8ac3e28cbca06 100644 (file)
@@ -15,6 +15,7 @@
 #include "ToolRunner.h"
 #include "llvm/Config/config.h"   // for HAVE_LINK_R
 #include "llvm/System/Program.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileUtilities.h"
 #include <fstream>
 #include <iostream>
 using namespace llvm;
 
+namespace {
+  cl::opt<std::string>
+  RSHHost("rsh-host",
+          cl::desc("Remote execution (rsh) host"));
+
+  cl::opt<std::string>
+  RSHUser("rsh-user",
+          cl::desc("Remote execution (rsh) user id"));
+}
+
 ToolExecutionError::~ToolExecutionError() throw() { }
 
 /// RunProgramWithTimeout - This function provides an alternate interface to the
@@ -32,14 +43,23 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath,
                                  const sys::Path &StdInFile,
                                  const sys::Path &StdOutFile,
                                  const sys::Path &StdErrFile,
-                                 unsigned NumSeconds = 0) {
+                                 unsigned NumSeconds = 0,
+                                 unsigned MemoryLimit = 0) {
   const sys::Path* redirects[3];
   redirects[0] = &StdInFile;
   redirects[1] = &StdOutFile;
   redirects[2] = &StdErrFile;
+                                   
+  if (0) {
+    std::cerr << "RUN:";
+    for (unsigned i = 0; Args[i]; ++i)
+      std::cerr << " " << Args[i];
+    std::cerr << "\n";
+  }
 
   return
-    sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, NumSeconds);
+    sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
+                                 NumSeconds, MemoryLimit);
 }
 
 
@@ -53,9 +73,13 @@ static void ProcessFailure(sys::Path ProgPath, const char** Args) {
 
   // Rerun the compiler, capturing any error messages to print them.
   sys::Path ErrorFilename("error_messages");
-  ErrorFilename.makeUnique();
+  std::string ErrMsg;
+  if (ErrorFilename.makeUnique(true, &ErrMsg)) {
+    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+    exit(1);
+  }
   RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
-                        ErrorFilename); // FIXME: check return code
+                        ErrorFilename); // FIXME: check return code ?
 
   // Print out the error messages generated by GCC if possible...
   std::ifstream ErrorFile(ErrorFilename.c_str());
@@ -91,7 +115,8 @@ namespace {
                                const std::vector<std::string> &GCCArgs,
                                const std::vector<std::string> &SharedLibs =
                                std::vector<std::string>(),
-                               unsigned Timeout = 0);
+                               unsigned Timeout = 0,
+                               unsigned MemoryLimit = 0);
   };
 }
 
@@ -101,7 +126,8 @@ int LLI::ExecuteProgram(const std::string &Bytecode,
                         const std::string &OutputFile,
                         const std::vector<std::string> &GCCArgs,
                         const std::vector<std::string> &SharedLibs,
-                        unsigned Timeout) {
+                        unsigned Timeout,
+                        unsigned MemoryLimit) {
   if (!SharedLibs.empty())
     throw ToolExecutionError("LLI currently does not support "
                              "loading shared libraries.");
@@ -131,7 +157,7 @@ int LLI::ExecuteProgram(const std::string &Bytecode,
         );
   return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
-      Timeout);
+      Timeout, MemoryLimit);
 }
 
 // LLI create method - Try to find the LLI executable
@@ -151,9 +177,14 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
 //===----------------------------------------------------------------------===//
 // LLC Implementation of AbstractIntepreter interface
 //
-void LLC::OutputAsm(const std::string &Bytecode, sys::Path &OutputAsmFile) {
+GCC::FileType LLC::OutputCode(const std::string &Bytecode, 
+                              sys::Path &OutputAsmFile) {
   sys::Path uniqueFile(Bytecode+".llc.s");
-  uniqueFile.makeUnique();
+  std::string ErrMsg;
+  if (uniqueFile.makeUnique(true, &ErrMsg)) {
+    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+    exit(1);
+  }
   OutputAsmFile = uniqueFile;
   std::vector<const char *> LLCArgs;
   LLCArgs.push_back (LLCPath.c_str());
@@ -177,11 +208,13 @@ void LLC::OutputAsm(const std::string &Bytecode, sys::Path &OutputAsmFile) {
   if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
                             sys::Path(), sys::Path(), sys::Path()))
     ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
+
+  return GCC::AsmFile;                              
 }
 
 void LLC::compileProgram(const std::string &Bytecode) {
   sys::Path OutputAsmFile;
-  OutputAsm(Bytecode, OutputAsmFile);
+  OutputCode(Bytecode, OutputAsmFile);
   OutputAsmFile.eraseFromDisk();
 }
 
@@ -191,10 +224,11 @@ int LLC::ExecuteProgram(const std::string &Bytecode,
                         const std::string &OutputFile,
                         const std::vector<std::string> &ArgsForGCC,
                         const std::vector<std::string> &SharedLibs,
-                        unsigned Timeout) {
+                        unsigned Timeout,
+                        unsigned MemoryLimit) {
 
   sys::Path OutputAsmFile;
-  OutputAsm(Bytecode, OutputAsmFile);
+  OutputCode(Bytecode, OutputAsmFile);
   FileRemover OutFileRemover(OutputAsmFile);
 
   std::vector<std::string> GCCArgs(ArgsForGCC);
@@ -202,7 +236,8 @@ int LLC::ExecuteProgram(const std::string &Bytecode,
 
   // Assuming LLC worked, compile the result with GCC and run it.
   return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
-                             InputFile, OutputFile, GCCArgs, Timeout);
+                             InputFile, OutputFile, GCCArgs,
+                             Timeout, MemoryLimit);
 }
 
 /// createLLC - Try to find the LLC executable
@@ -247,7 +282,8 @@ namespace {
                                  std::vector<std::string>(),
                                const std::vector<std::string> &SharedLibs =
                                  std::vector<std::string>(), 
-                               unsigned Timeout =0 );
+                               unsigned Timeout =0,
+                               unsigned MemoryLimit =0);
   };
 }
 
@@ -257,7 +293,8 @@ int JIT::ExecuteProgram(const std::string &Bytecode,
                         const std::string &OutputFile,
                         const std::vector<std::string> &GCCArgs,
                         const std::vector<std::string> &SharedLibs,
-                        unsigned Timeout) {
+                        unsigned Timeout,
+                        unsigned MemoryLimit) {
   if (!GCCArgs.empty())
     throw ToolExecutionError("JIT does not support GCC Arguments.");
   // Construct a vector of parameters, incorporating those from the command-line
@@ -288,7 +325,7 @@ int JIT::ExecuteProgram(const std::string &Bytecode,
   DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
   return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
       sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
-      Timeout);
+      Timeout, MemoryLimit);
 }
 
 /// createJIT - Try to find the LLI executable
@@ -305,9 +342,14 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
   return 0;
 }
 
-void CBE::OutputC(const std::string &Bytecode, sys::Path& OutputCFile) {
+GCC::FileType CBE::OutputCode(const std::string &Bytecode,
+                              sys::Path &OutputCFile) {
   sys::Path uniqueFile(Bytecode+".cbe.c");
-  uniqueFile.makeUnique();
+  std::string ErrMsg;
+  if (uniqueFile.makeUnique(true, &ErrMsg)) {
+    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+    exit(1);
+  }
   OutputCFile = uniqueFile;
   std::vector<const char *> LLCArgs;
   LLCArgs.push_back (LLCPath.c_str());
@@ -332,11 +374,12 @@ void CBE::OutputC(const std::string &Bytecode, sys::Path& OutputCFile) {
   if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
                             sys::Path()))
     ProcessFailure(LLCPath, &LLCArgs[0]);
+  return GCC::CFile;
 }
 
 void CBE::compileProgram(const std::string &Bytecode) {
   sys::Path OutputCFile;
-  OutputC(Bytecode, OutputCFile);
+  OutputCode(Bytecode, OutputCFile);
   OutputCFile.eraseFromDisk();
 }
 
@@ -346,16 +389,18 @@ int CBE::ExecuteProgram(const std::string &Bytecode,
                         const std::string &OutputFile,
                         const std::vector<std::string> &ArgsForGCC,
                         const std::vector<std::string> &SharedLibs,
-                        unsigned Timeout) {
+                        unsigned Timeout,
+                        unsigned MemoryLimit) {
   sys::Path OutputCFile;
-  OutputC(Bytecode, OutputCFile);
+  OutputCode(Bytecode, OutputCFile);
 
   FileRemover CFileRemove(OutputCFile);
 
   std::vector<std::string> GCCArgs(ArgsForGCC);
   GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
   return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
-                             InputFile, OutputFile, GCCArgs, Timeout);
+                             InputFile, OutputFile, GCCArgs,
+                             Timeout, MemoryLimit);
 }
 
 /// createCBE - Try to find the 'llc' executable
@@ -388,7 +433,8 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
                         const std::string &InputFile,
                         const std::string &OutputFile,
                         const std::vector<std::string> &ArgsForGCC,
-                        unsigned Timeout ) {
+                        unsigned Timeout,
+                        unsigned MemoryLimit) {
   std::vector<const char*> GCCArgs;
 
   GCCArgs.push_back(GCCPath.c_str());
@@ -409,7 +455,11 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
   GCCArgs.push_back("none");
   GCCArgs.push_back("-o");
   sys::Path OutputBinary (ProgramFile+".gcc.exe");
-  OutputBinary.makeUnique();
+  std::string ErrMsg;
+  if (OutputBinary.makeUnique(true, &ErrMsg)) {
+    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+    exit(1);
+  }
   GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
 
   // Add any arguments intended for GCC. We locate them here because this is
@@ -430,6 +480,11 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
   GCCArgs.push_back(0);                    // NULL terminator
 
   std::cout << "<gcc>" << std::flush;
+  DEBUG(std::cerr << "\nAbout to run:\t";
+        for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
+          std::cerr << " " << GCCArgs[i];
+        std::cerr << "\n";
+        );
   if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
         sys::Path())) {
     ProcessFailure(GCCPath, &GCCArgs[0]);
@@ -438,7 +493,22 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
 
   std::vector<const char*> ProgramArgs;
 
-  ProgramArgs.push_back(OutputBinary.c_str());
+  if (RSHPath.isEmpty())
+    ProgramArgs.push_back(OutputBinary.c_str());
+  else {
+    ProgramArgs.push_back(RSHPath.c_str());
+    ProgramArgs.push_back(RSHHost.c_str());
+    ProgramArgs.push_back("-l");
+    ProgramArgs.push_back(RSHUser.c_str());
+
+    char* env_pwd = getenv("PWD");
+    std::string Exec = "cd ";
+    Exec += env_pwd;
+    Exec += "; ./";
+    Exec += OutputBinary.c_str();
+    ProgramArgs.push_back(Exec.c_str());
+  }
+
   // 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());
@@ -453,16 +523,26 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
         );
 
   FileRemover OutputBinaryRemover(OutputBinary);
-  return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
-      sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
-      Timeout);
+
+  if (RSHPath.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],
+        sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+        Timeout, MemoryLimit);
 }
 
 int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
                           std::string &OutputFile,
                           const std::vector<std::string> &ArgsForGCC) {
   sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
-  uniqueFilename.makeUnique();
+  std::string ErrMsg;
+  if (uniqueFilename.makeUnique(true, &ErrMsg)) {
+    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+    exit(1);
+  }
   OutputFile = uniqueFilename.toString();
 
   std::vector<const char*> GCCArgs;
@@ -513,6 +593,11 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
   
 
   std::cout << "<gcc>" << std::flush;
+  DEBUG(std::cerr << "\nAbout to run:\t";
+        for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
+          std::cerr << " " << GCCArgs[i];
+        std::cerr << "\n";
+        );
   if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
                             sys::Path())) {
     ProcessFailure(GCCPath, &GCCArgs[0]);
@@ -530,6 +615,10 @@ GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {
     return 0;
   }
 
+  sys::Path RSHPath;
+  if (!RSHHost.empty())
+    RSHPath = FindExecutable("rsh", ProgramPath);
+
   Message = "Found gcc: " + GCCPath.toString() + "\n";
-  return new GCC(GCCPath);
+  return new GCC(GCCPath, RSHPath);
 }