CrashDebugger.cpp revision 198090
1//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the bugpoint internals that narrow down compilation crashes 11// 12//===----------------------------------------------------------------------===// 13 14#include "BugDriver.h" 15#include "ToolRunner.h" 16#include "ListReducer.h" 17#include "llvm/Constants.h" 18#include "llvm/DerivedTypes.h" 19#include "llvm/Instructions.h" 20#include "llvm/Module.h" 21#include "llvm/Pass.h" 22#include "llvm/PassManager.h" 23#include "llvm/ValueSymbolTable.h" 24#include "llvm/ADT/SmallPtrSet.h" 25#include "llvm/Analysis/Verifier.h" 26#include "llvm/Support/CFG.h" 27#include "llvm/Transforms/Scalar.h" 28#include "llvm/Transforms/Utils/Cloning.h" 29#include "llvm/Support/FileUtilities.h" 30#include "llvm/Support/CommandLine.h" 31#include <set> 32using namespace llvm; 33 34namespace { 35 cl::opt<bool> 36 KeepMain("keep-main", 37 cl::desc("Force function reduction to keep main"), 38 cl::init(false)); 39 cl::opt<bool> 40 NoGlobalRM ("disable-global-remove", 41 cl::desc("Do not remove global variables"), 42 cl::init(false)); 43} 44 45namespace llvm { 46 class ReducePassList : public ListReducer<const PassInfo*> { 47 BugDriver &BD; 48 public: 49 ReducePassList(BugDriver &bd) : BD(bd) {} 50 51 // doTest - Return true iff running the "removed" passes succeeds, and 52 // running the "Kept" passes fail when run on the output of the "removed" 53 // passes. If we return true, we update the current module of bugpoint. 54 // 55 virtual TestResult doTest(std::vector<const PassInfo*> &Removed, 56 std::vector<const PassInfo*> &Kept); 57 }; 58} 59 60ReducePassList::TestResult 61ReducePassList::doTest(std::vector<const PassInfo*> &Prefix, 62 std::vector<const PassInfo*> &Suffix) { 63 sys::Path PrefixOutput; 64 Module *OrigProgram = 0; 65 if (!Prefix.empty()) { 66 outs() << "Checking to see if these passes crash: " 67 << getPassesString(Prefix) << ": "; 68 std::string PfxOutput; 69 if (BD.runPasses(Prefix, PfxOutput)) 70 return KeepPrefix; 71 72 PrefixOutput.set(PfxOutput); 73 OrigProgram = BD.Program; 74 75 BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext()); 76 if (BD.Program == 0) { 77 errs() << BD.getToolName() << ": Error reading bitcode file '" 78 << PrefixOutput.str() << "'!\n"; 79 exit(1); 80 } 81 PrefixOutput.eraseFromDisk(); 82 } 83 84 outs() << "Checking to see if these passes crash: " 85 << getPassesString(Suffix) << ": "; 86 87 if (BD.runPasses(Suffix)) { 88 delete OrigProgram; // The suffix crashes alone... 89 return KeepSuffix; 90 } 91 92 // Nothing failed, restore state... 93 if (OrigProgram) { 94 delete BD.Program; 95 BD.Program = OrigProgram; 96 } 97 return NoFailure; 98} 99 100namespace { 101 /// ReduceCrashingGlobalVariables - This works by removing the global 102 /// variable's initializer and seeing if the program still crashes. If it 103 /// does, then we keep that program and try again. 104 /// 105 class ReduceCrashingGlobalVariables : public ListReducer<GlobalVariable*> { 106 BugDriver &BD; 107 bool (*TestFn)(BugDriver &, Module *); 108 public: 109 ReduceCrashingGlobalVariables(BugDriver &bd, 110 bool (*testFn)(BugDriver&, Module*)) 111 : BD(bd), TestFn(testFn) {} 112 113 virtual TestResult doTest(std::vector<GlobalVariable*>& Prefix, 114 std::vector<GlobalVariable*>& Kept) { 115 if (!Kept.empty() && TestGlobalVariables(Kept)) 116 return KeepSuffix; 117 118 if (!Prefix.empty() && TestGlobalVariables(Prefix)) 119 return KeepPrefix; 120 121 return NoFailure; 122 } 123 124 bool TestGlobalVariables(std::vector<GlobalVariable*>& GVs); 125 }; 126} 127 128bool 129ReduceCrashingGlobalVariables::TestGlobalVariables( 130 std::vector<GlobalVariable*>& GVs) { 131 // Clone the program to try hacking it apart... 132 DenseMap<const Value*, Value*> ValueMap; 133 Module *M = CloneModule(BD.getProgram(), ValueMap); 134 135 // Convert list to set for fast lookup... 136 std::set<GlobalVariable*> GVSet; 137 138 for (unsigned i = 0, e = GVs.size(); i != e; ++i) { 139 GlobalVariable* CMGV = cast<GlobalVariable>(ValueMap[GVs[i]]); 140 assert(CMGV && "Global Variable not in module?!"); 141 GVSet.insert(CMGV); 142 } 143 144 outs() << "Checking for crash with only these global variables: "; 145 PrintGlobalVariableList(GVs); 146 outs() << ": "; 147 148 // Loop over and delete any global variables which we aren't supposed to be 149 // playing with... 150 for (Module::global_iterator I = M->global_begin(), E = M->global_end(); 151 I != E; ++I) 152 if (I->hasInitializer() && !GVSet.count(I)) { 153 I->setInitializer(0); 154 I->setLinkage(GlobalValue::ExternalLinkage); 155 } 156 157 // Try running the hacked up program... 158 if (TestFn(BD, M)) { 159 BD.setNewProgram(M); // It crashed, keep the trimmed version... 160 161 // Make sure to use global variable pointers that point into the now-current 162 // module. 163 GVs.assign(GVSet.begin(), GVSet.end()); 164 return true; 165 } 166 167 delete M; 168 return false; 169} 170 171namespace llvm { 172 /// ReduceCrashingFunctions reducer - This works by removing functions and 173 /// seeing if the program still crashes. If it does, then keep the newer, 174 /// smaller program. 175 /// 176 class ReduceCrashingFunctions : public ListReducer<Function*> { 177 BugDriver &BD; 178 bool (*TestFn)(BugDriver &, Module *); 179 public: 180 ReduceCrashingFunctions(BugDriver &bd, 181 bool (*testFn)(BugDriver &, Module *)) 182 : BD(bd), TestFn(testFn) {} 183 184 virtual TestResult doTest(std::vector<Function*> &Prefix, 185 std::vector<Function*> &Kept) { 186 if (!Kept.empty() && TestFuncs(Kept)) 187 return KeepSuffix; 188 if (!Prefix.empty() && TestFuncs(Prefix)) 189 return KeepPrefix; 190 return NoFailure; 191 } 192 193 bool TestFuncs(std::vector<Function*> &Prefix); 194 }; 195} 196 197bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { 198 199 //if main isn't present, claim there is no problem 200 if (KeepMain && find(Funcs.begin(), Funcs.end(), 201 BD.getProgram()->getFunction("main")) == Funcs.end()) 202 return false; 203 204 // Clone the program to try hacking it apart... 205 DenseMap<const Value*, Value*> ValueMap; 206 Module *M = CloneModule(BD.getProgram(), ValueMap); 207 208 // Convert list to set for fast lookup... 209 std::set<Function*> Functions; 210 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { 211 Function *CMF = cast<Function>(ValueMap[Funcs[i]]); 212 assert(CMF && "Function not in module?!"); 213 assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty"); 214 assert(CMF->getName() == Funcs[i]->getName() && "wrong name"); 215 Functions.insert(CMF); 216 } 217 218 outs() << "Checking for crash with only these functions: "; 219 PrintFunctionList(Funcs); 220 outs() << ": "; 221 222 // Loop over and delete any functions which we aren't supposed to be playing 223 // with... 224 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) 225 if (!I->isDeclaration() && !Functions.count(I)) 226 DeleteFunctionBody(I); 227 228 // Try running the hacked up program... 229 if (TestFn(BD, M)) { 230 BD.setNewProgram(M); // It crashed, keep the trimmed version... 231 232 // Make sure to use function pointers that point into the now-current 233 // module. 234 Funcs.assign(Functions.begin(), Functions.end()); 235 return true; 236 } 237 delete M; 238 return false; 239} 240 241 242namespace { 243 /// ReduceCrashingBlocks reducer - This works by setting the terminators of 244 /// all terminators except the specified basic blocks to a 'ret' instruction, 245 /// then running the simplify-cfg pass. This has the effect of chopping up 246 /// the CFG really fast which can reduce large functions quickly. 247 /// 248 class ReduceCrashingBlocks : public ListReducer<const BasicBlock*> { 249 BugDriver &BD; 250 bool (*TestFn)(BugDriver &, Module *); 251 public: 252 ReduceCrashingBlocks(BugDriver &bd, bool (*testFn)(BugDriver &, Module *)) 253 : BD(bd), TestFn(testFn) {} 254 255 virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix, 256 std::vector<const BasicBlock*> &Kept) { 257 if (!Kept.empty() && TestBlocks(Kept)) 258 return KeepSuffix; 259 if (!Prefix.empty() && TestBlocks(Prefix)) 260 return KeepPrefix; 261 return NoFailure; 262 } 263 264 bool TestBlocks(std::vector<const BasicBlock*> &Prefix); 265 }; 266} 267 268bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { 269 // Clone the program to try hacking it apart... 270 DenseMap<const Value*, Value*> ValueMap; 271 Module *M = CloneModule(BD.getProgram(), ValueMap); 272 273 // Convert list to set for fast lookup... 274 SmallPtrSet<BasicBlock*, 8> Blocks; 275 for (unsigned i = 0, e = BBs.size(); i != e; ++i) 276 Blocks.insert(cast<BasicBlock>(ValueMap[BBs[i]])); 277 278 outs() << "Checking for crash with only these blocks:"; 279 unsigned NumPrint = Blocks.size(); 280 if (NumPrint > 10) NumPrint = 10; 281 for (unsigned i = 0, e = NumPrint; i != e; ++i) 282 outs() << " " << BBs[i]->getName(); 283 if (NumPrint < Blocks.size()) 284 outs() << "... <" << Blocks.size() << " total>"; 285 outs() << ": "; 286 287 // Loop over and delete any hack up any blocks that are not listed... 288 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) 289 for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) 290 if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) { 291 // Loop over all of the successors of this block, deleting any PHI nodes 292 // that might include it. 293 for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) 294 (*SI)->removePredecessor(BB); 295 296 TerminatorInst *BBTerm = BB->getTerminator(); 297 298 if (isa<StructType>(BBTerm->getType())) 299 BBTerm->replaceAllUsesWith(UndefValue::get(BBTerm->getType())); 300 else if (BB->getTerminator()->getType() != 301 Type::getVoidTy(BB->getContext())) 302 BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); 303 304 // Replace the old terminator instruction. 305 BB->getInstList().pop_back(); 306 new UnreachableInst(BB->getContext(), BB); 307 } 308 309 // The CFG Simplifier pass may delete one of the basic blocks we are 310 // interested in. If it does we need to take the block out of the list. Make 311 // a "persistent mapping" by turning basic blocks into <function, name> pairs. 312 // This won't work well if blocks are unnamed, but that is just the risk we 313 // have to take. 314 std::vector<std::pair<Function*, std::string> > BlockInfo; 315 316 for (SmallPtrSet<BasicBlock*, 8>::iterator I = Blocks.begin(), 317 E = Blocks.end(); I != E; ++I) 318 BlockInfo.push_back(std::make_pair((*I)->getParent(), (*I)->getName())); 319 320 // Now run the CFG simplify pass on the function... 321 PassManager Passes; 322 Passes.add(createCFGSimplificationPass()); 323 Passes.add(createVerifierPass()); 324 Passes.run(*M); 325 326 // Try running on the hacked up program... 327 if (TestFn(BD, M)) { 328 BD.setNewProgram(M); // It crashed, keep the trimmed version... 329 330 // Make sure to use basic block pointers that point into the now-current 331 // module, and that they don't include any deleted blocks. 332 BBs.clear(); 333 for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { 334 ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable(); 335 Value* V = ST.lookup(BlockInfo[i].second); 336 if (V && V->getType() == Type::getLabelTy(V->getContext())) 337 BBs.push_back(cast<BasicBlock>(V)); 338 } 339 return true; 340 } 341 delete M; // It didn't crash, try something else. 342 return false; 343} 344 345namespace { 346 /// ReduceCrashingInstructions reducer - This works by removing the specified 347 /// non-terminator instructions and replacing them with undef. 348 /// 349 class ReduceCrashingInstructions : public ListReducer<const Instruction*> { 350 BugDriver &BD; 351 bool (*TestFn)(BugDriver &, Module *); 352 public: 353 ReduceCrashingInstructions(BugDriver &bd, bool (*testFn)(BugDriver &, 354 Module *)) 355 : BD(bd), TestFn(testFn) {} 356 357 virtual TestResult doTest(std::vector<const Instruction*> &Prefix, 358 std::vector<const Instruction*> &Kept) { 359 if (!Kept.empty() && TestInsts(Kept)) 360 return KeepSuffix; 361 if (!Prefix.empty() && TestInsts(Prefix)) 362 return KeepPrefix; 363 return NoFailure; 364 } 365 366 bool TestInsts(std::vector<const Instruction*> &Prefix); 367 }; 368} 369 370bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> 371 &Insts) { 372 // Clone the program to try hacking it apart... 373 DenseMap<const Value*, Value*> ValueMap; 374 Module *M = CloneModule(BD.getProgram(), ValueMap); 375 376 // Convert list to set for fast lookup... 377 SmallPtrSet<Instruction*, 64> Instructions; 378 for (unsigned i = 0, e = Insts.size(); i != e; ++i) { 379 assert(!isa<TerminatorInst>(Insts[i])); 380 Instructions.insert(cast<Instruction>(ValueMap[Insts[i]])); 381 } 382 383 outs() << "Checking for crash with only " << Instructions.size(); 384 if (Instructions.size() == 1) 385 outs() << " instruction: "; 386 else 387 outs() << " instructions: "; 388 389 for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) 390 for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) 391 for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { 392 Instruction *Inst = I++; 393 if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) { 394 if (Inst->getType() != Type::getVoidTy(Inst->getContext())) 395 Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); 396 Inst->eraseFromParent(); 397 } 398 } 399 400 // Verify that this is still valid. 401 PassManager Passes; 402 Passes.add(createVerifierPass()); 403 Passes.run(*M); 404 405 // Try running on the hacked up program... 406 if (TestFn(BD, M)) { 407 BD.setNewProgram(M); // It crashed, keep the trimmed version... 408 409 // Make sure to use instruction pointers that point into the now-current 410 // module, and that they don't include any deleted blocks. 411 Insts.clear(); 412 for (SmallPtrSet<Instruction*, 64>::const_iterator I = Instructions.begin(), 413 E = Instructions.end(); I != E; ++I) 414 Insts.push_back(*I); 415 return true; 416 } 417 delete M; // It didn't crash, try something else. 418 return false; 419} 420 421/// DebugACrash - Given a predicate that determines whether a component crashes 422/// on a program, try to destructively reduce the program while still keeping 423/// the predicate true. 424static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { 425 // See if we can get away with nuking some of the global variable initializers 426 // in the program... 427 if (!NoGlobalRM && 428 BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { 429 // Now try to reduce the number of global variable initializers in the 430 // module to something small. 431 Module *M = CloneModule(BD.getProgram()); 432 bool DeletedInit = false; 433 434 for (Module::global_iterator I = M->global_begin(), E = M->global_end(); 435 I != E; ++I) 436 if (I->hasInitializer()) { 437 I->setInitializer(0); 438 I->setLinkage(GlobalValue::ExternalLinkage); 439 DeletedInit = true; 440 } 441 442 if (!DeletedInit) { 443 delete M; // No change made... 444 } else { 445 // See if the program still causes a crash... 446 outs() << "\nChecking to see if we can delete global inits: "; 447 448 if (TestFn(BD, M)) { // Still crashes? 449 BD.setNewProgram(M); 450 outs() << "\n*** Able to remove all global initializers!\n"; 451 } else { // No longer crashes? 452 outs() << " - Removing all global inits hides problem!\n"; 453 delete M; 454 455 std::vector<GlobalVariable*> GVs; 456 457 for (Module::global_iterator I = BD.getProgram()->global_begin(), 458 E = BD.getProgram()->global_end(); I != E; ++I) 459 if (I->hasInitializer()) 460 GVs.push_back(I); 461 462 if (GVs.size() > 1 && !BugpointIsInterrupted) { 463 outs() << "\n*** Attempting to reduce the number of global " 464 << "variables in the testcase\n"; 465 466 unsigned OldSize = GVs.size(); 467 ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs); 468 469 if (GVs.size() < OldSize) 470 BD.EmitProgressBitcode("reduced-global-variables"); 471 } 472 } 473 } 474 } 475 476 // Now try to reduce the number of functions in the module to something small. 477 std::vector<Function*> Functions; 478 for (Module::iterator I = BD.getProgram()->begin(), 479 E = BD.getProgram()->end(); I != E; ++I) 480 if (!I->isDeclaration()) 481 Functions.push_back(I); 482 483 if (Functions.size() > 1 && !BugpointIsInterrupted) { 484 outs() << "\n*** Attempting to reduce the number of functions " 485 "in the testcase\n"; 486 487 unsigned OldSize = Functions.size(); 488 ReduceCrashingFunctions(BD, TestFn).reduceList(Functions); 489 490 if (Functions.size() < OldSize) 491 BD.EmitProgressBitcode("reduced-function"); 492 } 493 494 // Attempt to delete entire basic blocks at a time to speed up 495 // convergence... this actually works by setting the terminator of the blocks 496 // to a return instruction then running simplifycfg, which can potentially 497 // shrinks the code dramatically quickly 498 // 499 if (!DisableSimplifyCFG && !BugpointIsInterrupted) { 500 std::vector<const BasicBlock*> Blocks; 501 for (Module::const_iterator I = BD.getProgram()->begin(), 502 E = BD.getProgram()->end(); I != E; ++I) 503 for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI) 504 Blocks.push_back(FI); 505 unsigned OldSize = Blocks.size(); 506 ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks); 507 if (Blocks.size() < OldSize) 508 BD.EmitProgressBitcode("reduced-blocks"); 509 } 510 511 // Attempt to delete instructions using bisection. This should help out nasty 512 // cases with large basic blocks where the problem is at one end. 513 if (!BugpointIsInterrupted) { 514 std::vector<const Instruction*> Insts; 515 for (Module::const_iterator MI = BD.getProgram()->begin(), 516 ME = BD.getProgram()->end(); MI != ME; ++MI) 517 for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE; 518 ++FI) 519 for (BasicBlock::const_iterator I = FI->begin(), E = FI->end(); 520 I != E; ++I) 521 if (!isa<TerminatorInst>(I)) 522 Insts.push_back(I); 523 524 ReduceCrashingInstructions(BD, TestFn).reduceList(Insts); 525 } 526 527 // FIXME: This should use the list reducer to converge faster by deleting 528 // larger chunks of instructions at a time! 529 unsigned Simplification = 2; 530 do { 531 if (BugpointIsInterrupted) break; 532 --Simplification; 533 outs() << "\n*** Attempting to reduce testcase by deleting instruc" 534 << "tions: Simplification Level #" << Simplification << '\n'; 535 536 // Now that we have deleted the functions that are unnecessary for the 537 // program, try to remove instructions that are not necessary to cause the 538 // crash. To do this, we loop through all of the instructions in the 539 // remaining functions, deleting them (replacing any values produced with 540 // nulls), and then running ADCE and SimplifyCFG. If the transformed input 541 // still triggers failure, keep deleting until we cannot trigger failure 542 // anymore. 543 // 544 unsigned InstructionsToSkipBeforeDeleting = 0; 545 TryAgain: 546 547 // Loop over all of the (non-terminator) instructions remaining in the 548 // function, attempting to delete them. 549 unsigned CurInstructionNum = 0; 550 for (Module::const_iterator FI = BD.getProgram()->begin(), 551 E = BD.getProgram()->end(); FI != E; ++FI) 552 if (!FI->isDeclaration()) 553 for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; 554 ++BI) 555 for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); 556 I != E; ++I, ++CurInstructionNum) 557 if (InstructionsToSkipBeforeDeleting) { 558 --InstructionsToSkipBeforeDeleting; 559 } else { 560 if (BugpointIsInterrupted) goto ExitLoops; 561 562 outs() << "Checking instruction: " << *I; 563 Module *M = BD.deleteInstructionFromProgram(I, Simplification); 564 565 // Find out if the pass still crashes on this pass... 566 if (TestFn(BD, M)) { 567 // Yup, it does, we delete the old module, and continue trying 568 // to reduce the testcase... 569 BD.setNewProgram(M); 570 InstructionsToSkipBeforeDeleting = CurInstructionNum; 571 goto TryAgain; // I wish I had a multi-level break here! 572 } 573 574 // This pass didn't crash without this instruction, try the next 575 // one. 576 delete M; 577 } 578 579 if (InstructionsToSkipBeforeDeleting) { 580 InstructionsToSkipBeforeDeleting = 0; 581 goto TryAgain; 582 } 583 584 } while (Simplification); 585ExitLoops: 586 587 // Try to clean up the testcase by running funcresolve and globaldce... 588 if (!BugpointIsInterrupted) { 589 outs() << "\n*** Attempting to perform final cleanups: "; 590 Module *M = CloneModule(BD.getProgram()); 591 M = BD.performFinalCleanups(M, true); 592 593 // Find out if the pass still crashes on the cleaned up program... 594 if (TestFn(BD, M)) { 595 BD.setNewProgram(M); // Yup, it does, keep the reduced version... 596 } else { 597 delete M; 598 } 599 } 600 601 BD.EmitProgressBitcode("reduced-simplified"); 602 603 return false; 604} 605 606static bool TestForOptimizerCrash(BugDriver &BD, Module *M) { 607 return BD.runPasses(M); 608} 609 610/// debugOptimizerCrash - This method is called when some pass crashes on input. 611/// It attempts to prune down the testcase to something reasonable, and figure 612/// out exactly which pass is crashing. 613/// 614bool BugDriver::debugOptimizerCrash(const std::string &ID) { 615 outs() << "\n*** Debugging optimizer crash!\n"; 616 617 // Reduce the list of passes which causes the optimizer to crash... 618 if (!BugpointIsInterrupted) 619 ReducePassList(*this).reduceList(PassesToRun); 620 621 outs() << "\n*** Found crashing pass" 622 << (PassesToRun.size() == 1 ? ": " : "es: ") 623 << getPassesString(PassesToRun) << '\n'; 624 625 EmitProgressBitcode(ID); 626 627 return DebugACrash(*this, TestForOptimizerCrash); 628} 629 630static bool TestForCodeGenCrash(BugDriver &BD, Module *M) { 631 try { 632 BD.compileProgram(M); 633 errs() << '\n'; 634 return false; 635 } catch (ToolExecutionError &) { 636 errs() << "<crash>\n"; 637 return true; // Tool is still crashing. 638 } 639} 640 641/// debugCodeGeneratorCrash - This method is called when the code generator 642/// crashes on an input. It attempts to reduce the input as much as possible 643/// while still causing the code generator to crash. 644bool BugDriver::debugCodeGeneratorCrash() { 645 errs() << "*** Debugging code generator crash!\n"; 646 647 return DebugACrash(*this, TestForCodeGenCrash); 648} 649