]> granicus.if.org Git - llvm/commitdiff
Implement the start of the miscompilation detection stuff
authorChris Lattner <sabre@nondot.org>
Mon, 23 Dec 2002 23:49:59 +0000 (23:49 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 23 Dec 2002 23:49:59 +0000 (23:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5119 91177308-0d34-0410-b5e6-96231b3b80d8

tools/bugpoint/BugDriver.cpp
tools/bugpoint/BugDriver.h
tools/bugpoint/CrashDebugger.cpp
tools/bugpoint/Makefile
tools/bugpoint/OptimizerDriver.cpp

index 0343f6381d604b6551f365ba89de7fee2e70785e..c204ab45b29a3b758b4f9dc6644133031dcdcf5d 100644 (file)
@@ -82,19 +82,3 @@ bool BugDriver::run() {
   else
     return debugMiscompilation();
 }
-
-
-/// debugMiscompilation - This method is used when the passes selected are not
-/// crashing, but the generated output is semantically different from the
-/// input.
-///
-bool BugDriver::debugMiscompilation() {
-  std::cout << "*** Debugging miscompilation!\n";
-  std::cerr << "Sorry, bugpoint cannot debug a miscompilation yet!\n";
-
-  // If no reference output was specified, run the program without optimizations
-  // to get a reference output.
-  //
-
-  return true;
-}
index f419249afa079ebbe8dd1d0ef37c4d44a88316ca..6398366d8cfbeea45db49b4943dbd14c26de2185 100644 (file)
 class PassInfo;
 class Module;
 class Function;
+class AbstractInterpreter;
 
 class BugDriver {
   const std::string ToolName;  // Name of bugpoint
   Module *Program;             // The raw program, linked together
   std::vector<const PassInfo*> PassesToRun;
+  AbstractInterpreter *Interpreter;   // How to run the program
 public:
-  BugDriver(const char *toolname) : ToolName(toolname), Program(0) {}
+  BugDriver(const char *toolname)
+    : ToolName(toolname), Program(0), Interpreter(0) {}
+
+  const std::string &getToolName() const { return ToolName; }
 
   // Set up methods... these methods are used to copy information about the
   // command line arguments into instance variables of BugDriver.
@@ -51,20 +56,25 @@ public:
   /// input.
   bool debugMiscompilation();
 
+  /// debugPassMiscompilation - This method is called when the specified pass
+  /// miscompiles Program as input.  It tries to reduce the testcase to
+  /// something that smaller that still miscompiles the program.
+  /// ReferenceOutput contains the filename of the file containing the output we
+  /// are to match.
+  ///
+  bool debugPassMiscompilation(const PassInfo *ThePass,
+                              const std::string &ReferenceOutput);
+
 private:
   /// ParseInputFile - Given a bytecode or assembly input filename, parse and
   /// return it, or return null if not possible.
   ///
   Module *ParseInputFile(const std::string &InputFilename) const;
 
-  /// removeFile - Delete the specified file
-  ///
-  void removeFile(const std::string &Filename) const;
-
   /// writeProgramToFile - This writes the current "Program" to the named
   /// bytecode file.  If an error occurs, true is returned.
   ///
-  bool writeProgramToFile(const std::string &Filename) const;
+  bool writeProgramToFile(const std::string &Filename, Module *M = 0) const;
 
 
   /// EmitProgressBytecode - This function is used to output the current Program
@@ -78,10 +88,11 @@ private:
   /// otherwise return false.  If DeleteOutput is set to true, the bytecode is
   /// deleted on success, and the filename string is undefined.  This prints to
   /// cout a single line message indicating whether compilation was successful
-  /// or failed.
+  /// or failed, unless Quiet is set.
   ///
   bool runPasses(const std::vector<const PassInfo*> &PassesToRun,
-                 std::string &OutputFilename, bool DeleteOutput = false) const;
+                 std::string &OutputFilename, bool DeleteOutput = false,
+                bool Quiet = false) const;
 
   /// runPasses - Just like the method above, but this just returns true or
   /// false indicating whether or not the optimizer crashed on the specified
@@ -94,6 +105,7 @@ private:
   }
 
   /// runPass - Run only the specified pass on the program.
+  ///
   bool runPass(const PassInfo *P, bool DeleteOutput = true) const {
     return runPasses(std::vector<const PassInfo*>(1, P), DeleteOutput);
   }
@@ -102,8 +114,27 @@ private:
   /// (non-external) function from the current program, slim down the module,
   /// and then return it.  This does not modify Program at all, it modifies a
   /// copy, which it returns.
+  ///
   Module *extractFunctionFromModule(Function *F) const;
 
+  /// initializeExecutionEnvironment - This method is used to set up the
+  /// environment for executing LLVM programs.
+  ///
+  bool initializeExecutionEnvironment();
+
+  /// executeProgram - This method runs "Program", capturing the output of the
+  /// program to a file, returning the filename of the file.  A recommended
+  /// filename may be optionally specified.
+  ///
+  std::string executeProgram(std::string RequestedOutputFilename = "",
+                            std::string Bytecode = "");
+
+  /// diffProgram - This method executes the specified module and diffs the
+  /// output against the file specified by ReferenceOutputFile.  If the output
+  /// is different, true is returned.
+  ///
+  bool diffProgram(const std::string &ReferenceOutputFile,
+                  const std::string &BytecodeFile = "");
 };
 
 #endif
