blob: 2d224f3fbadbccd4504084dac13f914ee3689b16 [file] [log] [blame]
Chris Lattnerafade922002-11-20 22:28:10 +00001//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
2//
3// This file defines the bugpoint internals that narrow down compilation crashes
4//
5//===----------------------------------------------------------------------===//
6
7#include "BugDriver.h"
Chris Lattner218e26e2002-12-23 23:49:59 +00008#include "SystemUtils.h"
Chris Lattneraae33f92003-04-24 22:24:58 +00009#include "ListReducer.h"
Chris Lattnerafade922002-11-20 22:28:10 +000010#include "llvm/Module.h"
Chris Lattner286921e2003-04-24 23:51:38 +000011#include "llvm/PassManager.h"
12#include "llvm/Pass.h"
13#include "llvm/Constant.h"
14#include "llvm/iTerminators.h"
15#include "llvm/Type.h"
16#include "llvm/SymbolTable.h"
17#include "llvm/Support/CFG.h"
18#include "llvm/Analysis/Verifier.h"
19#include "llvm/Transforms/Scalar.h"
Chris Lattneraae33f92003-04-24 22:24:58 +000020#include "llvm/Transforms/Utils/Cloning.h"
Chris Lattnerafade922002-11-20 22:28:10 +000021#include "llvm/Bytecode/Writer.h"
Chris Lattnerafade922002-11-20 22:28:10 +000022#include <fstream>
Chris Lattneraae33f92003-04-24 22:24:58 +000023#include <set>
Chris Lattnerafade922002-11-20 22:28:10 +000024
Chris Lattner640f22e2003-04-24 17:02:17 +000025class DebugCrashes : public ListReducer<const PassInfo*> {
26 BugDriver &BD;
27public:
28 DebugCrashes(BugDriver &bd) : BD(bd) {}
29
30 // doTest - Return true iff running the "removed" passes succeeds, and running
31 // the "Kept" passes fail when run on the output of the "removed" passes. If
32 // we return true, we update the current module of bugpoint.
33 //
Chris Lattneraae33f92003-04-24 22:24:58 +000034 virtual TestResult doTest(std::vector<const PassInfo*> &Removed,
35 std::vector<const PassInfo*> &Kept);
Chris Lattner640f22e2003-04-24 17:02:17 +000036};
Chris Lattneraae33f92003-04-24 22:24:58 +000037
38DebugCrashes::TestResult
39DebugCrashes::doTest(std::vector<const PassInfo*> &Prefix,
40 std::vector<const PassInfo*> &Suffix) {
41 std::string PrefixOutput;
42 if (!Prefix.empty()) {
43 std::cout << "Checking to see if these passes crash: "
44 << getPassesString(Prefix) << ": ";
45 if (BD.runPasses(Prefix, PrefixOutput))
46 return KeepPrefix;
47 }
48
49 std::cout << "Checking to see if these passes crash: "
50 << getPassesString(Suffix) << ": ";
51 Module *OrigProgram = BD.Program;
52 BD.Program = BD.ParseInputFile(PrefixOutput);
53 if (BD.Program == 0) {
54 std::cerr << BD.getToolName() << ": Error reading bytecode file '"
55 << PrefixOutput << "'!\n";
56 exit(1);
57 }
58 removeFile(PrefixOutput);
59
60 if (BD.runPasses(Suffix)) {
61 delete OrigProgram; // The suffix crashes alone...
62 return KeepSuffix;
63 }
64
65 // Nothing failed, restore state...
66 delete BD.Program;
67 BD.Program = OrigProgram;
68 return NoFailure;
69}
70
71class ReduceCrashingFunctions : public ListReducer<Function*> {
72 BugDriver &BD;
73public:
74 ReduceCrashingFunctions(BugDriver &bd) : BD(bd) {}
75
76 virtual TestResult doTest(std::vector<Function*> &Prefix,
77 std::vector<Function*> &Kept) {
78 if (TestFuncs(Kept))
79 return KeepSuffix;
80 if (!Prefix.empty() && TestFuncs(Prefix))
81 return KeepPrefix;
82 return NoFailure;
83 }
84
85 bool TestFuncs(std::vector<Function*> &Prefix);
86};
87
88bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
89 // Clone the program to try hacking it appart...
90 Module *M = CloneModule(BD.Program);
91
92 // Convert list to set for fast lookup...
93 std::set<Function*> Functions;
94 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
95 Function *CMF = M->getFunction(Funcs[i]->getName(),
96 Funcs[i]->getFunctionType());
97 assert(CMF && "Function not in module?!");
Chris Lattnerf607b792003-04-24 22:54:06 +000098 Functions.insert(CMF);
Chris Lattneraae33f92003-04-24 22:24:58 +000099 }
100
101 std::cout << "Checking for crash with only these functions:";
102 for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
103 std::cout << " " << Funcs[i]->getName();
104 std::cout << ": ";
105
106 // Loop over and delete any functions which we aren't supposed to be playing
107 // with...
108 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
Chris Lattnerf607b792003-04-24 22:54:06 +0000109 if (!I->isExternal() && !Functions.count(I))
Chris Lattneraae33f92003-04-24 22:24:58 +0000110 DeleteFunctionBody(I);
111
112 // Try running the hacked up program...
113 std::swap(BD.Program, M);
114 if (BD.runPasses(BD.PassesToRun)) {
115 delete M; // It crashed, keep the trimmed version...
116
117 // Make sure to use function pointers that point into the now-current
118 // module.
119 Funcs.assign(Functions.begin(), Functions.end());
120 return true;
121 }
122 delete BD.Program; // It didn't crash, revert...
123 BD.Program = M;
124 return false;
125}
126
Chris Lattner640f22e2003-04-24 17:02:17 +0000127
Chris Lattner286921e2003-04-24 23:51:38 +0000128/// ReduceCrashingBlocks reducer - This works by setting the terminators of all
129/// terminators except the specified basic blocks to a 'ret' instruction, then
130/// running the simplify-cfg pass. This has the effect of chopping up the CFG
131/// really fast which can reduce large functions quickly.
132///
133class ReduceCrashingBlocks : public ListReducer<BasicBlock*> {
134 BugDriver &BD;
135public:
136 ReduceCrashingBlocks(BugDriver &bd) : BD(bd) {}
137
138 virtual TestResult doTest(std::vector<BasicBlock*> &Prefix,
139 std::vector<BasicBlock*> &Kept) {
140 if (TestBlocks(Kept))
141 return KeepSuffix;
142 if (!Prefix.empty() && TestBlocks(Prefix))
143 return KeepPrefix;
144 return NoFailure;
145 }
146
147 bool TestBlocks(std::vector<BasicBlock*> &Prefix);
148};
149
150bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) {
151 // Clone the program to try hacking it appart...
152 Module *M = CloneModule(BD.Program);
153
154 // Convert list to set for fast lookup...
155 std::set<BasicBlock*> Blocks;
156 for (unsigned i = 0, e = BBs.size(); i != e; ++i) {
157 // Convert the basic block from the original module to the new module...
158 Function *F = BBs[i]->getParent();
159 Function *CMF = M->getFunction(F->getName(), F->getFunctionType());
160 assert(CMF && "Function not in module?!");
161
162 // Get the mapped basic block...
163 Function::iterator CBI = CMF->begin();
164 std::advance(CBI, std::distance(F->begin(), Function::iterator(BBs[i])));
165 Blocks.insert(CBI);
166 }
167
168 std::cout << "Checking for crash with only these blocks:";
169 for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
170 std::cout << " " << BBs[i]->getName();
171 std::cout << ": ";
172
173 // Loop over and delete any hack up any blocks that are not listed...
174 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
175 for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB)
176 if (!Blocks.count(BB) && !isa<ReturnInst>(BB->getTerminator())) {
177 // Loop over all of the successors of this block, deleting any PHI nodes
178 // that might include it.
179 for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
180 (*SI)->removePredecessor(BB);
181
182 // Delete the old terminator instruction...
183 BB->getInstList().pop_back();
184
185 // Add a new return instruction of the appropriate type...
186 const Type *RetTy = BB->getParent()->getReturnType();
187 ReturnInst *RI = new ReturnInst(RetTy == Type::VoidTy ? 0 :
188 Constant::getNullValue(RetTy));
189 BB->getInstList().push_back(RI);
190 }
191
192 // The CFG Simplifier pass may delete one of the basic blocks we are
193 // interested in. If it does we need to take the block out of the list. Make
194 // a "persistent mapping" by turning basic blocks into <function, name> pairs.
195 // This won't work well if blocks are unnamed, but that is just the risk we
196 // have to take.
197 std::vector<std::pair<Function*, std::string> > BlockInfo;
198
199 for (std::set<BasicBlock*>::iterator I = Blocks.begin(), E = Blocks.end();
200 I != E; ++I)
201 BlockInfo.push_back(std::make_pair((*I)->getParent(), (*I)->getName()));
202
203 // Now run the CFG simplify pass on the function...
204 PassManager Passes;
205 Passes.add(createCFGSimplificationPass());
206 Passes.add(createVerifierPass());
207 Passes.run(*M);
208
209 // Try running on the hacked up program...
210 std::swap(BD.Program, M);
211 if (BD.runPasses(BD.PassesToRun)) {
212 delete M; // It crashed, keep the trimmed version...
213
214 // Make sure to use basic block pointers that point into the now-current
215 // module, and that they don't include any deleted blocks.
216 BBs.clear();
217 for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
218 SymbolTable &ST = BlockInfo[i].first->getSymbolTable();
219 SymbolTable::iterator I = ST.find(Type::LabelTy);
220 if (I != ST.end() && I->second.count(BlockInfo[i].second))
221 BBs.push_back(cast<BasicBlock>(I->second[BlockInfo[i].second]));
222 }
223 return true;
224 }
225 delete BD.Program; // It didn't crash, revert...
226 BD.Program = M;
227 return false;
228}
229
Chris Lattnerafade922002-11-20 22:28:10 +0000230/// debugCrash - This method is called when some pass crashes on input. It
231/// attempts to prune down the testcase to something reasonable, and figure
232/// out exactly which pass is crashing.
233///
234bool BugDriver::debugCrash() {
Chris Lattneraae33f92003-04-24 22:24:58 +0000235 bool AnyReduction = false;
Chris Lattnerafade922002-11-20 22:28:10 +0000236 std::cout << "\n*** Debugging optimizer crash!\n";
237
Chris Lattner640f22e2003-04-24 17:02:17 +0000238 // Reduce the list of passes which causes the optimizer to crash...
Chris Lattneraae33f92003-04-24 22:24:58 +0000239 unsigned OldSize = PassesToRun.size();
Chris Lattner640f22e2003-04-24 17:02:17 +0000240 DebugCrashes(*this).reduceList(PassesToRun);
Chris Lattner640f22e2003-04-24 17:02:17 +0000241
Chris Lattneraae33f92003-04-24 22:24:58 +0000242 std::cout << "\n*** Found crashing pass"
243 << (PassesToRun.size() == 1 ? ": " : "es: ")
244 << getPassesString(PassesToRun) << "\n";
Chris Lattnerafade922002-11-20 22:28:10 +0000245
Chris Lattner640f22e2003-04-24 17:02:17 +0000246 EmitProgressBytecode("passinput");
Chris Lattneraae33f92003-04-24 22:24:58 +0000247
248 // Now try to reduce the number of functions in the module to something small.
249 std::vector<Function*> Functions;
250 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
251 if (!I->isExternal())
252 Functions.push_back(I);
Chris Lattnerafade922002-11-20 22:28:10 +0000253
Chris Lattneraae33f92003-04-24 22:24:58 +0000254 if (Functions.size() > 1) {
255 std::cout << "\n*** Attempting to reduce the number of functions "
256 "in the testcase\n";
Chris Lattnerafade922002-11-20 22:28:10 +0000257
Chris Lattneraae33f92003-04-24 22:24:58 +0000258 OldSize = Functions.size();
259 ReduceCrashingFunctions(*this).reduceList(Functions);
Chris Lattnerafade922002-11-20 22:28:10 +0000260
Chris Lattneraae33f92003-04-24 22:24:58 +0000261 if (Functions.size() < OldSize) {
262 EmitProgressBytecode("reduced-function");
263 AnyReduction = true;
Chris Lattner65207852003-01-23 02:48:33 +0000264 }
Chris Lattnerafade922002-11-20 22:28:10 +0000265 }
266
Chris Lattner286921e2003-04-24 23:51:38 +0000267 // Attempt to delete entire basic blocks at a time to speed up
268 // convergence... this actually works by setting the terminator of the blocks
269 // to a return instruction then running simplifycfg, which can potentially
270 // shrinks the code dramatically quickly
271 //
272 std::vector<BasicBlock*> Blocks;
273 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
274 for (Function::iterator FI = I->begin(), E = I->end(); FI != E; ++FI)
275 Blocks.push_back(FI);
276 ReduceCrashingBlocks(*this).reduceList(Blocks);
Chris Lattner218e26e2002-12-23 23:49:59 +0000277
Chris Lattneraae33f92003-04-24 22:24:58 +0000278 // FIXME: This should use the list reducer to converge faster by deleting
279 // larger chunks of instructions at a time!
Chris Lattner65207852003-01-23 02:48:33 +0000280 unsigned Simplification = 4;
281 do {
282 --Simplification;
283 std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
284 << "tions: Simplification Level #" << Simplification << "\n";
285
286 // Now that we have deleted the functions that are unneccesary for the
287 // program, try to remove instructions that are not neccesary to cause the
288 // crash. To do this, we loop through all of the instructions in the
289 // remaining functions, deleting them (replacing any values produced with
290 // nulls), and then running ADCE and SimplifyCFG. If the transformed input
291 // still triggers failure, keep deleting until we cannot trigger failure
292 // anymore.
293 //
294 TryAgain:
295
296 // Loop over all of the (non-terminator) instructions remaining in the
297 // function, attempting to delete them.
298 for (Module::iterator FI = Program->begin(), E = Program->end();
299 FI != E; ++FI)
300 if (!FI->isExternal()) {
301 for (Function::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI)
302 for (BasicBlock::iterator I = BI->begin(), E = --BI->end();
303 I != E; ++I) {
304 Module *M = deleteInstructionFromProgram(I, Simplification);
305
306 // Make the function the current program...
307 std::swap(Program, M);
308
309 // Find out if the pass still crashes on this pass...
310 std::cout << "Checking instruction '" << I->getName() << "': ";
Chris Lattneraae33f92003-04-24 22:24:58 +0000311 if (runPasses(PassesToRun)) {
Chris Lattner65207852003-01-23 02:48:33 +0000312 // Yup, it does, we delete the old module, and continue trying to
313 // reduce the testcase...
Chris Lattner65207852003-01-23 02:48:33 +0000314 delete M;
Chris Lattnerf607b792003-04-24 22:54:06 +0000315 AnyReduction = true;
Chris Lattner65207852003-01-23 02:48:33 +0000316 goto TryAgain; // I wish I had a multi-level break here!
317 }
318
319 // This pass didn't crash without this instruction, try the next
320 // one.
321 delete Program;
322 Program = M;
323 }
324 }
325 } while (Simplification);
Chris Lattnerba386d92003-02-28 16:13:20 +0000326
327 // Try to clean up the testcase by running funcresolve and globaldce...
328 if (AnyReduction) {
329 std::cout << "\n*** Attempting to perform final cleanups: ";
330 Module *M = performFinalCleanups();
331 std::swap(Program, M);
332
333 // Find out if the pass still crashes on the cleaned up program...
Chris Lattneraae33f92003-04-24 22:24:58 +0000334 if (runPasses(PassesToRun)) {
Chris Lattnerba386d92003-02-28 16:13:20 +0000335 // Yup, it does, keep the reduced version...
336 delete M;
Chris Lattnerf607b792003-04-24 22:54:06 +0000337 AnyReduction = true;
Chris Lattnerba386d92003-02-28 16:13:20 +0000338 } else {
339 delete Program; // Otherwise, restore the original module...
340 Program = M;
341 }
342 }
343
Chris Lattnerf607b792003-04-24 22:54:06 +0000344 if (AnyReduction)
Chris Lattner640f22e2003-04-24 17:02:17 +0000345 EmitProgressBytecode("reduced-simplified");
Chris Lattnerba386d92003-02-28 16:13:20 +0000346
Chris Lattnerafade922002-11-20 22:28:10 +0000347 return false;
348}