synchronizeICache removeed from TargetJITInfo.
[oota-llvm.git] / tools / bugpoint / ExecutionDriver.cpp
index 8044f504a43f5ded933c97690e6e59fca82ff697..453833eb8dff9a12b27537aa49857f28e60be809 100644 (file)
@@ -1,10 +1,10 @@
 //===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===//
-// 
+//
 //                     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 contains code used to execute the program utilizing one of the
 //===----------------------------------------------------------------------===//
 
 #include "BugDriver.h"
-#include "llvm/Support/ToolRunner.h"
+#include "ToolRunner.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/SystemUtils.h"
 #include <fstream>
+#include <iostream>
+
 using namespace llvm;
 
 namespace {
@@ -29,6 +31,13 @@ namespace {
     AutoPick, RunLLI, RunJIT, RunLLC, RunCBE
   };
 
+  cl::opt<double>
+  AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
+               cl::init(0.0));
+  cl::opt<double>
+  RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
+               cl::init(0.0));
+
   cl::opt<OutputType>
   InterpreterSel(cl::desc("Specify how LLVM code should be executed:"),
                  cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
@@ -54,10 +63,9 @@ namespace {
                 cl::desc("Additional shared objects to load "
                          "into executing programs"));
 
-  cl::opt<unsigned>
-  TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"),
-               cl::desc("Number of seconds program is allowed to run before it "
-                        "is killed (default is 300s), 0 disables timeout"));
+  cl::list<std::string>
+    AdditionalLinkerArgs("Xlinker", 
+      cl::desc("Additional arguments to pass to the linker"));
 }
 
 namespace llvm {
@@ -195,7 +203,8 @@ std::string BugDriver::executeProgram(std::string OutputFile,
   }
 
   // Remove the temporary bytecode file when we are done.
-  FileRemover BytecodeFileRemover(sys::Path(BytecodeFile), CreatedBytecode);
+  sys::Path BytecodePath (BytecodeFile);
+  FileRemover BytecodeFileRemover(BytecodePath, CreatedBytecode);
 
   if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
 
@@ -209,9 +218,19 @@ std::string BugDriver::executeProgram(std::string OutputFile,
   if (!SharedObj.empty())
     SharedObjs.push_back(SharedObj);
 
-  // Actually execute the program!
-  int RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
-                                  OutputFile, SharedObjs, TimeoutValue);
+  
+  // If this is an LLC or CBE run, then the GCC compiler might get run to 
+  // compile the program. If so, we should pass the user's -Xlinker options
+  // as the GCCArgs.
+  int RetVal = 0;
+  if (InterpreterSel == RunLLC || InterpreterSel == RunCBE)
+    RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
+                                OutputFile, AdditionalLinkerArgs, SharedObjs, 
+                                Timeout);
+  else 
+    RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
+                                OutputFile, std::vector<std::string>(), 
+                                SharedObjs, Timeout);
 
   if (RetVal == -1) {
     std::cerr << "<timeout>";
@@ -268,12 +287,12 @@ std::string BugDriver::compileSharedObject(const std::string &BytecodeFile) {
 #endif
 
   std::string SharedObjectFile;
-  if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile, 
-                            SharedObjectFile))
+  if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile,
+                            SharedObjectFile, AdditionalLinkerArgs))
     exit(1);
 
   // Remove the intermediate C file
-  OutputCFile.destroyFile();
+  OutputCFile.eraseFromDisk();
 
   return "./" + SharedObjectFile;
 }
@@ -289,32 +308,35 @@ bool BugDriver::diffProgram(const std::string &BytecodeFile,
   bool ProgramExitedNonzero;
 
   // Execute the program, generating an output file...
-  sys::Path Output (executeProgram("", BytecodeFile, SharedObject, 0,
+  sys::Path Output(executeProgram("", BytecodeFile, SharedObject, 0,
                                       &ProgramExitedNonzero));
 
   // If we're checking the program exit code, assume anything nonzero is bad.
   if (CheckProgramExitCode && ProgramExitedNonzero) {
-    Output.destroyFile();
-    if (RemoveBytecode) 
-      sys::Path(BytecodeFile).destroyFile();
+    Output.eraseFromDisk();
+    if (RemoveBytecode)
+      sys::Path(BytecodeFile).eraseFromDisk();
     return true;
   }
 
   std::string Error;
   bool FilesDifferent = false;
-  if (DiffFiles(ReferenceOutputFile, Output.toString(), &Error)) {
-    if (!Error.empty()) {
+  if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
+                                        sys::Path(Output.toString()),
+                                        AbsTolerance, RelTolerance, &Error)) {
+    if (Diff == 2) {
       std::cerr << "While diffing output: " << Error << '\n';
       exit(1);
     }
     FilesDifferent = true;
   }
-  
+
   // Remove the generated output.
-  Output.destroyFile();
+  Output.eraseFromDisk();
 
   // Remove the bytecode file if we are supposed to.
-  if (RemoveBytecode) sys::Path(BytecodeFile).destroyFile();
+  if (RemoveBytecode)
+    sys::Path(BytecodeFile).eraseFromDisk();
   return FilesDifferent;
 }