Revise comment and error message for the Bug 38 situation. Also, make it
[oota-llvm.git] / tools / bugpoint / CodeGeneratorBug.cpp
index 10f544a69ad35ad967a721177f91792802984639..4da709a3f8cd8790bc5dfd0f490b905a2ecec6ae 100644 (file)
@@ -1,4 +1,11 @@
 //===- CodeGeneratorBug.cpp - Debug code generation bugs ------------------===//
+// 
+//                     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 implements program code generation debugging support.
 //
 #include "Support/FileUtilities.h"
 #include <algorithm>
 #include <set>
+using namespace llvm;
 
-extern cl::list<std::string> InputArgv;
-
-class ReduceMisCodegenFunctions : public ListReducer<Function*> {
-  BugDriver &BD;
-public:
-  ReduceMisCodegenFunctions(BugDriver &bd) : BD(bd) {}
-
-  virtual TestResult doTest(std::vector<Function*> &Prefix,
-                            std::vector<Function*> &Suffix) {
-    if (!Prefix.empty() && TestFuncs(Prefix))
-      return KeepPrefix;
-    if (!Suffix.empty() && TestFuncs(Suffix))
-      return KeepSuffix;
-    return NoFailure;
-  }
-  
-  bool TestFuncs(const std::vector<Function*> &CodegenTest,
-                 bool KeepFiles = false);
-};
+namespace llvm {
+  extern cl::list<std::string> InputArgv;
 
+  class ReduceMisCodegenFunctions : public ListReducer<Function*> {
+    BugDriver &BD;
+  public:
+    ReduceMisCodegenFunctions(BugDriver &bd) : BD(bd) {}
+    
+    virtual TestResult doTest(std::vector<Function*> &Prefix,
+                              std::vector<Function*> &Suffix) {
+      if (!Prefix.empty() && TestFuncs(Prefix))
+        return KeepPrefix;
+      if (!Suffix.empty() && TestFuncs(Suffix))
+        return KeepSuffix;
+      return NoFailure;
+    }
+    
+    bool TestFuncs(const std::vector<Function*> &CodegenTest,
+                   bool KeepFiles = false);
+  };
+}
 
 bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
                                           bool KeepFiles) {
@@ -112,8 +121,10 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
     // Use the function we just added to get addresses of functions we need
     // Iterate over the global declarations in the Safe module
     for (Module::iterator F=SafeModule->begin(),E=SafeModule->end(); F!=E; ++F){
-      if (F->isExternal() && !F->use_empty() && &(*F) != resolverFunc &&
-          F->getIntrinsicID() == 0 /* ignore intrinsics */) {
+      if (F->isExternal() && !F->use_empty() && &*F != resolverFunc &&
+          F->getIntrinsicID() == 0 /* ignore intrinsics */ &&
+          // Don't forward functions which are external in the test module too.
+          !TestModule->getNamedFunction(F->getName())->isExternal()) {
         // If it has a non-zero use list,
         // 1. Add a string constant with its name to the global file
         // The correct type is `const [ NUM x sbyte ]' where NUM is length of
@@ -144,8 +155,8 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
         ResolverArgs.push_back(GEP);
 
         // Insert code at the beginning of the function
-        for (Value::use_iterator i=F->use_begin(), e=F->use_end(); i!=e; ++i) {
-          if (Instruction* Inst = dyn_cast<Instruction>(*i)) {
+        while (!F->use_empty())
+          if (Instruction *Inst = dyn_cast<Instruction>(F->use_back())) {
             // call resolver(GetElementPtr...)
             CallInst *resolve = new CallInst(resolverFunc, ResolverArgs, 
                                              "resolver", Inst);
@@ -156,12 +167,13 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
             // actually use the resolved function
             Inst->replaceUsesOfWith(F, castResolver);
           } else {
-            // FIXME: need to take care of cases where a function is used that
-            // is not an instruction, e.g. global variable initializer...
-            std::cerr << "Non-instruction is using an external function!\n";
+            // FIXME: need to take care of cases where a function is used by
+            // something other than an instruction; e.g., global variable
+            // initializers and constant expressions.
+            std::cerr << "UNSUPPORTED: Non-instruction is using an external "
+                      << "function, " << F->getName() << "().\n";
             abort();
           }
-        }
       }
     }
   }
@@ -251,7 +263,7 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
     for (unsigned i=0, e = InputArgv.size(); i != e; ++i)
       std::cout << " " << InputArgv[i];
     std::cout << "\n";
-    std::cout << "The shared object was created with:\n  llvm-dis -c "
+    std::cout << "The shared object was created with:\n  llc -march=c "
               << SafeModuleBC << " -o temporary.c\n"
               << "  gcc -xc temporary.c -O2 -o " << SharedObject
 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
@@ -317,7 +329,7 @@ namespace {
   };
 }
 
-void DisambiguateGlobalSymbols(Module *M) {
+static void DisambiguateGlobalSymbols(Module *M) {
   // First, try not to cause collisions by minimizing chances of renaming an
   // already-external symbol, so take in external globals and functions as-is.
   Disambiguator D;
@@ -337,8 +349,19 @@ void DisambiguateGlobalSymbols(Module *M) {
 
 
 bool BugDriver::debugCodeGenerator() {
+  if ((void*)cbe == (void*)Interpreter) {
+    std::string Result = executeProgramWithCBE("bugpoint.cbe.out");
+    std::cout << "\n*** The C backend cannot match the reference diff, but it "
+              << "is used as the 'known good'\n    code generator, so I can't"
+              << " debug it.  Perhaps you have a front-end problem?\n    As a"
+              << " sanity check, I left the result of executing the program "
+              << "with the C backend\n    in this file for you: '"
+              << Result << "'.\n";
+    return true;
+  }
+
   // See if we can pin down which functions are being miscompiled...
-  //First, build a list of all of the non-external functions in the program.
+  // First, build a list of all of the non-external functions in the program.
   std::vector<Function*> MisCodegenFunctions;
   for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
     if (!I->isExternal())
@@ -370,15 +393,11 @@ bool BugDriver::debugCodeGenerator() {
     BB->getInstList().push_back(call);
     
     // if the type of old function wasn't void, return value of call
-    ReturnInst *ret;
     if (oldMain->getReturnType() != Type::VoidTy) {
-      ret = new ReturnInst(call);
+      new ReturnInst(call, BB);
     } else {
-      ret = new ReturnInst();
+      new ReturnInst(0, BB);
     }
-
-    // Add the return instruction to the BasicBlock
-    BB->getInstList().push_back(ret);
   }
 
   DisambiguateGlobalSymbols(Program);