index 3c4fa2dd47901845012a67cd7b79b18c5d7771d2..c69ca453621d71a618b5381ce5b96de0f8d7ce6b 100644 (file)
@@ -5,6 +5,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "BugDriver.h"
+#include "SystemUtils.h"
 #include "llvm/Module.h"
 #include "llvm/Bytecode/Writer.h"
 #include "llvm/Pass.h"
@@ -44,8 +45,7 @@ bool BugDriver::debugCrash() {
             << "': " << CrashingPass->getPassName() << "\n";
 
   // Compile the program with just the passes that don't crash.
-  if (LastToPass != 0) {
-    // Don't bother doing this if the first pass crashes...
+  if (LastToPass != 0) { // Don't bother doing this if the first pass crashes...
     std::vector<const PassInfo*> P(PassesToRun.begin(), 
                                    PassesToRun.begin()+LastToPass);
     std::string Filename;
@@ -87,7 +87,7 @@ bool BugDriver::debugPassCrash(const PassInfo *Pass) {
 
   if (CountFunctions(Program) > 1) {
     // Attempt to reduce the input program down to a single function that still
-    // crashes.
+    // crashes.  Do this by removing everything except for that one function...
     //
     std::cout << "\n*** Attempting to reduce the testcase to one function\n";
 
@@ -116,5 +116,16 @@ bool BugDriver::debugPassCrash(const PassInfo *Pass) {
       }
   }
 
+  if (CountFunctions(Program) > 1) {
+    std::cout << "\n*** Couldn't reduce testcase to one function.\n"
+             << "    Attempting to remove individual functions.\n";
+    std::cout << "XXX Individual function removal unimplemented!\n";
+  }
+
+  // Now that we have deleted the functions that are unneccesary for the
+  // program, try to remove instructions and basic blocks that are not neccesary
+  // to cause the crash.
+  //
+  
   return false;
 }
index 43f1c91d3006d399bc1c2b8a8b7539c73f031755..a648a3c4759d7c3670584e65cf857d892d2dea3f 100644 (file)
@@ -2,10 +2,10 @@ LEVEL = ../..
 
 TOOLNAME = bugpoint
 
-OPTLIBS  = instrument profpaths scalaropts ipo
-ANALIBS  = datastructure ipa target.a analysis
+#OPTLIBS  = instrument profpaths 
+ANALIBS  = datastructure ipa target.a 
 
-USEDLIBS = ipo scalaropts $(ANALIBS) \
+USEDLIBS = ipo scalaropts analysis $(OPTLIBS) $(ANALIBS) \
            transformutils asmparser bcreader bcwriter vmcore support
 
 TOOLLINKOPTS = -ldl
index 26a6ae70fe64fbb806b78f7c74bca1ce6053ec10..aae5791935ce483aa99b38b1c23234a6960382b4 100644 (file)
@@ -9,6 +9,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "BugDriver.h"
+#include "SystemUtils.h"
 #include "llvm/PassManager.h"
 #include "llvm/Analysis/Verifier.h"
 #include "llvm/Bytecode/WriteBytecodePass.h"
 #include <stdlib.h>
 #include <fstream>
 
-/// removeFile - Delete the specified file
-///
-void BugDriver::removeFile(const std::string &Filename) const {
-  unlink(Filename.c_str());
-}
-
 /// writeProgramToFile - This writes the current "Program" to the named bytecode
 /// file.  If an error occurs, true is returned.
 ///
-bool BugDriver::writeProgramToFile(const std::string &Filename) const {
+bool BugDriver::writeProgramToFile(const std::string &Filename,
+                                  Module *M) const {
   std::ofstream Out(Filename.c_str());
   if (!Out.good()) return true;
-
-  WriteBytecodeToFile(Program, Out);
+  WriteBytecodeToFile(M ? M : Program, Out);
   return false;
 }
 
@@ -50,7 +45,7 @@ void BugDriver::EmitProgressBytecode(const PassInfo *Pass,
     return;
   }
 
-  std::cout << "Emitted bytecode to 'bugpoint-" << Filename << ".bc'\n";
+  std::cout << "Emitted bytecode to '" << Filename << "'\n";
   std::cout << "\n*** You can reproduce the problem with: ";
 
   unsigned PassType = Pass->getPassType();
@@ -101,23 +96,11 @@ static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes,
 /// failed.
 ///
 bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
-                          std::string &OutputFilename, bool DeleteOutput) const{
+                          std::string &OutputFilename, bool DeleteOutput,
+                         bool Quiet) const{
   std::cout << std::flush;
+  OutputFilename = getUniqueFilename("bugpoint-output.bc");
 
-  // Agree on a temporary file name to use....
-  char FNBuffer[] = "bugpoint-output.bc-XXXXXX";
-  int TempFD;
-  if ((TempFD = mkstemp(FNBuffer)) == -1) {
-    std::cerr << ToolName << ": ERROR: Cannot create temporary"
-              << " file in the current directory!\n";
-    exit(1);
-  }
-  OutputFilename = FNBuffer;
-
-  // We don't need to hold the temp file descriptor... we will trust that noone
-  // will overwrite/delete the file while we are working on it...
-  close(TempFD);
-  
   pid_t child_pid;
   switch (child_pid = fork()) {
   case -1:    // Error occurred
@@ -143,7 +126,7 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
   if (DeleteOutput)
     removeFile(OutputFilename);
 
-  std::cout << (Status ? "Crashed!\n" : "Success!\n");
+  if (!Quiet) std::cout << (Status ? "Crashed!\n" : "Success!\n");
 
   // Was the child successful?
   return Status != 0;