1 //===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
3 // This file defines the bugpoint internals that narrow down compilation crashes
5 //===----------------------------------------------------------------------===//
8 #include "SystemUtils.h"
9 #include "ListReducer.h"
10 #include "llvm/Module.h"
11 #include "llvm/Transforms/Utils/Cloning.h"
12 #include "llvm/Bytecode/Writer.h"
13 #include "llvm/Pass.h"
17 class DebugCrashes : public ListReducer<const PassInfo*> {
20 DebugCrashes(BugDriver &bd) : BD(bd) {}
22 // doTest - Return true iff running the "removed" passes succeeds, and running
23 // the "Kept" passes fail when run on the output of the "removed" passes. If
24 // we return true, we update the current module of bugpoint.
26 virtual TestResult doTest(std::vector<const PassInfo*> &Removed,
27 std::vector<const PassInfo*> &Kept);
30 DebugCrashes::TestResult
31 DebugCrashes::doTest(std::vector<const PassInfo*> &Prefix,
32 std::vector<const PassInfo*> &Suffix) {
33 std::string PrefixOutput;
34 if (!Prefix.empty()) {
35 std::cout << "Checking to see if these passes crash: "
36 << getPassesString(Prefix) << ": ";
37 if (BD.runPasses(Prefix, PrefixOutput))
41 std::cout << "Checking to see if these passes crash: "
42 << getPassesString(Suffix) << ": ";
43 Module *OrigProgram = BD.Program;
44 BD.Program = BD.ParseInputFile(PrefixOutput);
45 if (BD.Program == 0) {
46 std::cerr << BD.getToolName() << ": Error reading bytecode file '"
47 << PrefixOutput << "'!\n";
50 removeFile(PrefixOutput);
52 if (BD.runPasses(Suffix)) {
53 delete OrigProgram; // The suffix crashes alone...
57 // Nothing failed, restore state...
59 BD.Program = OrigProgram;
63 class ReduceCrashingFunctions : public ListReducer<Function*> {
66 ReduceCrashingFunctions(BugDriver &bd) : BD(bd) {}
68 virtual TestResult doTest(std::vector<Function*> &Prefix,
69 std::vector<Function*> &Kept) {
72 if (!Prefix.empty() && TestFuncs(Prefix))
77 bool TestFuncs(std::vector<Function*> &Prefix);
80 bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
81 // Clone the program to try hacking it appart...
82 Module *M = CloneModule(BD.Program);
84 // Convert list to set for fast lookup...
85 std::set<Function*> Functions;
86 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
87 Function *CMF = M->getFunction(Funcs[i]->getName(),
88 Funcs[i]->getFunctionType());
89 assert(CMF && "Function not in module?!");
90 Functions.insert(CMF);
93 std::cout << "Checking for crash with only these functions:";
94 for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
95 std::cout << " " << Funcs[i]->getName();
98 // Loop over and delete any functions which we aren't supposed to be playing
100 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
101 if (!I->isExternal() && !Functions.count(I))
102 DeleteFunctionBody(I);
104 // Try running the hacked up program...
105 std::swap(BD.Program, M);
106 if (BD.runPasses(BD.PassesToRun)) {
107 delete M; // It crashed, keep the trimmed version...
109 // Make sure to use function pointers that point into the now-current
111 Funcs.assign(Functions.begin(), Functions.end());
114 delete BD.Program; // It didn't crash, revert...
120 /// debugCrash - This method is called when some pass crashes on input. It
121 /// attempts to prune down the testcase to something reasonable, and figure
122 /// out exactly which pass is crashing.
124 bool BugDriver::debugCrash() {
125 bool AnyReduction = false;
126 std::cout << "\n*** Debugging optimizer crash!\n";
128 // Reduce the list of passes which causes the optimizer to crash...
129 unsigned OldSize = PassesToRun.size();
130 DebugCrashes(*this).reduceList(PassesToRun);
132 std::cout << "\n*** Found crashing pass"
133 << (PassesToRun.size() == 1 ? ": " : "es: ")
134 << getPassesString(PassesToRun) << "\n";
136 EmitProgressBytecode("passinput");
138 // Now try to reduce the number of functions in the module to something small.
139 std::vector<Function*> Functions;
140 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
141 if (!I->isExternal())
142 Functions.push_back(I);
144 if (Functions.size() > 1) {
145 std::cout << "\n*** Attempting to reduce the number of functions "
148 OldSize = Functions.size();
149 ReduceCrashingFunctions(*this).reduceList(Functions);
151 if (Functions.size() < OldSize) {
152 EmitProgressBytecode("reduced-function");
157 // FIXME: This should attempt to delete entire basic blocks at a time to speed
160 // FIXME: This should use the list reducer to converge faster by deleting
161 // larger chunks of instructions at a time!
162 unsigned Simplification = 4;
165 std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
166 << "tions: Simplification Level #" << Simplification << "\n";
168 // Now that we have deleted the functions that are unneccesary for the
169 // program, try to remove instructions that are not neccesary to cause the
170 // crash. To do this, we loop through all of the instructions in the
171 // remaining functions, deleting them (replacing any values produced with
172 // nulls), and then running ADCE and SimplifyCFG. If the transformed input
173 // still triggers failure, keep deleting until we cannot trigger failure
178 // Loop over all of the (non-terminator) instructions remaining in the
179 // function, attempting to delete them.
180 for (Module::iterator FI = Program->begin(), E = Program->end();
182 if (!FI->isExternal()) {
183 for (Function::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI)
184 for (BasicBlock::iterator I = BI->begin(), E = --BI->end();
186 Module *M = deleteInstructionFromProgram(I, Simplification);
188 // Make the function the current program...
189 std::swap(Program, M);
191 // Find out if the pass still crashes on this pass...
192 std::cout << "Checking instruction '" << I->getName() << "': ";
193 if (runPasses(PassesToRun)) {
194 // Yup, it does, we delete the old module, and continue trying to
195 // reduce the testcase...
198 goto TryAgain; // I wish I had a multi-level break here!
201 // This pass didn't crash without this instruction, try the next
207 } while (Simplification);
209 // Try to clean up the testcase by running funcresolve and globaldce...
211 std::cout << "\n*** Attempting to perform final cleanups: ";
212 Module *M = performFinalCleanups();
213 std::swap(Program, M);
215 // Find out if the pass still crashes on the cleaned up program...
216 if (runPasses(PassesToRun)) {
217 // Yup, it does, keep the reduced version...
221 delete Program; // Otherwise, restore the original module...
227 EmitProgressBytecode("reduced-simplified");