Identify llvm bit-code file that is causing linking failure in LTO mode.
authorDevang Patel <dpatel@apple.com>
Thu, 24 Jul 2008 00:34:11 +0000 (00:34 +0000)
committerDevang Patel <dpatel@apple.com>
Thu, 24 Jul 2008 00:34:11 +0000 (00:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53972 91177308-0d34-0410-b5e6-96231b3b80d8

tools/lto-bugpoint/LTOBugPoint.cpp
tools/lto-bugpoint/LTOBugPoint.h

index d54b28d251f90705287addb664816adb8bf2d552..587e360bc62f0bb568b6b26b1b1375e827e3f5a4 100644 (file)
 
 using namespace llvm;
 using namespace Reloc;
+
+/// printBitVector - Helper function.
+static void printBitVector(BitVector &BV, const char *Title) {
+  std::cerr << Title;
+  for (unsigned i = 0, e = BV.size(); i < e; i++) {
+    if (BV[i])
+      std::cerr << " " << i;
+  }
+  std::cerr << "\n";
+}
+
+/// printBitVector - Helper function.
+static void printBitVectorFiles(BitVector &BV, const char *Title,
+                                SmallVector<std::string, 16> &InFiles) {
+  std::cerr << Title << "\n";
+  for (unsigned i = 0, e = BV.size(); i < e; i++) {
+    if (BV[i])
+      std::cerr << "\t" << InFiles[i] << "\n";
+  }
+}
+
 /// LTOBugPoint -- Constructor. Popuate list of linker options and
 /// list of linker input files.
 LTOBugPoint::LTOBugPoint(std::istream &args, std::istream &ins) {
@@ -46,6 +67,9 @@ LTOBugPoint::LTOBugPoint(std::istream &args, std::istream &ins) {
     LinkerInputFiles.push_back(inFile);
 
   TempDir = sys::Path::GetTemporaryDirectory();
+
+  // FIXME - Use command line option to set this.
+  findLinkingFailure = true;
 }
 
 LTOBugPoint::~LTOBugPoint() {
@@ -59,48 +83,62 @@ LTOBugPoint::findTroubleMakers(SmallVector<std::string, 4> &TroubleMakers,
                                std::string &Script) {
 
   // Reproduce original error.
-  if (!relinkProgram(LinkerInputFiles) || !reproduceProgramError(Script)) {
-    ErrMsg += " Unable to reproduce original error!";
+  if (!relinkProgram(LinkerInputFiles) && !findLinkingFailure) {
+    ErrMsg = " Unable to reproduce original error!";
+    return false;
+  }
+
+  if (!findLinkingFailure && !reproduceProgramError(Script)) {
+    ErrMsg = " Unable to reproduce original error!";
     return false;
   }
     
   // Build native object files set.
-  bool bitcodeFileSeen = false;
   unsigned Size = LinkerInputFiles.size();
+  BCFiles.resize(Size);
+  ConfirmedClean.resize(Size);
+  ConfirmedGuilty.resize(Size);
   for (unsigned I = 0; I < Size; ++I) {
     std::string &FileName = LinkerInputFiles[I];
     sys::Path InputFile(FileName.c_str());
     if (InputFile.isDynamicLibrary() || InputFile.isArchive()) {
-      ErrMsg = "Unable to handle input file ";
-      ErrMsg += FileName;
+      ErrMsg = "Unable to handle input file " + FileName;
       return false;
     }
     else if (InputFile.isBitcodeFile()) {
-      bitcodeFileSeen = true;
+      BCFiles.set(I);
       if (getNativeObjectFile(FileName) == false)
         return false;
     }
-    else
+    else {
+      // Original native object input files are always clean.
+      ConfirmedClean.set(I);
       NativeInputFiles.push_back(FileName);
+    }
   }
 
-  if (!bitcodeFileSeen) {
+  if (BCFiles.none()) {
     ErrMsg = "Unable to help!";
-    ErrMsg += " Need at least one input file that contains llvm bitcode";
+    ErrMsg = " Need at least one input file that contains llvm bitcode";
     return false;
   }
 
   // Try to reproduce error using native object files first. If the error
   // occurs then this is not a LTO error.
   if (!relinkProgram(NativeInputFiles))  {
-    ErrMsg += " Unable to link the program using all native object files!";
+    ErrMsg = " Unable to link the program using all native object files!";
     return false;
   }
-  if (reproduceProgramError(Script) == true) {
-    ErrMsg += " Unable to fix program error using all native object files!";
+  if (!findLinkingFailure && reproduceProgramError(Script) == true) {
+    ErrMsg = " Unable to fix program error using all native object files!";
     return false;
   }
 
+  printBitVector(BCFiles, "Initial set of llvm bitcode files");
+  identifyTroubleMakers(BCFiles);
+  printBitVectorFiles(ConfirmedGuilty, 
+                      "Identified minimal set of bitcode files!",
+                      LinkerInputFiles);
   return true;
 }
 
@@ -192,8 +230,7 @@ bool LTOBugPoint::getNativeObjectFile(std::string &FileName) {
   MemoryBuffer *Buffer
     = MemoryBuffer::getFile(FileName.c_str(), &ErrMsg);
   if (!Buffer) {
-    ErrMsg = "Unable to read ";
-    ErrMsg += FileName;
+    ErrMsg = "Unable to read " + FileName;
     return false;
   }
   M.reset(ParseBitcodeFile(Buffer, &ErrMsg));
@@ -261,6 +298,7 @@ bool LTOBugPoint::getNativeObjectFile(std::string &FileName) {
   }
 
   AsmFile.eraseFromDisk();
+  NativeInputFiles.push_back(NativeFile.c_str());
   return true;
 }
 
@@ -289,10 +327,9 @@ bool LTOBugPoint::relinkProgram(llvm::SmallVector<std::string, 16> &InFiles) {
   Args.push_back(0);
   
   if (sys::Program::ExecuteAndWait(linker, &Args[0], 0, 0, 0, 0, &ErrMsg)) {
-    ErrMsg += "error while linking program";
-    return false;
+      ErrMsg = "error while linking program";
+      return false;
   }
-
   return true;
 }
 
@@ -325,3 +362,70 @@ bool LTOBugPoint::reproduceProgramError(std::string &Script) {
 
   return false;
 }
+
+/// identifyTroubleMakers - Identify set of bit code files that are causing
+/// the error. This is a recursive function.
+void LTOBugPoint::identifyTroubleMakers(llvm::BitVector &In) {
+
+  assert (In.size() == LinkerInputFiles.size() 
+          && "Invalid identifyTroubleMakers input!\n");
+
+  printBitVector(In, "Processing files ");
+  BitVector CandidateVector;
+  CandidateVector.resize(LinkerInputFiles.size());
+
+  // Process first half
+  unsigned count = 0;
+  for (unsigned i = 0, e =  In.size(); i < e; ++i) {
+    if (!ConfirmedClean[i]) {
+      count++;
+      CandidateVector.set(i);
+    }
+    if (count >= In.count()/2)
+      break;
+  }
+
+  if (CandidateVector.none())
+    return;
+
+  printBitVector(CandidateVector, "Candidate vector ");
+
+  // Reproduce the error using native object files for candidate files.
+  SmallVector<std::string, 16> CandidateFiles;
+  for (unsigned i = 0, e = CandidateVector.size(); i < e; ++i) {
+    if (CandidateVector[i] || ConfirmedClean[i])
+      CandidateFiles.push_back(NativeInputFiles[i]);
+    else
+      CandidateFiles.push_back(LinkerInputFiles[i]);
+  }
+
+  bool result = relinkProgram(CandidateFiles);
+  if (findLinkingFailure) {
+    if (result == true) {
+      // Candidate files are suspected.
+      if (CandidateVector.count() == 1) {
+        ConfirmedGuilty.set(CandidateVector.find_first());
+        return;
+      }
+      else
+        identifyTroubleMakers(CandidateVector);
+    } else {
+      // Candidate files are not causing this error.
+      for (unsigned i = 0, e = CandidateVector.size(); i < e; ++i) {
+        if (CandidateVector[i])
+          ConfirmedClean.set(i);
+      }
+    }
+  } else {
+    std::cerr << "FIXME : Not yet implemented!\n";
+  }
+
+  // Process remaining cadidates
+  CandidateVector.clear();
+  CandidateVector.resize(LinkerInputFiles.size());
+  for (unsigned i = 0, e = LinkerInputFiles.size(); i < e; ++i) {
+    if (!ConfirmedClean[i] && !ConfirmedGuilty[i])
+      CandidateVector.set(i);
+  }
+  identifyTroubleMakers(CandidateVector);
+}
index 5f1b5cce2badafb9afc8c14d33e1784c157fa490..417912430966f047f185dcd8cd90694d3d530ed0 100644 (file)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/Module.h"
 #include "llvm/System/Path.h"
 #include <string>
@@ -30,7 +31,8 @@ class LTOBugPoint {
                        std::string &Script);
 
   /// getNativeObjectFile - Generate native object file based from llvm
-  /// bitcode file. Return false in case of an error.
+  /// bitcode file. Return false in case of an error. Generated native
+  /// object file is inserted in to the NativeInputFiles list.
   bool getNativeObjectFile(std::string &FileName);
 
   std::string &getErrMsg() { return ErrMsg; }
@@ -49,10 +51,26 @@ class LTOBugPoint {
   /// at index 4 in NativeInputFiles is corresponding native object file.
   llvm::SmallVector<std::string, 16> NativeInputFiles;
 
+  /// BCFiles - This bit vector tracks input bitcode files.
+  llvm::BitVector BCFiles;
+
+  /// ConfirmedClean - This bit vector tracks input files that are confirmed
+  /// to be clean.
+  llvm::BitVector ConfirmedClean;
+
+  /// ConfirmedGuilty - This bit vector tracks input files that are confirmed
+  /// to contribute to the bug being investigated.
+  llvm::BitVector ConfirmedGuilty;
   std::string getFeatureString(const char *TargetTriple);
   std::string ErrMsg;
 
   llvm::sys::Path TempDir;
+
+  /// findLinkingFailure - If true, investigate link failure bugs when
+  /// one or more linker input files are llvm bitcode files. If false,
+  /// investigate optimization or code generation bugs in LTO mode.
+  bool findLinkingFailure;
+
 private:
   /// assembleBitcode - Generate assembly code from the module. Return false
   /// in case of an error.
@@ -63,4 +81,8 @@ private:
 
   /// reproduceProgramError - Validate program using user provided script.
   bool reproduceProgramError(std::string &Script);
+
+  /// identifyTroubleMakers - Identify set of inputs from the given 
+  /// bitvector that are causing the bug under investigation.
+  void identifyTroubleMakers(llvm::BitVector &In);
 };