1413 lines · cpp
1//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the bugpoint internals that narrow down compilation crashes10//11//===----------------------------------------------------------------------===//12 13#include "BugDriver.h"14#include "ListReducer.h"15#include "ToolRunner.h"16#include "llvm/ADT/SmallPtrSet.h"17#include "llvm/ADT/StringSet.h"18#include "llvm/Analysis/TargetTransformInfo.h"19#include "llvm/IR/CFG.h"20#include "llvm/IR/Constants.h"21#include "llvm/IR/DebugInfo.h"22#include "llvm/IR/DerivedTypes.h"23#include "llvm/IR/InstIterator.h"24#include "llvm/IR/Instructions.h"25#include "llvm/IR/LegacyPassManager.h"26#include "llvm/IR/Module.h"27#include "llvm/IR/ValueSymbolTable.h"28#include "llvm/IR/Verifier.h"29#include "llvm/Pass.h"30#include "llvm/Support/CommandLine.h"31#include "llvm/Support/FileUtilities.h"32#include "llvm/Transforms/Scalar.h"33#include "llvm/Transforms/Utils/BasicBlockUtils.h"34#include "llvm/Transforms/Utils/Cloning.h"35#include "llvm/Transforms/Utils/Local.h"36#include <set>37using namespace llvm;38 39static cl::opt<bool> KeepMain("keep-main",40 cl::desc("Force function reduction to keep main"),41 cl::init(false));42static cl::opt<bool> NoGlobalRM("disable-global-remove",43 cl::desc("Do not remove global variables"),44 cl::init(false));45 46static cl::opt<bool>47 NoAttributeRM("disable-attribute-remove",48 cl::desc("Do not remove function attributes"),49 cl::init(false));50 51static cl::opt<bool> ReplaceFuncsWithNull(52 "replace-funcs-with-null",53 cl::desc("When stubbing functions, replace all uses will null"),54 cl::init(false));55 56static cl::opt<bool>57 DontReducePassList("disable-pass-list-reduction",58 cl::desc("Skip pass list reduction steps"),59 cl::init(false));60 61static cl::opt<bool>62 NoNamedMDRM("disable-namedmd-remove",63 cl::desc("Do not remove global named metadata"),64 cl::init(false));65static cl::opt<bool>66 NoStripDebugInfo("disable-strip-debuginfo",67 cl::desc("Do not strip debug info metadata"),68 cl::init(false));69static cl::opt<bool>70 NoStripDebugTypeInfo("disable-strip-debug-types",71 cl::desc("Do not strip debug type info metadata"),72 cl::init(false));73static cl::opt<bool>74 VerboseErrors("verbose-errors",75 cl::desc("Print the output of crashing program"),76 cl::init(false));77 78static bool isValidModule(std::unique_ptr<Module> &M,79 bool ExitOnFailure = true) {80 if (!llvm::verifyModule(*M, &llvm::errs()))81 return true;82 83 if (ExitOnFailure) {84 llvm::errs() << "verify failed!\n";85 exit(1);86 }87 return false;88}89 90namespace llvm {91// Note this class needs to be in llvm namespace since its declared as a friend92// of BugDriver.93class ReducePassList : public ListReducer<std::string> {94 BugDriver &BD;95 96public:97 ReducePassList(BugDriver &bd) : BD(bd) {}98 99 // Return true iff running the "removed" passes succeeds, and running the100 // "Kept" passes fail when run on the output of the "removed" passes. If we101 // return true, we update the current module of bugpoint.102 Expected<TestResult> doTest(std::vector<std::string> &Removed,103 std::vector<std::string> &Kept) override;104};105} // namespace llvm106 107Expected<ReducePassList::TestResult>108ReducePassList::doTest(std::vector<std::string> &Prefix,109 std::vector<std::string> &Suffix) {110 std::string PrefixOutput;111 std::unique_ptr<Module> OrigProgram;112 if (!Prefix.empty()) {113 outs() << "Checking to see if these passes crash: "114 << getPassesString(Prefix) << ": ";115 if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))116 return KeepPrefix;117 118 OrigProgram = std::move(BD.Program);119 120 BD.Program = parseInputFile(PrefixOutput, BD.getContext());121 if (BD.Program == nullptr) {122 errs() << BD.getToolName() << ": Error reading bitcode file '"123 << PrefixOutput << "'!\n";124 exit(1);125 }126 sys::fs::remove(PrefixOutput);127 }128 129 outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)130 << ": ";131 132 if (BD.runPasses(BD.getProgram(), Suffix))133 return KeepSuffix; // The suffix crashes alone...134 135 // Nothing failed, restore state...136 if (OrigProgram)137 BD.Program = std::move(OrigProgram);138 return NoFailure;139}140 141using BugTester = bool (*)(const BugDriver &, Module *);142 143namespace {144/// ReduceCrashingGlobalInitializers - This works by removing global variable145/// initializers and seeing if the program still crashes. If it does, then we146/// keep that program and try again.147class ReduceCrashingGlobalInitializers : public ListReducer<GlobalVariable *> {148 BugDriver &BD;149 BugTester TestFn;150 151public:152 ReduceCrashingGlobalInitializers(BugDriver &bd, BugTester testFn)153 : BD(bd), TestFn(testFn) {}154 155 Expected<TestResult> doTest(std::vector<GlobalVariable *> &Prefix,156 std::vector<GlobalVariable *> &Kept) override {157 if (!Kept.empty() && TestGlobalVariables(Kept))158 return KeepSuffix;159 if (!Prefix.empty() && TestGlobalVariables(Prefix))160 return KeepPrefix;161 return NoFailure;162 }163 164 bool TestGlobalVariables(std::vector<GlobalVariable *> &GVs);165};166} // namespace167 168bool ReduceCrashingGlobalInitializers::TestGlobalVariables(169 std::vector<GlobalVariable *> &GVs) {170 // Clone the program to try hacking it apart...171 ValueToValueMapTy VMap;172 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);173 174 // Convert list to set for fast lookup...175 std::set<GlobalVariable *> GVSet;176 177 for (GlobalVariable *GV : GVs) {178 GlobalVariable *CMGV = cast<GlobalVariable>(VMap[GV]);179 assert(CMGV && "Global Variable not in module?!");180 GVSet.insert(CMGV);181 }182 183 outs() << "Checking for crash with only these global variables: ";184 printGlobalVariableList(GVs);185 outs() << ": ";186 187 // Loop over and delete any global variables which we aren't supposed to be188 // playing with...189 for (GlobalVariable &I : M->globals())190 if (I.hasInitializer() && !GVSet.count(&I)) {191 deleteGlobalInitializer(&I);192 I.setLinkage(GlobalValue::ExternalLinkage);193 I.setComdat(nullptr);194 }195 196 // Try running the hacked up program...197 if (TestFn(BD, M.get())) {198 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...199 200 // Make sure to use global variable pointers that point into the now-current201 // module.202 GVs.assign(GVSet.begin(), GVSet.end());203 return true;204 }205 206 return false;207}208 209namespace {210/// ReduceCrashingFunctions reducer - This works by removing functions and211/// seeing if the program still crashes. If it does, then keep the newer,212/// smaller program.213///214class ReduceCrashingFunctions : public ListReducer<Function *> {215 BugDriver &BD;216 BugTester TestFn;217 218public:219 ReduceCrashingFunctions(BugDriver &bd, BugTester testFn)220 : BD(bd), TestFn(testFn) {}221 222 Expected<TestResult> doTest(std::vector<Function *> &Prefix,223 std::vector<Function *> &Kept) override {224 if (!Kept.empty() && TestFuncs(Kept))225 return KeepSuffix;226 if (!Prefix.empty() && TestFuncs(Prefix))227 return KeepPrefix;228 return NoFailure;229 }230 231 bool TestFuncs(std::vector<Function *> &Prefix);232};233} // namespace234 235static void RemoveFunctionReferences(Module *M, const char *Name) {236 auto *UsedVar = M->getGlobalVariable(Name, true);237 if (!UsedVar || !UsedVar->hasInitializer())238 return;239 if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) {240 assert(UsedVar->use_empty());241 UsedVar->eraseFromParent();242 return;243 }244 auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer());245 std::vector<Constant *> Used;246 for (Value *V : OldUsedVal->operand_values()) {247 Constant *Op = cast<Constant>(V->stripPointerCasts());248 if (!Op->isNullValue()) {249 Used.push_back(cast<Constant>(V));250 }251 }252 auto *NewValElemTy = OldUsedVal->getType()->getElementType();253 auto *NewValTy = ArrayType::get(NewValElemTy, Used.size());254 auto *NewUsedVal = ConstantArray::get(NewValTy, Used);255 UsedVar->mutateType(PointerType::getUnqual(M->getContext()));256 UsedVar->setInitializer(NewUsedVal);257}258 259bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {260 // If main isn't present, claim there is no problem.261 if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))262 return false;263 264 // Clone the program to try hacking it apart...265 ValueToValueMapTy VMap;266 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);267 268 // Convert list to set for fast lookup...269 std::set<Function *> Functions;270 for (Function *Func : Funcs) {271 Function *CMF = cast<Function>(VMap[Func]);272 assert(CMF && "Function not in module?!");273 assert(CMF->getFunctionType() == Func->getFunctionType() && "wrong ty");274 assert(CMF->getName() == Func->getName() && "wrong name");275 Functions.insert(CMF);276 }277 278 outs() << "Checking for crash with only these functions: ";279 printFunctionList(Funcs);280 outs() << ": ";281 if (!ReplaceFuncsWithNull) {282 // Loop over and delete any functions which we aren't supposed to be playing283 // with...284 for (Function &I : *M)285 if (!I.isDeclaration() && !Functions.count(&I))286 deleteFunctionBody(&I);287 } else {288 std::vector<GlobalValue *> ToRemove;289 // First, remove aliases to functions we're about to purge.290 for (GlobalAlias &Alias : M->aliases()) {291 GlobalObject *Root = Alias.getAliaseeObject();292 auto *F = dyn_cast<Function>(Root);293 if (F) {294 if (Functions.count(F))295 // We're keeping this function.296 continue;297 } else if (Root->isNullValue()) {298 // This referenced a globalalias that we've already replaced,299 // so we still need to replace this alias.300 } else {301 // Not a function, therefore not something we mess with.302 continue;303 }304 305 PointerType *Ty = cast<PointerType>(Alias.getType());306 Constant *Replacement = ConstantPointerNull::get(Ty);307 Alias.replaceAllUsesWith(Replacement);308 ToRemove.push_back(&Alias);309 }310 311 for (Function &I : *M) {312 if (!I.isDeclaration() && !Functions.count(&I)) {313 PointerType *Ty = cast<PointerType>(I.getType());314 Constant *Replacement = ConstantPointerNull::get(Ty);315 I.replaceAllUsesWith(Replacement);316 ToRemove.push_back(&I);317 }318 }319 320 for (auto *F : ToRemove) {321 F->eraseFromParent();322 }323 324 // Finally, remove any null members from any global intrinsic.325 RemoveFunctionReferences(M.get(), "llvm.used");326 RemoveFunctionReferences(M.get(), "llvm.compiler.used");327 }328 // Try running the hacked up program...329 if (TestFn(BD, M.get())) {330 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...331 332 // Make sure to use function pointers that point into the now-current333 // module.334 Funcs.assign(Functions.begin(), Functions.end());335 return true;336 }337 return false;338}339 340namespace {341/// ReduceCrashingFunctionAttributes reducer - This works by removing342/// attributes on a particular function and seeing if the program still crashes.343/// If it does, then keep the newer, smaller program.344///345class ReduceCrashingFunctionAttributes : public ListReducer<Attribute> {346 BugDriver &BD;347 std::string FnName;348 BugTester TestFn;349 350public:351 ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,352 BugTester testFn)353 : BD(bd), FnName(FnName), TestFn(testFn) {}354 355 Expected<TestResult> doTest(std::vector<Attribute> &Prefix,356 std::vector<Attribute> &Kept) override {357 if (!Kept.empty() && TestFuncAttrs(Kept))358 return KeepSuffix;359 if (!Prefix.empty() && TestFuncAttrs(Prefix))360 return KeepPrefix;361 return NoFailure;362 }363 364 bool TestFuncAttrs(std::vector<Attribute> &Attrs);365};366} // namespace367 368bool ReduceCrashingFunctionAttributes::TestFuncAttrs(369 std::vector<Attribute> &Attrs) {370 // Clone the program to try hacking it apart...371 std::unique_ptr<Module> M = CloneModule(BD.getProgram());372 Function *F = M->getFunction(FnName);373 374 // Build up an AttributeList from the attributes we've been given by the375 // reducer.376 AttrBuilder AB(M->getContext());377 for (auto A : Attrs)378 AB.addAttribute(A);379 AttributeList NewAttrs;380 NewAttrs = NewAttrs.addFnAttributes(BD.getContext(), AB);381 382 // Set this new list of attributes on the function.383 F->setAttributes(NewAttrs);384 385 // If the attribute list includes "optnone" we need to make sure it also386 // includes "noinline" otherwise we will get a verifier failure.387 if (F->hasFnAttribute(Attribute::OptimizeNone))388 F->addFnAttr(Attribute::NoInline);389 390 // If modifying the attribute list leads to invalid IR, revert the change391 if (!isValidModule(M, /*ExitOnFailure=*/false))392 return false;393 394 // Try running on the hacked up program...395 if (TestFn(BD, M.get())) {396 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...397 398 // Pass along the set of attributes that caused the crash.399 Attrs.clear();400 llvm::append_range(Attrs, NewAttrs.getFnAttrs());401 return true;402 }403 return false;404}405 406/// Simplify the CFG without completely destroying it.407/// This is not well defined, but basically comes down to "try to eliminate408/// unreachable blocks and constant fold terminators without deciding that409/// certain undefined behavior cuts off the program at the legs".410static void simpleSimplifyCfg(Function &F, SmallVectorImpl<BasicBlock *> &BBs) {411 if (F.empty())412 return;413 414 for (auto *BB : BBs) {415 ConstantFoldTerminator(BB);416 MergeBlockIntoPredecessor(BB);417 }418 419 // Remove unreachable blocks420 // removeUnreachableBlocks can't be used here, it will turn various421 // undefined behavior into unreachables, but bugpoint was the thing that422 // generated the undefined behavior, and we don't want it to kill the entire423 // program.424 SmallPtrSet<BasicBlock *, 16> Visited(llvm::from_range,425 depth_first(&F.getEntryBlock()));426 427 SmallVector<BasicBlock *, 16> Unreachable;428 for (auto &BB : F)429 if (!Visited.count(&BB))430 Unreachable.push_back(&BB);431 432 // The dead BB's may be in a dead cycle or otherwise have references to each433 // other. Because of this, we have to drop all references first, then delete434 // them all at once.435 for (auto *BB : Unreachable) {436 for (BasicBlock *Successor : successors(&*BB))437 if (Visited.count(Successor))438 Successor->removePredecessor(&*BB);439 BB->dropAllReferences();440 }441 for (auto *BB : Unreachable)442 BB->eraseFromParent();443}444 445namespace {446/// ReduceCrashingBlocks reducer - This works by setting the terminators of447/// all terminators except the specified basic blocks to a 'ret' instruction,448/// then running the simplifycfg pass. This has the effect of chopping up449/// the CFG really fast which can reduce large functions quickly.450///451class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {452 BugDriver &BD;453 BugTester TestFn;454 455public:456 ReduceCrashingBlocks(BugDriver &BD, BugTester testFn)457 : BD(BD), TestFn(testFn) {}458 459 Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,460 std::vector<const BasicBlock *> &Kept) override {461 if (!Kept.empty() && TestBlocks(Kept))462 return KeepSuffix;463 if (!Prefix.empty() && TestBlocks(Prefix))464 return KeepPrefix;465 return NoFailure;466 }467 468 bool TestBlocks(std::vector<const BasicBlock *> &Prefix);469};470} // namespace471 472bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {473 // Clone the program to try hacking it apart...474 ValueToValueMapTy VMap;475 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);476 477 // Convert list to set for fast lookup...478 SmallPtrSet<BasicBlock *, 8> Blocks;479 for (const BasicBlock *BB : BBs)480 Blocks.insert(cast<BasicBlock>(VMap[BB]));481 482 outs() << "Checking for crash with only these blocks:";483 unsigned NumPrint = Blocks.size();484 if (NumPrint > 10)485 NumPrint = 10;486 for (unsigned i = 0, e = NumPrint; i != e; ++i)487 outs() << " " << BBs[i]->getName();488 if (NumPrint < Blocks.size())489 outs() << "... <" << Blocks.size() << " total>";490 outs() << ": ";491 492 // Loop over and delete any hack up any blocks that are not listed...493 for (Function &F : M->functions()) {494 for (BasicBlock &BB : F) {495 if (!Blocks.count(&BB) && BB.getTerminator()->getNumSuccessors()) {496 // Loop over all of the successors of this block, deleting any PHI nodes497 // that might include it.498 for (BasicBlock *Succ : successors(&BB))499 Succ->removePredecessor(&BB);500 501 Instruction *BBTerm = BB.getTerminator();502 if (BBTerm->isEHPad() || BBTerm->getType()->isTokenTy())503 continue;504 if (!BBTerm->getType()->isVoidTy())505 BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));506 507 // Replace the old terminator instruction.508 BB.back().eraseFromParent();509 new UnreachableInst(BB.getContext(), &BB);510 }511 }512 }513 514 // The CFG Simplifier pass may delete one of the basic blocks we are515 // interested in. If it does we need to take the block out of the list. Make516 // a "persistent mapping" by turning basic blocks into <function, name> pairs.517 // This won't work well if blocks are unnamed, but that is just the risk we518 // have to take. FIXME: Can we just name the blocks?519 std::vector<std::pair<std::string, std::string>> BlockInfo;520 521 for (BasicBlock *BB : Blocks)522 BlockInfo.emplace_back(std::string(BB->getParent()->getName()),523 std::string(BB->getName()));524 525 SmallVector<BasicBlock *, 16> ToProcess;526 for (auto &F : *M) {527 for (auto &BB : F)528 if (!Blocks.count(&BB))529 ToProcess.push_back(&BB);530 simpleSimplifyCfg(F, ToProcess);531 ToProcess.clear();532 }533 // Verify we didn't break anything534 isValidModule(M);535 536 // Try running on the hacked up program...537 if (TestFn(BD, M.get())) {538 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...539 540 // Make sure to use basic block pointers that point into the now-current541 // module, and that they don't include any deleted blocks.542 BBs.clear();543 const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();544 for (const auto &BI : BlockInfo) {545 Function *F = cast<Function>(GST.lookup(BI.first));546 Value *V = F->getValueSymbolTable()->lookup(BI.second);547 if (V && V->getType() == Type::getLabelTy(V->getContext()))548 BBs.push_back(cast<BasicBlock>(V));549 }550 return true;551 }552 // It didn't crash, try something else.553 return false;554}555 556namespace {557/// ReduceCrashingConditionals reducer - This works by changing558/// conditional branches to unconditional ones, then simplifying the CFG559/// This has the effect of chopping up the CFG really fast which can reduce560/// large functions quickly.561///562class ReduceCrashingConditionals : public ListReducer<const BasicBlock *> {563 BugDriver &BD;564 BugTester TestFn;565 bool Direction;566 567public:568 ReduceCrashingConditionals(BugDriver &bd, BugTester testFn, bool Direction)569 : BD(bd), TestFn(testFn), Direction(Direction) {}570 571 Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,572 std::vector<const BasicBlock *> &Kept) override {573 if (!Kept.empty() && TestBlocks(Kept))574 return KeepSuffix;575 if (!Prefix.empty() && TestBlocks(Prefix))576 return KeepPrefix;577 return NoFailure;578 }579 580 bool TestBlocks(std::vector<const BasicBlock *> &Prefix);581};582} // namespace583 584bool ReduceCrashingConditionals::TestBlocks(585 std::vector<const BasicBlock *> &BBs) {586 // Clone the program to try hacking it apart...587 ValueToValueMapTy VMap;588 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);589 590 // Convert list to set for fast lookup...591 SmallPtrSet<const BasicBlock *, 8> Blocks;592 for (const auto *BB : BBs)593 Blocks.insert(cast<BasicBlock>(VMap[BB]));594 595 outs() << "Checking for crash with changing conditionals to always jump to "596 << (Direction ? "true" : "false") << ":";597 unsigned NumPrint = Blocks.size();598 if (NumPrint > 10)599 NumPrint = 10;600 for (unsigned i = 0, e = NumPrint; i != e; ++i)601 outs() << " " << BBs[i]->getName();602 if (NumPrint < Blocks.size())603 outs() << "... <" << Blocks.size() << " total>";604 outs() << ": ";605 606 // Loop over and delete any hack up any blocks that are not listed...607 for (auto &F : *M)608 for (auto &BB : F)609 if (!Blocks.count(&BB)) {610 auto *BR = dyn_cast<BranchInst>(BB.getTerminator());611 if (!BR || !BR->isConditional())612 continue;613 if (Direction)614 BR->setCondition(ConstantInt::getTrue(BR->getContext()));615 else616 BR->setCondition(ConstantInt::getFalse(BR->getContext()));617 }618 619 // The following may destroy some blocks, so we save them first620 std::vector<std::pair<std::string, std::string>> BlockInfo;621 622 for (const BasicBlock *BB : Blocks)623 BlockInfo.emplace_back(std::string(BB->getParent()->getName()),624 std::string(BB->getName()));625 626 SmallVector<BasicBlock *, 16> ToProcess;627 for (auto &F : *M) {628 for (auto &BB : F)629 if (!Blocks.count(&BB))630 ToProcess.push_back(&BB);631 simpleSimplifyCfg(F, ToProcess);632 ToProcess.clear();633 }634 // Verify we didn't break anything635 isValidModule(M);636 637 // Try running on the hacked up program...638 if (TestFn(BD, M.get())) {639 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...640 641 // Make sure to use basic block pointers that point into the now-current642 // module, and that they don't include any deleted blocks.643 BBs.clear();644 const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();645 for (auto &BI : BlockInfo) {646 auto *F = cast<Function>(GST.lookup(BI.first));647 Value *V = F->getValueSymbolTable()->lookup(BI.second);648 if (V && V->getType() == Type::getLabelTy(V->getContext()))649 BBs.push_back(cast<BasicBlock>(V));650 }651 return true;652 }653 // It didn't crash, try something else.654 return false;655}656 657namespace {658/// SimplifyCFG reducer - This works by calling SimplifyCFG on each basic block659/// in the program.660 661class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {662 BugDriver &BD;663 BugTester TestFn;664 TargetTransformInfo TTI;665 666public:667 ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)668 : BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}669 670 Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,671 std::vector<const BasicBlock *> &Kept) override {672 if (!Kept.empty() && TestBlocks(Kept))673 return KeepSuffix;674 if (!Prefix.empty() && TestBlocks(Prefix))675 return KeepPrefix;676 return NoFailure;677 }678 679 bool TestBlocks(std::vector<const BasicBlock *> &Prefix);680};681} // namespace682 683bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {684 // Clone the program to try hacking it apart...685 ValueToValueMapTy VMap;686 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);687 688 // Convert list to set for fast lookup...689 SmallPtrSet<const BasicBlock *, 8> Blocks;690 for (const auto *BB : BBs)691 Blocks.insert(cast<BasicBlock>(VMap[BB]));692 693 outs() << "Checking for crash with CFG simplifying:";694 unsigned NumPrint = Blocks.size();695 if (NumPrint > 10)696 NumPrint = 10;697 for (unsigned i = 0, e = NumPrint; i != e; ++i)698 outs() << " " << BBs[i]->getName();699 if (NumPrint < Blocks.size())700 outs() << "... <" << Blocks.size() << " total>";701 outs() << ": ";702 703 // The following may destroy some blocks, so we save them first704 std::vector<std::pair<std::string, std::string>> BlockInfo;705 706 for (const BasicBlock *BB : Blocks)707 BlockInfo.emplace_back(std::string(BB->getParent()->getName()),708 std::string(BB->getName()));709 710 // Loop over and delete any hack up any blocks that are not listed...711 for (auto &F : *M)712 // Loop over all of the basic blocks and remove them if they are unneeded.713 for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {714 if (!Blocks.count(&*BBIt)) {715 ++BBIt;716 continue;717 }718 simplifyCFG(&*BBIt++, TTI);719 }720 // Verify we didn't break anything721 isValidModule(M);722 723 // Try running on the hacked up program...724 if (TestFn(BD, M.get())) {725 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...726 727 // Make sure to use basic block pointers that point into the now-current728 // module, and that they don't include any deleted blocks.729 BBs.clear();730 const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();731 for (auto &BI : BlockInfo) {732 auto *F = cast<Function>(GST.lookup(BI.first));733 Value *V = F->getValueSymbolTable()->lookup(BI.second);734 if (V && V->getType() == Type::getLabelTy(V->getContext()))735 BBs.push_back(cast<BasicBlock>(V));736 }737 return true;738 }739 // It didn't crash, try something else.740 return false;741}742 743namespace {744/// ReduceCrashingInstructions reducer - This works by removing the specified745/// non-terminator instructions and replacing them with undef.746///747class ReduceCrashingInstructions : public ListReducer<const Instruction *> {748 BugDriver &BD;749 BugTester TestFn;750 751public:752 ReduceCrashingInstructions(BugDriver &bd, BugTester testFn)753 : BD(bd), TestFn(testFn) {}754 755 Expected<TestResult> doTest(std::vector<const Instruction *> &Prefix,756 std::vector<const Instruction *> &Kept) override {757 if (!Kept.empty() && TestInsts(Kept))758 return KeepSuffix;759 if (!Prefix.empty() && TestInsts(Prefix))760 return KeepPrefix;761 return NoFailure;762 }763 764 bool TestInsts(std::vector<const Instruction *> &Prefix);765};766} // namespace767 768bool ReduceCrashingInstructions::TestInsts(769 std::vector<const Instruction *> &Insts) {770 // Clone the program to try hacking it apart...771 ValueToValueMapTy VMap;772 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);773 774 // Convert list to set for fast lookup...775 SmallPtrSet<Instruction *, 32> Instructions;776 for (const Instruction *Inst : Insts) {777 assert(!Inst->isTerminator());778 Instructions.insert(cast<Instruction>(VMap[Inst]));779 }780 781 outs() << "Checking for crash with only " << Instructions.size();782 if (Instructions.size() == 1)783 outs() << " instruction: ";784 else785 outs() << " instructions: ";786 787 for (Function &F : *M)788 for (BasicBlock &BB : F)789 for (Instruction &Inst : llvm::make_early_inc_range(BB)) {790 if (!Instructions.count(&Inst) && !Inst.isTerminator() &&791 !Inst.isEHPad() && !Inst.getType()->isTokenTy() &&792 !Inst.isSwiftError()) {793 if (!Inst.getType()->isVoidTy())794 Inst.replaceAllUsesWith(PoisonValue::get(Inst.getType()));795 Inst.eraseFromParent();796 }797 }798 799 // Verify that this is still valid.800 isValidModule(M, /*ExitOnFailure=*/false);801 802 // Try running on the hacked up program...803 if (TestFn(BD, M.get())) {804 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...805 806 // Make sure to use instruction pointers that point into the now-current807 // module, and that they don't include any deleted blocks.808 Insts.clear();809 llvm::append_range(Insts, Instructions);810 return true;811 }812 // It didn't crash, try something else.813 return false;814}815 816namespace {817/// ReduceCrashingMetadata reducer - This works by removing all metadata from818/// the specified instructions.819///820class ReduceCrashingMetadata : public ListReducer<Instruction *> {821 BugDriver &BD;822 BugTester TestFn;823 824public:825 ReduceCrashingMetadata(BugDriver &bd, BugTester testFn)826 : BD(bd), TestFn(testFn) {}827 828 Expected<TestResult> doTest(std::vector<Instruction *> &Prefix,829 std::vector<Instruction *> &Kept) override {830 if (!Kept.empty() && TestInsts(Kept))831 return KeepSuffix;832 if (!Prefix.empty() && TestInsts(Prefix))833 return KeepPrefix;834 return NoFailure;835 }836 837 bool TestInsts(std::vector<Instruction *> &Prefix);838};839} // namespace840 841bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {842 // Clone the program to try hacking it apart...843 ValueToValueMapTy VMap;844 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);845 846 // Convert list to set for fast lookup...847 SmallPtrSet<Instruction *, 32> Instructions;848 for (Instruction *I : Insts)849 Instructions.insert(cast<Instruction>(VMap[I]));850 851 outs() << "Checking for crash with metadata retained from "852 << Instructions.size();853 if (Instructions.size() == 1)854 outs() << " instruction: ";855 else856 outs() << " instructions: ";857 858 // Try to drop instruction metadata from all instructions, except the ones859 // selected in Instructions.860 for (Function &F : *M)861 for (Instruction &Inst : instructions(F)) {862 if (!Instructions.count(&Inst)) {863 Inst.dropUnknownNonDebugMetadata();864 Inst.setDebugLoc({});865 }866 }867 868 // Verify that this is still valid.869 isValidModule(M, /*ExitOnFailure=*/false);870 871 // Try running on the hacked up program...872 if (TestFn(BD, M.get())) {873 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...874 875 // Make sure to use instruction pointers that point into the now-current876 // module, and that they don't include any deleted blocks.877 Insts.clear();878 llvm::append_range(Insts, Instructions);879 return true;880 }881 // It didn't crash, try something else.882 return false;883}884 885namespace {886// Reduce the list of Named Metadata nodes. We keep this as a list of887// names to avoid having to convert back and forth every time.888class ReduceCrashingNamedMD : public ListReducer<std::string> {889 BugDriver &BD;890 BugTester TestFn;891 892public:893 ReduceCrashingNamedMD(BugDriver &bd, BugTester testFn)894 : BD(bd), TestFn(testFn) {}895 896 Expected<TestResult> doTest(std::vector<std::string> &Prefix,897 std::vector<std::string> &Kept) override {898 if (!Kept.empty() && TestNamedMDs(Kept))899 return KeepSuffix;900 if (!Prefix.empty() && TestNamedMDs(Prefix))901 return KeepPrefix;902 return NoFailure;903 }904 905 bool TestNamedMDs(std::vector<std::string> &NamedMDs);906};907} // namespace908 909bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {910 911 ValueToValueMapTy VMap;912 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);913 914 outs() << "Checking for crash with only these named metadata nodes:";915 unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);916 for (unsigned i = 0, e = NumPrint; i != e; ++i)917 outs() << " " << NamedMDs[i];918 if (NumPrint < NamedMDs.size())919 outs() << "... <" << NamedMDs.size() << " total>";920 outs() << ": ";921 922 // Make a StringMap for faster lookup923 StringSet<> Names(llvm::from_range, NamedMDs);924 925 // First collect all the metadata to delete in a vector, then926 // delete them all at once to avoid invalidating the iterator927 std::vector<NamedMDNode *> ToDelete;928 ToDelete.reserve(M->named_metadata_size() - Names.size());929 for (auto &NamedMD : M->named_metadata())930 // Always keep a nonempty llvm.dbg.cu because the Verifier would complain.931 if (!Names.count(NamedMD.getName()) &&932 (!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0)))933 ToDelete.push_back(&NamedMD);934 935 for (auto *NamedMD : ToDelete)936 NamedMD->eraseFromParent();937 938 // Verify that this is still valid.939 isValidModule(M, /*ExitOnFailure=*/false);940 941 // Try running on the hacked up program...942 if (TestFn(BD, M.get())) {943 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...944 return true;945 }946 return false;947}948 949namespace {950// Reduce the list of operands to named metadata nodes951class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {952 BugDriver &BD;953 BugTester TestFn;954 955public:956 ReduceCrashingNamedMDOps(BugDriver &bd, BugTester testFn)957 : BD(bd), TestFn(testFn) {}958 959 Expected<TestResult> doTest(std::vector<const MDNode *> &Prefix,960 std::vector<const MDNode *> &Kept) override {961 if (!Kept.empty() && TestNamedMDOps(Kept))962 return KeepSuffix;963 if (!Prefix.empty() && TestNamedMDOps(Prefix))964 return KeepPrefix;965 return NoFailure;966 }967 968 bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps);969};970} // namespace971 972bool ReduceCrashingNamedMDOps::TestNamedMDOps(973 std::vector<const MDNode *> &NamedMDOps) {974 // Convert list to set for fast lookup...975 SmallPtrSet<const MDNode *, 32> OldMDNodeOps(llvm::from_range, NamedMDOps);976 977 outs() << "Checking for crash with only " << OldMDNodeOps.size();978 if (OldMDNodeOps.size() == 1)979 outs() << " named metadata operand: ";980 else981 outs() << " named metadata operands: ";982 983 ValueToValueMapTy VMap;984 std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);985 986 // This is a little wasteful. In the future it might be good if we could have987 // these dropped during cloning.988 for (auto &NamedMD : BD.getProgram().named_metadata()) {989 // Drop the old one and create a new one990 M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));991 NamedMDNode *NewNamedMDNode =992 M->getOrInsertNamedMetadata(NamedMD.getName());993 for (MDNode *op : NamedMD.operands())994 if (OldMDNodeOps.count(op))995 NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap)));996 }997 998 // Verify that this is still valid.999 isValidModule(M, /*ExitOnFailure=*/false);1000 1001 // Try running on the hacked up program...1002 if (TestFn(BD, M.get())) {1003 // Make sure to use instruction pointers that point into the now-current1004 // module, and that they don't include any deleted blocks.1005 NamedMDOps.clear();1006 for (const MDNode *Node : OldMDNodeOps)1007 NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));1008 1009 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...1010 return true;1011 }1012 // It didn't crash, try something else.1013 return false;1014}1015 1016/// Attempt to eliminate as many global initializers as possible.1017static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {1018 Module &OrigM = BD.getProgram();1019 if (OrigM.global_empty())1020 return Error::success();1021 1022 // Now try to reduce the number of global variable initializers in the1023 // module to something small.1024 std::unique_ptr<Module> M = CloneModule(OrigM);1025 bool DeletedInit = false;1026 1027 for (GlobalVariable &GV : M->globals()) {1028 if (GV.hasInitializer()) {1029 deleteGlobalInitializer(&GV);1030 GV.setLinkage(GlobalValue::ExternalLinkage);1031 GV.setComdat(nullptr);1032 DeletedInit = true;1033 }1034 }1035 1036 if (!DeletedInit)1037 return Error::success();1038 1039 // See if the program still causes a crash...1040 outs() << "\nChecking to see if we can delete global inits: ";1041 1042 if (TestFn(BD, M.get())) { // Still crashes?1043 BD.setNewProgram(std::move(M));1044 outs() << "\n*** Able to remove all global initializers!\n";1045 return Error::success();1046 }1047 1048 // No longer crashes.1049 outs() << " - Removing all global inits hides problem!\n";1050 1051 std::vector<GlobalVariable *> GVs;1052 for (GlobalVariable &GV : OrigM.globals())1053 if (GV.hasInitializer())1054 GVs.push_back(&GV);1055 1056 if (GVs.size() > 1 && !BugpointIsInterrupted) {1057 outs() << "\n*** Attempting to reduce the number of global initializers "1058 << "in the testcase\n";1059 1060 unsigned OldSize = GVs.size();1061 Expected<bool> Result =1062 ReduceCrashingGlobalInitializers(BD, TestFn).reduceList(GVs);1063 if (Error E = Result.takeError())1064 return E;1065 1066 if (GVs.size() < OldSize)1067 BD.emitProgressBitcode(BD.getProgram(), "reduced-global-variables");1068 }1069 return Error::success();1070}1071 1072static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {1073 // Attempt to delete instructions using bisection. This should help out nasty1074 // cases with large basic blocks where the problem is at one end.1075 if (!BugpointIsInterrupted) {1076 std::vector<const Instruction *> Insts;1077 for (const Function &F : BD.getProgram())1078 for (const BasicBlock &BB : F)1079 for (const Instruction &I : BB)1080 if (!I.isTerminator())1081 Insts.push_back(&I);1082 1083 Expected<bool> Result =1084 ReduceCrashingInstructions(BD, TestFn).reduceList(Insts);1085 if (Error E = Result.takeError())1086 return E;1087 }1088 1089 unsigned Simplification = 2;1090 do {1091 if (BugpointIsInterrupted)1092 // TODO: Should we distinguish this with an "interrupted error"?1093 return Error::success();1094 --Simplification;1095 outs() << "\n*** Attempting to reduce testcase by deleting instruc"1096 << "tions: Simplification Level #" << Simplification << '\n';1097 1098 // Now that we have deleted the functions that are unnecessary for the1099 // program, try to remove instructions that are not necessary to cause the1100 // crash. To do this, we loop through all of the instructions in the1101 // remaining functions, deleting them (replacing any values produced with1102 // nulls), and then running ADCE and SimplifyCFG. If the transformed input1103 // still triggers failure, keep deleting until we cannot trigger failure1104 // anymore.1105 //1106 unsigned InstructionsToSkipBeforeDeleting = 0;1107 TryAgain:1108 1109 // Loop over all of the (non-terminator) instructions remaining in the1110 // function, attempting to delete them.1111 unsigned CurInstructionNum = 0;1112 for (Module::const_iterator FI = BD.getProgram().begin(),1113 E = BD.getProgram().end();1114 FI != E; ++FI)1115 if (!FI->isDeclaration())1116 for (const BasicBlock &BI : *FI)1117 for (BasicBlock::const_iterator I = BI.begin(), E = --BI.end();1118 I != E; ++I, ++CurInstructionNum) {1119 if (InstructionsToSkipBeforeDeleting) {1120 --InstructionsToSkipBeforeDeleting;1121 } else {1122 if (BugpointIsInterrupted)1123 // TODO: Should this be some kind of interrupted error?1124 return Error::success();1125 1126 if (I->isEHPad() || I->getType()->isTokenTy() ||1127 I->isSwiftError())1128 continue;1129 1130 outs() << "Checking instruction: " << *I;1131 std::unique_ptr<Module> M =1132 BD.deleteInstructionFromProgram(&*I, Simplification);1133 1134 // Find out if the pass still crashes on this pass...1135 if (TestFn(BD, M.get())) {1136 // Yup, it does, we delete the old module, and continue trying1137 // to reduce the testcase...1138 BD.setNewProgram(std::move(M));1139 InstructionsToSkipBeforeDeleting = CurInstructionNum;1140 goto TryAgain; // I wish I had a multi-level break here!1141 }1142 }1143 }1144 1145 if (InstructionsToSkipBeforeDeleting) {1146 InstructionsToSkipBeforeDeleting = 0;1147 goto TryAgain;1148 }1149 1150 } while (Simplification);1151 1152 // Attempt to drop metadata from instructions that does not contribute to the1153 // crash.1154 if (!BugpointIsInterrupted) {1155 std::vector<Instruction *> Insts;1156 for (Function &F : BD.getProgram())1157 for (Instruction &I : instructions(F))1158 Insts.push_back(&I);1159 1160 Expected<bool> Result =1161 ReduceCrashingMetadata(BD, TestFn).reduceList(Insts);1162 if (Error E = Result.takeError())1163 return E;1164 }1165 1166 BD.emitProgressBitcode(BD.getProgram(), "reduced-instructions");1167 return Error::success();1168}1169 1170/// DebugACrash - Given a predicate that determines whether a component crashes1171/// on a program, try to destructively reduce the program while still keeping1172/// the predicate true.1173static Error DebugACrash(BugDriver &BD, BugTester TestFn) {1174 // See if we can get away with nuking some of the global variable initializers1175 // in the program...1176 if (!NoGlobalRM)1177 if (Error E = ReduceGlobalInitializers(BD, TestFn))1178 return E;1179 1180 // Now try to reduce the number of functions in the module to something small.1181 std::vector<Function *> Functions;1182 for (Function &F : BD.getProgram())1183 if (!F.isDeclaration())1184 Functions.push_back(&F);1185 1186 if (Functions.size() > 1 && !BugpointIsInterrupted) {1187 outs() << "\n*** Attempting to reduce the number of functions "1188 "in the testcase\n";1189 1190 unsigned OldSize = Functions.size();1191 Expected<bool> Result =1192 ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);1193 if (Error E = Result.takeError())1194 return E;1195 1196 if (Functions.size() < OldSize)1197 BD.emitProgressBitcode(BD.getProgram(), "reduced-function");1198 }1199 1200 if (!NoAttributeRM) {1201 // For each remaining function, try to reduce that function's attributes.1202 std::vector<std::string> FunctionNames;1203 for (Function &F : BD.getProgram())1204 FunctionNames.push_back(std::string(F.getName()));1205 1206 if (!FunctionNames.empty() && !BugpointIsInterrupted) {1207 outs() << "\n*** Attempting to reduce the number of function attributes"1208 " in the testcase\n";1209 1210 unsigned OldSize = 0;1211 unsigned NewSize = 0;1212 for (std::string &Name : FunctionNames) {1213 Function *Fn = BD.getProgram().getFunction(Name);1214 assert(Fn && "Could not find function?");1215 1216 std::vector<Attribute> Attrs;1217 llvm::append_range(Attrs, Fn->getAttributes().getFnAttrs());1218 1219 OldSize += Attrs.size();1220 Expected<bool> Result =1221 ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);1222 if (Error E = Result.takeError())1223 return E;1224 1225 NewSize += Attrs.size();1226 }1227 1228 if (OldSize < NewSize)1229 BD.emitProgressBitcode(BD.getProgram(), "reduced-function-attributes");1230 }1231 }1232 1233 // Attempt to change conditional branches into unconditional branches to1234 // eliminate blocks.1235 if (!DisableSimplifyCFG && !BugpointIsInterrupted) {1236 std::vector<const BasicBlock *> Blocks;1237 for (Function &F : BD.getProgram())1238 for (BasicBlock &BB : F)1239 Blocks.push_back(&BB);1240 unsigned OldSize = Blocks.size();1241 Expected<bool> Result =1242 ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks);1243 if (Error E = Result.takeError())1244 return E;1245 Result = ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks);1246 if (Error E = Result.takeError())1247 return E;1248 if (Blocks.size() < OldSize)1249 BD.emitProgressBitcode(BD.getProgram(), "reduced-conditionals");1250 }1251 1252 // Attempt to delete entire basic blocks at a time to speed up1253 // convergence... this actually works by setting the terminator of the blocks1254 // to a return instruction then running simplifycfg, which can potentially1255 // shrinks the code dramatically quickly1256 //1257 if (!DisableSimplifyCFG && !BugpointIsInterrupted) {1258 std::vector<const BasicBlock *> Blocks;1259 for (Function &F : BD.getProgram())1260 for (BasicBlock &BB : F)1261 Blocks.push_back(&BB);1262 unsigned OldSize = Blocks.size();1263 Expected<bool> Result = ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks);1264 if (Error E = Result.takeError())1265 return E;1266 if (Blocks.size() < OldSize)1267 BD.emitProgressBitcode(BD.getProgram(), "reduced-blocks");1268 }1269 1270 if (!DisableSimplifyCFG && !BugpointIsInterrupted) {1271 std::vector<const BasicBlock *> Blocks;1272 for (Function &F : BD.getProgram())1273 for (BasicBlock &BB : F)1274 Blocks.push_back(&BB);1275 unsigned OldSize = Blocks.size();1276 Expected<bool> Result = ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks);1277 if (Error E = Result.takeError())1278 return E;1279 if (Blocks.size() < OldSize)1280 BD.emitProgressBitcode(BD.getProgram(), "reduced-simplifycfg");1281 }1282 1283 // Attempt to delete instructions using bisection. This should help out nasty1284 // cases with large basic blocks where the problem is at one end.1285 if (!BugpointIsInterrupted)1286 if (Error E = ReduceInsts(BD, TestFn))1287 return E;1288 1289 // Attempt to strip debug info metadata.1290 auto stripMetadata = [&](std::function<bool(Module &)> strip) {1291 std::unique_ptr<Module> M = CloneModule(BD.getProgram());1292 strip(*M);1293 if (TestFn(BD, M.get()))1294 BD.setNewProgram(std::move(M));1295 };1296 if (!NoStripDebugInfo && !BugpointIsInterrupted) {1297 outs() << "\n*** Attempting to strip the debug info: ";1298 stripMetadata(StripDebugInfo);1299 }1300 if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {1301 outs() << "\n*** Attempting to strip the debug type info: ";1302 stripMetadata(stripNonLineTableDebugInfo);1303 }1304 1305 if (!NoNamedMDRM) {1306 if (!BugpointIsInterrupted) {1307 // Try to reduce the amount of global metadata (particularly debug info),1308 // by dropping global named metadata that anchors them1309 outs() << "\n*** Attempting to remove named metadata: ";1310 std::vector<std::string> NamedMDNames;1311 for (auto &NamedMD : BD.getProgram().named_metadata())1312 NamedMDNames.push_back(NamedMD.getName().str());1313 Expected<bool> Result =1314 ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);1315 if (Error E = Result.takeError())1316 return E;1317 }1318 1319 if (!BugpointIsInterrupted) {1320 // Now that we quickly dropped all the named metadata that doesn't1321 // contribute to the crash, bisect the operands of the remaining ones1322 std::vector<const MDNode *> NamedMDOps;1323 for (auto &NamedMD : BD.getProgram().named_metadata())1324 llvm::append_range(NamedMDOps, NamedMD.operands());1325 Expected<bool> Result =1326 ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps);1327 if (Error E = Result.takeError())1328 return E;1329 }1330 BD.emitProgressBitcode(BD.getProgram(), "reduced-named-md");1331 }1332 1333 // Try to clean up the testcase by running funcresolve and globaldce...1334 if (!BugpointIsInterrupted) {1335 outs() << "\n*** Attempting to perform final cleanups: ";1336 std::unique_ptr<Module> M = CloneModule(BD.getProgram());1337 M = BD.performFinalCleanups(std::move(M), true);1338 1339 // Find out if the pass still crashes on the cleaned up program...1340 if (M && TestFn(BD, M.get()))1341 BD.setNewProgram(1342 std::move(M)); // Yup, it does, keep the reduced version...1343 }1344 1345 BD.emitProgressBitcode(BD.getProgram(), "reduced-simplified");1346 1347 return Error::success();1348}1349 1350static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {1351 return BD.runPasses(*M, BD.getPassesToRun());1352}1353 1354/// debugOptimizerCrash - This method is called when some pass crashes on input.1355/// It attempts to prune down the testcase to something reasonable, and figure1356/// out exactly which pass is crashing.1357///1358Error BugDriver::debugOptimizerCrash(const std::string &ID) {1359 outs() << "\n*** Debugging optimizer crash!\n";1360 1361 // Reduce the list of passes which causes the optimizer to crash...1362 if (!BugpointIsInterrupted && !DontReducePassList) {1363 Expected<bool> Result = ReducePassList(*this).reduceList(PassesToRun);1364 if (Error E = Result.takeError())1365 return E;1366 }1367 1368 outs() << "\n*** Found crashing pass"1369 << (PassesToRun.size() == 1 ? ": " : "es: ")1370 << getPassesString(PassesToRun) << '\n';1371 1372 emitProgressBitcode(*Program, ID);1373 1374 auto Res = DebugACrash(*this, TestForOptimizerCrash);1375 if (Res || DontReducePassList)1376 return Res;1377 // Try to reduce the pass list again. This covers additional cases1378 // we failed to reduce earlier, because of more complex pass dependencies1379 // triggering the crash.1380 auto SecondRes = ReducePassList(*this).reduceList(PassesToRun);1381 if (Error E = SecondRes.takeError())1382 return E;1383 outs() << "\n*** Found crashing pass"1384 << (PassesToRun.size() == 1 ? ": " : "es: ")1385 << getPassesString(PassesToRun) << '\n';1386 1387 emitProgressBitcode(getProgram(), "reduced-simplified");1388 return Res;1389}1390 1391static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {1392 if (Error E = BD.compileProgram(*M)) {1393 if (VerboseErrors)1394 errs() << toString(std::move(E)) << "\n";1395 else {1396 consumeError(std::move(E));1397 errs() << "<crash>\n";1398 }1399 return true; // Tool is still crashing.1400 }1401 errs() << '\n';1402 return false;1403}1404 1405/// debugCodeGeneratorCrash - This method is called when the code generator1406/// crashes on an input. It attempts to reduce the input as much as possible1407/// while still causing the code generator to crash.1408Error BugDriver::debugCodeGeneratorCrash() {1409 errs() << "*** Debugging code generator crash!\n";1410 1411 return DebugACrash(*this, TestForCodeGenCrash);1412}1413