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 if (PassesToRun.size() == OldSize) { // Make sure something crashed. :)
133 std::cerr << "ERROR: No passes crashed!\n";
137 std::cout << "\n*** Found crashing pass"
138 << (PassesToRun.size() == 1 ? ": " : "es: ")
139 << getPassesString(PassesToRun) << "\n";
141 EmitProgressBytecode("passinput");
143 // Now try to reduce the number of functions in the module to something small.
144 std::vector<Function*> Functions;
145 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
146 if (!I->isExternal())
147 Functions.push_back(I);
149 if (Functions.size() > 1) {
150 std::cout << "\n*** Attempting to reduce the number of functions "
153 OldSize = Functions.size();
154 ReduceCrashingFunctions(*this).reduceList(Functions);
156 if (Functions.size() < OldSize) {
157 EmitProgressBytecode("reduced-function");
162 // FIXME: This should attempt to delete entire basic blocks at a time to speed
165 // FIXME: This should use the list reducer to converge faster by deleting
166 // larger chunks of instructions at a time!
167 bool Reduced = false;
168 unsigned Simplification = 4;
171 std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
172 << "tions: Simplification Level #" << Simplification << "\n";
174 // Now that we have deleted the functions that are unneccesary for the
175 // program, try to remove instructions that are not neccesary to cause the
176 // crash. To do this, we loop through all of the instructions in the
177 // remaining functions, deleting them (replacing any values produced with
178 // nulls), and then running ADCE and SimplifyCFG. If the transformed input
179 // still triggers failure, keep deleting until we cannot trigger failure
184 // Loop over all of the (non-terminator) instructions remaining in the
185 // function, attempting to delete them.
186 for (Module::iterator FI = Program->begin(), E = Program->end();
188 if (!FI->isExternal()) {
189 for (Function::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI)
190 for (BasicBlock::iterator I = BI->begin(), E = --BI->end();
192 Module *M = deleteInstructionFromProgram(I, Simplification);
194 // Make the function the current program...
195 std::swap(Program, M);
197 // Find out if the pass still crashes on this pass...
198 std::cout << "Checking instruction '" << I->getName() << "': ";
199 if (runPasses(PassesToRun)) {
200 // Yup, it does, we delete the old module, and continue trying to
201 // reduce the testcase...
203 Reduced = AnyReduction = true;
204 goto TryAgain; // I wish I had a multi-level break here!
207 // This pass didn't crash without this instruction, try the next
213 } while (Simplification);
215 // Try to clean up the testcase by running funcresolve and globaldce...
217 std::cout << "\n*** Attempting to perform final cleanups: ";
218 Module *M = performFinalCleanups();
219 std::swap(Program, M);
221 // Find out if the pass still crashes on the cleaned up program...
222 if (runPasses(PassesToRun)) {
223 // Yup, it does, keep the reduced version...
225 Reduced = AnyReduction = true;
227 delete Program; // Otherwise, restore the original module...
233 EmitProgressBytecode("reduced-simplified");