Changes in directory llvm/tools/bugpoint:
BugDriver.cpp updated: 1.48 -> 1.49 BugDriver.h updated: 1.46 -> 1.47 CrashDebugger.cpp updated: 1.49 -> 1.50 --- Log message: Fix for PR960: http://llvm.org/PR960 . Improves bugpoint so that it removes global variable initializers as well. This is only a first pass. It can be slow because it clones the module for each pass. An obvious improvement is not to do that. --- Diffs of the changes: (+110 -23) BugDriver.cpp | 10 ++++ BugDriver.h | 5 ++ CrashDebugger.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 110 insertions(+), 23 deletions(-) Index: llvm/tools/bugpoint/BugDriver.cpp diff -u llvm/tools/bugpoint/BugDriver.cpp:1.48 llvm/tools/bugpoint/BugDriver.cpp:1.49 --- llvm/tools/bugpoint/BugDriver.cpp:1.48 Fri Aug 18 03:43:06 2006 +++ llvm/tools/bugpoint/BugDriver.cpp Wed Oct 25 13:36:14 2006 @@ -221,3 +221,13 @@ std::cout << "... <" << Funcs.size() << " total>"; std::cout << std::flush; } + +void llvm::PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs) { + unsigned NumPrint = GVs.size(); + if (NumPrint > 10) NumPrint = 10; + for (unsigned i = 0; i != NumPrint; ++i) + std::cout << " " << GVs[i]->getName(); + if (NumPrint < GVs.size()) + std::cout << "... <" << GVs.size() << " total>"; + std::cout << std::flush; +} Index: llvm/tools/bugpoint/BugDriver.h diff -u llvm/tools/bugpoint/BugDriver.h:1.46 llvm/tools/bugpoint/BugDriver.h:1.47 --- llvm/tools/bugpoint/BugDriver.h:1.46 Fri Sep 15 16:29:15 2006 +++ llvm/tools/bugpoint/BugDriver.h Wed Oct 25 13:36:14 2006 @@ -23,6 +23,7 @@ class PassInfo; class Module; +class GlobalVariable; class Function; class BasicBlock; class AbstractInterpreter; @@ -295,6 +296,10 @@ /// void PrintFunctionList(const std::vector<Function*> &Funcs); +/// PrintGlobalVariableList - prints out list of problematic global variables +/// +void PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs); + // DeleteFunctionBody - "Remove" the function by deleting all of it's basic // blocks, making it external. // Index: llvm/tools/bugpoint/CrashDebugger.cpp diff -u llvm/tools/bugpoint/CrashDebugger.cpp:1.49 llvm/tools/bugpoint/CrashDebugger.cpp:1.50 --- llvm/tools/bugpoint/CrashDebugger.cpp:1.49 Tue Aug 15 11:40:49 2006 +++ llvm/tools/bugpoint/CrashDebugger.cpp Wed Oct 25 13:36:14 2006 @@ -15,12 +15,12 @@ #include "ToolRunner.h" #include "ListReducer.h" #include "llvm/Constant.h" +#include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" #include "llvm/SymbolTable.h" -#include "llvm/Type.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bytecode/Writer.h" #include "llvm/Support/CFG.h" @@ -94,7 +94,81 @@ return NoFailure; } +namespace { + /// ReduceCrashingGlobalVariables - This works by removing the global + /// variable's initializer and seeing if the program still crashes. If it + /// does, then we keep that program and try again. + /// + class ReduceCrashingGlobalVariables : public ListReducer<GlobalVariable*> { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *); + public: + ReduceCrashingGlobalVariables(BugDriver &bd, + bool (*testFn)(BugDriver&, Module*)) + : BD(bd), TestFn(testFn) {} + + virtual TestResult doTest(std::vector<GlobalVariable*>& Prefix, + std::vector<GlobalVariable*>& Kept) { + if (!Kept.empty() && TestGlobalVariables(Kept)) + return KeepSuffix; + + if (!Prefix.empty() && TestGlobalVariables(Prefix)) + return KeepPrefix; + + return NoFailure; + } + + bool TestGlobalVariables(std::vector<GlobalVariable*>& GVs); + }; +} + +bool +ReduceCrashingGlobalVariables::TestGlobalVariables( + std::vector<GlobalVariable*>& GVs) { + // Clone the program to try hacking it apart... + Module *M = CloneModule(BD.getProgram()); + + // Convert list to set for fast lookup... + std::set<GlobalVariable*> GVSet; + + for (unsigned i = 0, e = GVs.size(); i != e; ++i) { + GlobalVariable* CMGV = M->getNamedGlobal(GVs[i]->getName()); + assert(CMGV && "Global Variable not in module?!"); + GVSet.insert(CMGV); + } + + std::cout << "Checking for crash with only these global variables: "; + PrintGlobalVariableList(GVs); + std::cout << ": "; + + // Loop over and delete any global variables which we aren't supposed to be + // playing with... + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) + if (I->hasInitializer()) { + I->setInitializer(0); + I->setLinkage(GlobalValue::ExternalLinkage); + } + + // Try running the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + + // Make sure to use global variable pointers that point into the now-current + // module. + GVs.assign(GVSet.begin(), GVSet.end()); + return true; + } + + delete M; + return false; +} + namespace llvm { + /// ReduceCrashingFunctions reducer - This works by removing functions and + /// seeing if the program still crashes. If it does, then keep the newer, + /// smaller program. + /// class ReduceCrashingFunctions : public ListReducer<Function*> { BugDriver &BD; bool (*TestFn)(BugDriver &, Module *); @@ -119,7 +193,8 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { //if main isn't present, claim there is no problem - if (KeepMain && find(Funcs.begin(), Funcs.end(), BD.getProgram()->getMainFunction()) == Funcs.end()) + if (KeepMain && find(Funcs.begin(), Funcs.end(), + BD.getProgram()->getMainFunction()) == Funcs.end()) return false; // Clone the program to try hacking it apart... @@ -277,30 +352,27 @@ /// on a program, try to destructively reduce the program while still keeping /// the predicate true. static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { - // See if we can get away with nuking all of the global variable initializers + // See if we can get away with nuking some of the global variable initializers // in the program... if (BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { - Module *M = CloneModule(BD.getProgram()); - bool DeletedInit = false; - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) - if (I->hasInitializer()) { - I->setInitializer(0); - I->setLinkage(GlobalValue::ExternalLinkage); - DeletedInit = true; - } + // Now try to reduce the number of global variable initializers in the + // module to something small. + std::vector<GlobalVariable*> GVs; + + for (Module::global_iterator I = BD.getProgram()->global_begin(), + E = BD.getProgram()->global_end(); I != E; ++I) + if (I->hasInitializer()) + GVs.push_back(I); + + if (GVs.size() > 1 && !BugpointIsInterrupted) { + std::cout << "\n*** Attempting to reduce the number of global variables " + << "in the testcase\n"; - if (!DeletedInit) { - delete M; // No change made... - } else { - // See if the program still causes a crash... - std::cout << "\nChecking to see if we can delete global inits: "; - if (TestFn(BD, M)) { // Still crashes? - BD.setNewProgram(M); - std::cout << "\n*** Able to remove all global initializers!\n"; - } else { // No longer crashes? - std::cout << " - Removing all global inits hides problem!\n"; - delete M; - } + unsigned OldSize = GVs.size(); + ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs); + + if (GVs.size() < OldSize) + BD.EmitProgressBytecode("reduced-global-variables"); } } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits