Path: blob/main/contrib/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
35231 views
//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the bugpoint internals that narrow down compilation crashes9//10//===----------------------------------------------------------------------===//1112#include "BugDriver.h"13#include "ListReducer.h"14#include "ToolRunner.h"15#include "llvm/ADT/SmallPtrSet.h"16#include "llvm/ADT/StringSet.h"17#include "llvm/Analysis/TargetTransformInfo.h"18#include "llvm/IR/CFG.h"19#include "llvm/IR/Constants.h"20#include "llvm/IR/DebugInfo.h"21#include "llvm/IR/DerivedTypes.h"22#include "llvm/IR/InstIterator.h"23#include "llvm/IR/Instructions.h"24#include "llvm/IR/LegacyPassManager.h"25#include "llvm/IR/Module.h"26#include "llvm/IR/ValueSymbolTable.h"27#include "llvm/IR/Verifier.h"28#include "llvm/Pass.h"29#include "llvm/Support/CommandLine.h"30#include "llvm/Support/FileUtilities.h"31#include "llvm/Transforms/Scalar.h"32#include "llvm/Transforms/Utils/BasicBlockUtils.h"33#include "llvm/Transforms/Utils/Cloning.h"34#include "llvm/Transforms/Utils/Local.h"35#include <set>36using namespace llvm;3738namespace {39cl::opt<bool> KeepMain("keep-main",40cl::desc("Force function reduction to keep main"),41cl::init(false));42cl::opt<bool> NoGlobalRM("disable-global-remove",43cl::desc("Do not remove global variables"),44cl::init(false));4546cl::opt<bool> NoAttributeRM("disable-attribute-remove",47cl::desc("Do not remove function attributes"),48cl::init(false));4950cl::opt<bool> ReplaceFuncsWithNull(51"replace-funcs-with-null",52cl::desc("When stubbing functions, replace all uses will null"),53cl::init(false));54cl::opt<bool> DontReducePassList("disable-pass-list-reduction",55cl::desc("Skip pass list reduction steps"),56cl::init(false));5758cl::opt<bool> NoNamedMDRM("disable-namedmd-remove",59cl::desc("Do not remove global named metadata"),60cl::init(false));61cl::opt<bool> NoStripDebugInfo("disable-strip-debuginfo",62cl::desc("Do not strip debug info metadata"),63cl::init(false));64cl::opt<bool> NoStripDebugTypeInfo("disable-strip-debug-types",65cl::desc("Do not strip debug type info metadata"),66cl::init(false));67cl::opt<bool> VerboseErrors("verbose-errors",68cl::desc("Print the output of crashing program"),69cl::init(false));70}7172static bool isValidModule(std::unique_ptr<Module> &M,73bool ExitOnFailure = true) {74if (!llvm::verifyModule(*M, &llvm::errs()))75return true;7677if (ExitOnFailure) {78llvm::errs() << "verify failed!\n";79exit(1);80}81return false;82}8384namespace llvm {85class ReducePassList : public ListReducer<std::string> {86BugDriver &BD;8788public:89ReducePassList(BugDriver &bd) : BD(bd) {}9091// Return true iff running the "removed" passes succeeds, and running the92// "Kept" passes fail when run on the output of the "removed" passes. If we93// return true, we update the current module of bugpoint.94Expected<TestResult> doTest(std::vector<std::string> &Removed,95std::vector<std::string> &Kept) override;96};97}9899Expected<ReducePassList::TestResult>100ReducePassList::doTest(std::vector<std::string> &Prefix,101std::vector<std::string> &Suffix) {102std::string PrefixOutput;103std::unique_ptr<Module> OrigProgram;104if (!Prefix.empty()) {105outs() << "Checking to see if these passes crash: "106<< getPassesString(Prefix) << ": ";107if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))108return KeepPrefix;109110OrigProgram = std::move(BD.Program);111112BD.Program = parseInputFile(PrefixOutput, BD.getContext());113if (BD.Program == nullptr) {114errs() << BD.getToolName() << ": Error reading bitcode file '"115<< PrefixOutput << "'!\n";116exit(1);117}118sys::fs::remove(PrefixOutput);119}120121outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)122<< ": ";123124if (BD.runPasses(BD.getProgram(), Suffix))125return KeepSuffix; // The suffix crashes alone...126127// Nothing failed, restore state...128if (OrigProgram)129BD.Program = std::move(OrigProgram);130return NoFailure;131}132133using BugTester = bool (*)(const BugDriver &, Module *);134135namespace {136/// ReduceCrashingGlobalInitializers - This works by removing global variable137/// initializers and seeing if the program still crashes. If it does, then we138/// keep that program and try again.139class ReduceCrashingGlobalInitializers : public ListReducer<GlobalVariable *> {140BugDriver &BD;141BugTester TestFn;142143public:144ReduceCrashingGlobalInitializers(BugDriver &bd, BugTester testFn)145: BD(bd), TestFn(testFn) {}146147Expected<TestResult> doTest(std::vector<GlobalVariable *> &Prefix,148std::vector<GlobalVariable *> &Kept) override {149if (!Kept.empty() && TestGlobalVariables(Kept))150return KeepSuffix;151if (!Prefix.empty() && TestGlobalVariables(Prefix))152return KeepPrefix;153return NoFailure;154}155156bool TestGlobalVariables(std::vector<GlobalVariable *> &GVs);157};158}159160bool ReduceCrashingGlobalInitializers::TestGlobalVariables(161std::vector<GlobalVariable *> &GVs) {162// Clone the program to try hacking it apart...163ValueToValueMapTy VMap;164std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);165166// Convert list to set for fast lookup...167std::set<GlobalVariable *> GVSet;168169for (unsigned i = 0, e = GVs.size(); i != e; ++i) {170GlobalVariable *CMGV = cast<GlobalVariable>(VMap[GVs[i]]);171assert(CMGV && "Global Variable not in module?!");172GVSet.insert(CMGV);173}174175outs() << "Checking for crash with only these global variables: ";176PrintGlobalVariableList(GVs);177outs() << ": ";178179// Loop over and delete any global variables which we aren't supposed to be180// playing with...181for (GlobalVariable &I : M->globals())182if (I.hasInitializer() && !GVSet.count(&I)) {183DeleteGlobalInitializer(&I);184I.setLinkage(GlobalValue::ExternalLinkage);185I.setComdat(nullptr);186}187188// Try running the hacked up program...189if (TestFn(BD, M.get())) {190BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...191192// Make sure to use global variable pointers that point into the now-current193// module.194GVs.assign(GVSet.begin(), GVSet.end());195return true;196}197198return false;199}200201namespace {202/// ReduceCrashingFunctions reducer - This works by removing functions and203/// seeing if the program still crashes. If it does, then keep the newer,204/// smaller program.205///206class ReduceCrashingFunctions : public ListReducer<Function *> {207BugDriver &BD;208BugTester TestFn;209210public:211ReduceCrashingFunctions(BugDriver &bd, BugTester testFn)212: BD(bd), TestFn(testFn) {}213214Expected<TestResult> doTest(std::vector<Function *> &Prefix,215std::vector<Function *> &Kept) override {216if (!Kept.empty() && TestFuncs(Kept))217return KeepSuffix;218if (!Prefix.empty() && TestFuncs(Prefix))219return KeepPrefix;220return NoFailure;221}222223bool TestFuncs(std::vector<Function *> &Prefix);224};225}226227static void RemoveFunctionReferences(Module *M, const char *Name) {228auto *UsedVar = M->getGlobalVariable(Name, true);229if (!UsedVar || !UsedVar->hasInitializer())230return;231if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) {232assert(UsedVar->use_empty());233UsedVar->eraseFromParent();234return;235}236auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer());237std::vector<Constant *> Used;238for (Value *V : OldUsedVal->operand_values()) {239Constant *Op = cast<Constant>(V->stripPointerCasts());240if (!Op->isNullValue()) {241Used.push_back(cast<Constant>(V));242}243}244auto *NewValElemTy = OldUsedVal->getType()->getElementType();245auto *NewValTy = ArrayType::get(NewValElemTy, Used.size());246auto *NewUsedVal = ConstantArray::get(NewValTy, Used);247UsedVar->mutateType(NewUsedVal->getType()->getPointerTo());248UsedVar->setInitializer(NewUsedVal);249}250251bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {252// If main isn't present, claim there is no problem.253if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))254return false;255256// Clone the program to try hacking it apart...257ValueToValueMapTy VMap;258std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);259260// Convert list to set for fast lookup...261std::set<Function *> Functions;262for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {263Function *CMF = cast<Function>(VMap[Funcs[i]]);264assert(CMF && "Function not in module?!");265assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty");266assert(CMF->getName() == Funcs[i]->getName() && "wrong name");267Functions.insert(CMF);268}269270outs() << "Checking for crash with only these functions: ";271PrintFunctionList(Funcs);272outs() << ": ";273if (!ReplaceFuncsWithNull) {274// Loop over and delete any functions which we aren't supposed to be playing275// with...276for (Function &I : *M)277if (!I.isDeclaration() && !Functions.count(&I))278DeleteFunctionBody(&I);279} else {280std::vector<GlobalValue *> ToRemove;281// First, remove aliases to functions we're about to purge.282for (GlobalAlias &Alias : M->aliases()) {283GlobalObject *Root = Alias.getAliaseeObject();284auto *F = dyn_cast<Function>(Root);285if (F) {286if (Functions.count(F))287// We're keeping this function.288continue;289} else if (Root->isNullValue()) {290// This referenced a globalalias that we've already replaced,291// so we still need to replace this alias.292} else {293// Not a function, therefore not something we mess with.294continue;295}296297PointerType *Ty = cast<PointerType>(Alias.getType());298Constant *Replacement = ConstantPointerNull::get(Ty);299Alias.replaceAllUsesWith(Replacement);300ToRemove.push_back(&Alias);301}302303for (Function &I : *M) {304if (!I.isDeclaration() && !Functions.count(&I)) {305PointerType *Ty = cast<PointerType>(I.getType());306Constant *Replacement = ConstantPointerNull::get(Ty);307I.replaceAllUsesWith(Replacement);308ToRemove.push_back(&I);309}310}311312for (auto *F : ToRemove) {313F->eraseFromParent();314}315316// Finally, remove any null members from any global intrinsic.317RemoveFunctionReferences(M.get(), "llvm.used");318RemoveFunctionReferences(M.get(), "llvm.compiler.used");319}320// Try running the hacked up program...321if (TestFn(BD, M.get())) {322BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...323324// Make sure to use function pointers that point into the now-current325// module.326Funcs.assign(Functions.begin(), Functions.end());327return true;328}329return false;330}331332namespace {333/// ReduceCrashingFunctionAttributes reducer - This works by removing334/// attributes on a particular function and seeing if the program still crashes.335/// If it does, then keep the newer, smaller program.336///337class ReduceCrashingFunctionAttributes : public ListReducer<Attribute> {338BugDriver &BD;339std::string FnName;340BugTester TestFn;341342public:343ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,344BugTester testFn)345: BD(bd), FnName(FnName), TestFn(testFn) {}346347Expected<TestResult> doTest(std::vector<Attribute> &Prefix,348std::vector<Attribute> &Kept) override {349if (!Kept.empty() && TestFuncAttrs(Kept))350return KeepSuffix;351if (!Prefix.empty() && TestFuncAttrs(Prefix))352return KeepPrefix;353return NoFailure;354}355356bool TestFuncAttrs(std::vector<Attribute> &Attrs);357};358}359360bool ReduceCrashingFunctionAttributes::TestFuncAttrs(361std::vector<Attribute> &Attrs) {362// Clone the program to try hacking it apart...363std::unique_ptr<Module> M = CloneModule(BD.getProgram());364Function *F = M->getFunction(FnName);365366// Build up an AttributeList from the attributes we've been given by the367// reducer.368AttrBuilder AB(M->getContext());369for (auto A : Attrs)370AB.addAttribute(A);371AttributeList NewAttrs;372NewAttrs = NewAttrs.addFnAttributes(BD.getContext(), AB);373374// Set this new list of attributes on the function.375F->setAttributes(NewAttrs);376377// If the attribute list includes "optnone" we need to make sure it also378// includes "noinline" otherwise we will get a verifier failure.379if (F->hasFnAttribute(Attribute::OptimizeNone))380F->addFnAttr(Attribute::NoInline);381382// If modifying the attribute list leads to invalid IR, revert the change383if (!isValidModule(M, /*ExitOnFailure=*/false))384return false;385386// Try running on the hacked up program...387if (TestFn(BD, M.get())) {388BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...389390// Pass along the set of attributes that caused the crash.391Attrs.clear();392for (Attribute A : NewAttrs.getFnAttrs()) {393Attrs.push_back(A);394}395return true;396}397return false;398}399400namespace {401/// Simplify the CFG without completely destroying it.402/// This is not well defined, but basically comes down to "try to eliminate403/// unreachable blocks and constant fold terminators without deciding that404/// certain undefined behavior cuts off the program at the legs".405void simpleSimplifyCfg(Function &F, SmallVectorImpl<BasicBlock *> &BBs) {406if (F.empty())407return;408409for (auto *BB : BBs) {410ConstantFoldTerminator(BB);411MergeBlockIntoPredecessor(BB);412}413414// Remove unreachable blocks415// removeUnreachableBlocks can't be used here, it will turn various416// undefined behavior into unreachables, but bugpoint was the thing that417// generated the undefined behavior, and we don't want it to kill the entire418// program.419SmallPtrSet<BasicBlock *, 16> Visited;420for (auto *BB : depth_first(&F.getEntryBlock()))421Visited.insert(BB);422423SmallVector<BasicBlock *, 16> Unreachable;424for (auto &BB : F)425if (!Visited.count(&BB))426Unreachable.push_back(&BB);427428// The dead BB's may be in a dead cycle or otherwise have references to each429// other. Because of this, we have to drop all references first, then delete430// them all at once.431for (auto *BB : Unreachable) {432for (BasicBlock *Successor : successors(&*BB))433if (Visited.count(Successor))434Successor->removePredecessor(&*BB);435BB->dropAllReferences();436}437for (auto *BB : Unreachable)438BB->eraseFromParent();439}440/// ReduceCrashingBlocks reducer - This works by setting the terminators of441/// all terminators except the specified basic blocks to a 'ret' instruction,442/// then running the simplifycfg pass. This has the effect of chopping up443/// the CFG really fast which can reduce large functions quickly.444///445class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {446BugDriver &BD;447BugTester TestFn;448449public:450ReduceCrashingBlocks(BugDriver &BD, BugTester testFn)451: BD(BD), TestFn(testFn) {}452453Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,454std::vector<const BasicBlock *> &Kept) override {455if (!Kept.empty() && TestBlocks(Kept))456return KeepSuffix;457if (!Prefix.empty() && TestBlocks(Prefix))458return KeepPrefix;459return NoFailure;460}461462bool TestBlocks(std::vector<const BasicBlock *> &Prefix);463};464}465466bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {467// Clone the program to try hacking it apart...468ValueToValueMapTy VMap;469std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);470471// Convert list to set for fast lookup...472SmallPtrSet<BasicBlock *, 8> Blocks;473for (unsigned i = 0, e = BBs.size(); i != e; ++i)474Blocks.insert(cast<BasicBlock>(VMap[BBs[i]]));475476outs() << "Checking for crash with only these blocks:";477unsigned NumPrint = Blocks.size();478if (NumPrint > 10)479NumPrint = 10;480for (unsigned i = 0, e = NumPrint; i != e; ++i)481outs() << " " << BBs[i]->getName();482if (NumPrint < Blocks.size())483outs() << "... <" << Blocks.size() << " total>";484outs() << ": ";485486// Loop over and delete any hack up any blocks that are not listed...487for (Function &F : M->functions()) {488for (BasicBlock &BB : F) {489if (!Blocks.count(&BB) && BB.getTerminator()->getNumSuccessors()) {490// Loop over all of the successors of this block, deleting any PHI nodes491// that might include it.492for (BasicBlock *Succ : successors(&BB))493Succ->removePredecessor(&BB);494495Instruction *BBTerm = BB.getTerminator();496if (BBTerm->isEHPad() || BBTerm->getType()->isTokenTy())497continue;498if (!BBTerm->getType()->isVoidTy())499BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));500501// Replace the old terminator instruction.502BB.back().eraseFromParent();503new UnreachableInst(BB.getContext(), &BB);504}505}506}507508// The CFG Simplifier pass may delete one of the basic blocks we are509// interested in. If it does we need to take the block out of the list. Make510// a "persistent mapping" by turning basic blocks into <function, name> pairs.511// This won't work well if blocks are unnamed, but that is just the risk we512// have to take. FIXME: Can we just name the blocks?513std::vector<std::pair<std::string, std::string>> BlockInfo;514515for (BasicBlock *BB : Blocks)516BlockInfo.emplace_back(std::string(BB->getParent()->getName()),517std::string(BB->getName()));518519SmallVector<BasicBlock *, 16> ToProcess;520for (auto &F : *M) {521for (auto &BB : F)522if (!Blocks.count(&BB))523ToProcess.push_back(&BB);524simpleSimplifyCfg(F, ToProcess);525ToProcess.clear();526}527// Verify we didn't break anything528isValidModule(M);529530// Try running on the hacked up program...531if (TestFn(BD, M.get())) {532BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...533534// Make sure to use basic block pointers that point into the now-current535// module, and that they don't include any deleted blocks.536BBs.clear();537const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();538for (const auto &BI : BlockInfo) {539Function *F = cast<Function>(GST.lookup(BI.first));540Value *V = F->getValueSymbolTable()->lookup(BI.second);541if (V && V->getType() == Type::getLabelTy(V->getContext()))542BBs.push_back(cast<BasicBlock>(V));543}544return true;545}546// It didn't crash, try something else.547return false;548}549550namespace {551/// ReduceCrashingConditionals reducer - This works by changing552/// conditional branches to unconditional ones, then simplifying the CFG553/// This has the effect of chopping up the CFG really fast which can reduce554/// large functions quickly.555///556class ReduceCrashingConditionals : public ListReducer<const BasicBlock *> {557BugDriver &BD;558BugTester TestFn;559bool Direction;560561public:562ReduceCrashingConditionals(BugDriver &bd, BugTester testFn, bool Direction)563: BD(bd), TestFn(testFn), Direction(Direction) {}564565Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,566std::vector<const BasicBlock *> &Kept) override {567if (!Kept.empty() && TestBlocks(Kept))568return KeepSuffix;569if (!Prefix.empty() && TestBlocks(Prefix))570return KeepPrefix;571return NoFailure;572}573574bool TestBlocks(std::vector<const BasicBlock *> &Prefix);575};576}577578bool ReduceCrashingConditionals::TestBlocks(579std::vector<const BasicBlock *> &BBs) {580// Clone the program to try hacking it apart...581ValueToValueMapTy VMap;582std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);583584// Convert list to set for fast lookup...585SmallPtrSet<const BasicBlock *, 8> Blocks;586for (const auto *BB : BBs)587Blocks.insert(cast<BasicBlock>(VMap[BB]));588589outs() << "Checking for crash with changing conditionals to always jump to "590<< (Direction ? "true" : "false") << ":";591unsigned NumPrint = Blocks.size();592if (NumPrint > 10)593NumPrint = 10;594for (unsigned i = 0, e = NumPrint; i != e; ++i)595outs() << " " << BBs[i]->getName();596if (NumPrint < Blocks.size())597outs() << "... <" << Blocks.size() << " total>";598outs() << ": ";599600// Loop over and delete any hack up any blocks that are not listed...601for (auto &F : *M)602for (auto &BB : F)603if (!Blocks.count(&BB)) {604auto *BR = dyn_cast<BranchInst>(BB.getTerminator());605if (!BR || !BR->isConditional())606continue;607if (Direction)608BR->setCondition(ConstantInt::getTrue(BR->getContext()));609else610BR->setCondition(ConstantInt::getFalse(BR->getContext()));611}612613// The following may destroy some blocks, so we save them first614std::vector<std::pair<std::string, std::string>> BlockInfo;615616for (const BasicBlock *BB : Blocks)617BlockInfo.emplace_back(std::string(BB->getParent()->getName()),618std::string(BB->getName()));619620SmallVector<BasicBlock *, 16> ToProcess;621for (auto &F : *M) {622for (auto &BB : F)623if (!Blocks.count(&BB))624ToProcess.push_back(&BB);625simpleSimplifyCfg(F, ToProcess);626ToProcess.clear();627}628// Verify we didn't break anything629isValidModule(M);630631// Try running on the hacked up program...632if (TestFn(BD, M.get())) {633BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...634635// Make sure to use basic block pointers that point into the now-current636// module, and that they don't include any deleted blocks.637BBs.clear();638const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();639for (auto &BI : BlockInfo) {640auto *F = cast<Function>(GST.lookup(BI.first));641Value *V = F->getValueSymbolTable()->lookup(BI.second);642if (V && V->getType() == Type::getLabelTy(V->getContext()))643BBs.push_back(cast<BasicBlock>(V));644}645return true;646}647// It didn't crash, try something else.648return false;649}650651namespace {652/// SimplifyCFG reducer - This works by calling SimplifyCFG on each basic block653/// in the program.654655class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {656BugDriver &BD;657BugTester TestFn;658TargetTransformInfo TTI;659660public:661ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)662: BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}663664Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,665std::vector<const BasicBlock *> &Kept) override {666if (!Kept.empty() && TestBlocks(Kept))667return KeepSuffix;668if (!Prefix.empty() && TestBlocks(Prefix))669return KeepPrefix;670return NoFailure;671}672673bool TestBlocks(std::vector<const BasicBlock *> &Prefix);674};675}676677bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {678// Clone the program to try hacking it apart...679ValueToValueMapTy VMap;680std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);681682// Convert list to set for fast lookup...683SmallPtrSet<const BasicBlock *, 8> Blocks;684for (const auto *BB : BBs)685Blocks.insert(cast<BasicBlock>(VMap[BB]));686687outs() << "Checking for crash with CFG simplifying:";688unsigned NumPrint = Blocks.size();689if (NumPrint > 10)690NumPrint = 10;691for (unsigned i = 0, e = NumPrint; i != e; ++i)692outs() << " " << BBs[i]->getName();693if (NumPrint < Blocks.size())694outs() << "... <" << Blocks.size() << " total>";695outs() << ": ";696697// The following may destroy some blocks, so we save them first698std::vector<std::pair<std::string, std::string>> BlockInfo;699700for (const BasicBlock *BB : Blocks)701BlockInfo.emplace_back(std::string(BB->getParent()->getName()),702std::string(BB->getName()));703704// Loop over and delete any hack up any blocks that are not listed...705for (auto &F : *M)706// Loop over all of the basic blocks and remove them if they are unneeded.707for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {708if (!Blocks.count(&*BBIt)) {709++BBIt;710continue;711}712simplifyCFG(&*BBIt++, TTI);713}714// Verify we didn't break anything715isValidModule(M);716717// Try running on the hacked up program...718if (TestFn(BD, M.get())) {719BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...720721// Make sure to use basic block pointers that point into the now-current722// module, and that they don't include any deleted blocks.723BBs.clear();724const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();725for (auto &BI : BlockInfo) {726auto *F = cast<Function>(GST.lookup(BI.first));727Value *V = F->getValueSymbolTable()->lookup(BI.second);728if (V && V->getType() == Type::getLabelTy(V->getContext()))729BBs.push_back(cast<BasicBlock>(V));730}731return true;732}733// It didn't crash, try something else.734return false;735}736737namespace {738/// ReduceCrashingInstructions reducer - This works by removing the specified739/// non-terminator instructions and replacing them with undef.740///741class ReduceCrashingInstructions : public ListReducer<const Instruction *> {742BugDriver &BD;743BugTester TestFn;744745public:746ReduceCrashingInstructions(BugDriver &bd, BugTester testFn)747: BD(bd), TestFn(testFn) {}748749Expected<TestResult> doTest(std::vector<const Instruction *> &Prefix,750std::vector<const Instruction *> &Kept) override {751if (!Kept.empty() && TestInsts(Kept))752return KeepSuffix;753if (!Prefix.empty() && TestInsts(Prefix))754return KeepPrefix;755return NoFailure;756}757758bool TestInsts(std::vector<const Instruction *> &Prefix);759};760}761762bool ReduceCrashingInstructions::TestInsts(763std::vector<const Instruction *> &Insts) {764// Clone the program to try hacking it apart...765ValueToValueMapTy VMap;766std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);767768// Convert list to set for fast lookup...769SmallPtrSet<Instruction *, 32> Instructions;770for (unsigned i = 0, e = Insts.size(); i != e; ++i) {771assert(!Insts[i]->isTerminator());772Instructions.insert(cast<Instruction>(VMap[Insts[i]]));773}774775outs() << "Checking for crash with only " << Instructions.size();776if (Instructions.size() == 1)777outs() << " instruction: ";778else779outs() << " instructions: ";780781for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI)782for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI)783for (Instruction &Inst : llvm::make_early_inc_range(*FI)) {784if (!Instructions.count(&Inst) && !Inst.isTerminator() &&785!Inst.isEHPad() && !Inst.getType()->isTokenTy() &&786!Inst.isSwiftError()) {787if (!Inst.getType()->isVoidTy())788Inst.replaceAllUsesWith(PoisonValue::get(Inst.getType()));789Inst.eraseFromParent();790}791}792793// Verify that this is still valid.794isValidModule(M, /*ExitOnFailure=*/false);795796// Try running on the hacked up program...797if (TestFn(BD, M.get())) {798BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...799800// Make sure to use instruction pointers that point into the now-current801// module, and that they don't include any deleted blocks.802Insts.clear();803for (Instruction *Inst : Instructions)804Insts.push_back(Inst);805return true;806}807// It didn't crash, try something else.808return false;809}810811namespace {812/// ReduceCrashingMetadata reducer - This works by removing all metadata from813/// the specified instructions.814///815class ReduceCrashingMetadata : public ListReducer<Instruction *> {816BugDriver &BD;817BugTester TestFn;818819public:820ReduceCrashingMetadata(BugDriver &bd, BugTester testFn)821: BD(bd), TestFn(testFn) {}822823Expected<TestResult> doTest(std::vector<Instruction *> &Prefix,824std::vector<Instruction *> &Kept) override {825if (!Kept.empty() && TestInsts(Kept))826return KeepSuffix;827if (!Prefix.empty() && TestInsts(Prefix))828return KeepPrefix;829return NoFailure;830}831832bool TestInsts(std::vector<Instruction *> &Prefix);833};834} // namespace835836bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {837// Clone the program to try hacking it apart...838ValueToValueMapTy VMap;839std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);840841// Convert list to set for fast lookup...842SmallPtrSet<Instruction *, 32> Instructions;843for (Instruction *I : Insts)844Instructions.insert(cast<Instruction>(VMap[I]));845846outs() << "Checking for crash with metadata retained from "847<< Instructions.size();848if (Instructions.size() == 1)849outs() << " instruction: ";850else851outs() << " instructions: ";852853// Try to drop instruction metadata from all instructions, except the ones854// selected in Instructions.855for (Function &F : *M)856for (Instruction &Inst : instructions(F)) {857if (!Instructions.count(&Inst)) {858Inst.dropUnknownNonDebugMetadata();859Inst.setDebugLoc({});860}861}862863// Verify that this is still valid.864isValidModule(M, /*ExitOnFailure=*/false);865866// Try running on the hacked up program...867if (TestFn(BD, M.get())) {868BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...869870// Make sure to use instruction pointers that point into the now-current871// module, and that they don't include any deleted blocks.872Insts.clear();873for (Instruction *I : Instructions)874Insts.push_back(I);875return true;876}877// It didn't crash, try something else.878return false;879}880881namespace {882// Reduce the list of Named Metadata nodes. We keep this as a list of883// names to avoid having to convert back and forth every time.884class ReduceCrashingNamedMD : public ListReducer<std::string> {885BugDriver &BD;886BugTester TestFn;887888public:889ReduceCrashingNamedMD(BugDriver &bd, BugTester testFn)890: BD(bd), TestFn(testFn) {}891892Expected<TestResult> doTest(std::vector<std::string> &Prefix,893std::vector<std::string> &Kept) override {894if (!Kept.empty() && TestNamedMDs(Kept))895return KeepSuffix;896if (!Prefix.empty() && TestNamedMDs(Prefix))897return KeepPrefix;898return NoFailure;899}900901bool TestNamedMDs(std::vector<std::string> &NamedMDs);902};903}904905bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {906907ValueToValueMapTy VMap;908std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);909910outs() << "Checking for crash with only these named metadata nodes:";911unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);912for (unsigned i = 0, e = NumPrint; i != e; ++i)913outs() << " " << NamedMDs[i];914if (NumPrint < NamedMDs.size())915outs() << "... <" << NamedMDs.size() << " total>";916outs() << ": ";917918// Make a StringMap for faster lookup919StringSet<> Names;920for (const std::string &Name : NamedMDs)921Names.insert(Name);922923// First collect all the metadata to delete in a vector, then924// delete them all at once to avoid invalidating the iterator925std::vector<NamedMDNode *> ToDelete;926ToDelete.reserve(M->named_metadata_size() - Names.size());927for (auto &NamedMD : M->named_metadata())928// Always keep a nonempty llvm.dbg.cu because the Verifier would complain.929if (!Names.count(NamedMD.getName()) &&930(!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0)))931ToDelete.push_back(&NamedMD);932933for (auto *NamedMD : ToDelete)934NamedMD->eraseFromParent();935936// Verify that this is still valid.937isValidModule(M, /*ExitOnFailure=*/false);938939// Try running on the hacked up program...940if (TestFn(BD, M.get())) {941BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...942return true;943}944return false;945}946947namespace {948// Reduce the list of operands to named metadata nodes949class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {950BugDriver &BD;951BugTester TestFn;952953public:954ReduceCrashingNamedMDOps(BugDriver &bd, BugTester testFn)955: BD(bd), TestFn(testFn) {}956957Expected<TestResult> doTest(std::vector<const MDNode *> &Prefix,958std::vector<const MDNode *> &Kept) override {959if (!Kept.empty() && TestNamedMDOps(Kept))960return KeepSuffix;961if (!Prefix.empty() && TestNamedMDOps(Prefix))962return KeepPrefix;963return NoFailure;964}965966bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps);967};968}969970bool ReduceCrashingNamedMDOps::TestNamedMDOps(971std::vector<const MDNode *> &NamedMDOps) {972// Convert list to set for fast lookup...973SmallPtrSet<const MDNode *, 32> OldMDNodeOps;974for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) {975OldMDNodeOps.insert(NamedMDOps[i]);976}977978outs() << "Checking for crash with only " << OldMDNodeOps.size();979if (OldMDNodeOps.size() == 1)980outs() << " named metadata operand: ";981else982outs() << " named metadata operands: ";983984ValueToValueMapTy VMap;985std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);986987// This is a little wasteful. In the future it might be good if we could have988// these dropped during cloning.989for (auto &NamedMD : BD.getProgram().named_metadata()) {990// Drop the old one and create a new one991M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));992NamedMDNode *NewNamedMDNode =993M->getOrInsertNamedMetadata(NamedMD.getName());994for (MDNode *op : NamedMD.operands())995if (OldMDNodeOps.count(op))996NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap)));997}998999// Verify that this is still valid.1000isValidModule(M, /*ExitOnFailure=*/false);10011002// Try running on the hacked up program...1003if (TestFn(BD, M.get())) {1004// Make sure to use instruction pointers that point into the now-current1005// module, and that they don't include any deleted blocks.1006NamedMDOps.clear();1007for (const MDNode *Node : OldMDNodeOps)1008NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));10091010BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...1011return true;1012}1013// It didn't crash, try something else.1014return false;1015}10161017/// Attempt to eliminate as many global initializers as possible.1018static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {1019Module &OrigM = BD.getProgram();1020if (OrigM.global_empty())1021return Error::success();10221023// Now try to reduce the number of global variable initializers in the1024// module to something small.1025std::unique_ptr<Module> M = CloneModule(OrigM);1026bool DeletedInit = false;10271028for (GlobalVariable &GV : M->globals()) {1029if (GV.hasInitializer()) {1030DeleteGlobalInitializer(&GV);1031GV.setLinkage(GlobalValue::ExternalLinkage);1032GV.setComdat(nullptr);1033DeletedInit = true;1034}1035}10361037if (!DeletedInit)1038return Error::success();10391040// See if the program still causes a crash...1041outs() << "\nChecking to see if we can delete global inits: ";10421043if (TestFn(BD, M.get())) { // Still crashes?1044BD.setNewProgram(std::move(M));1045outs() << "\n*** Able to remove all global initializers!\n";1046return Error::success();1047}10481049// No longer crashes.1050outs() << " - Removing all global inits hides problem!\n";10511052std::vector<GlobalVariable *> GVs;1053for (GlobalVariable &GV : OrigM.globals())1054if (GV.hasInitializer())1055GVs.push_back(&GV);10561057if (GVs.size() > 1 && !BugpointIsInterrupted) {1058outs() << "\n*** Attempting to reduce the number of global initializers "1059<< "in the testcase\n";10601061unsigned OldSize = GVs.size();1062Expected<bool> Result =1063ReduceCrashingGlobalInitializers(BD, TestFn).reduceList(GVs);1064if (Error E = Result.takeError())1065return E;10661067if (GVs.size() < OldSize)1068BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");1069}1070return Error::success();1071}10721073static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {1074// Attempt to delete instructions using bisection. This should help out nasty1075// cases with large basic blocks where the problem is at one end.1076if (!BugpointIsInterrupted) {1077std::vector<const Instruction *> Insts;1078for (const Function &F : BD.getProgram())1079for (const BasicBlock &BB : F)1080for (const Instruction &I : BB)1081if (!I.isTerminator())1082Insts.push_back(&I);10831084Expected<bool> Result =1085ReduceCrashingInstructions(BD, TestFn).reduceList(Insts);1086if (Error E = Result.takeError())1087return E;1088}10891090unsigned Simplification = 2;1091do {1092if (BugpointIsInterrupted)1093// TODO: Should we distinguish this with an "interrupted error"?1094return Error::success();1095--Simplification;1096outs() << "\n*** Attempting to reduce testcase by deleting instruc"1097<< "tions: Simplification Level #" << Simplification << '\n';10981099// Now that we have deleted the functions that are unnecessary for the1100// program, try to remove instructions that are not necessary to cause the1101// crash. To do this, we loop through all of the instructions in the1102// remaining functions, deleting them (replacing any values produced with1103// nulls), and then running ADCE and SimplifyCFG. If the transformed input1104// still triggers failure, keep deleting until we cannot trigger failure1105// anymore.1106//1107unsigned InstructionsToSkipBeforeDeleting = 0;1108TryAgain:11091110// Loop over all of the (non-terminator) instructions remaining in the1111// function, attempting to delete them.1112unsigned CurInstructionNum = 0;1113for (Module::const_iterator FI = BD.getProgram().begin(),1114E = BD.getProgram().end();1115FI != E; ++FI)1116if (!FI->isDeclaration())1117for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;1118++BI)1119for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end();1120I != E; ++I, ++CurInstructionNum) {1121if (InstructionsToSkipBeforeDeleting) {1122--InstructionsToSkipBeforeDeleting;1123} else {1124if (BugpointIsInterrupted)1125// TODO: Should this be some kind of interrupted error?1126return Error::success();11271128if (I->isEHPad() || I->getType()->isTokenTy() ||1129I->isSwiftError())1130continue;11311132outs() << "Checking instruction: " << *I;1133std::unique_ptr<Module> M =1134BD.deleteInstructionFromProgram(&*I, Simplification);11351136// Find out if the pass still crashes on this pass...1137if (TestFn(BD, M.get())) {1138// Yup, it does, we delete the old module, and continue trying1139// to reduce the testcase...1140BD.setNewProgram(std::move(M));1141InstructionsToSkipBeforeDeleting = CurInstructionNum;1142goto TryAgain; // I wish I had a multi-level break here!1143}1144}1145}11461147if (InstructionsToSkipBeforeDeleting) {1148InstructionsToSkipBeforeDeleting = 0;1149goto TryAgain;1150}11511152} while (Simplification);11531154// Attempt to drop metadata from instructions that does not contribute to the1155// crash.1156if (!BugpointIsInterrupted) {1157std::vector<Instruction *> Insts;1158for (Function &F : BD.getProgram())1159for (Instruction &I : instructions(F))1160Insts.push_back(&I);11611162Expected<bool> Result =1163ReduceCrashingMetadata(BD, TestFn).reduceList(Insts);1164if (Error E = Result.takeError())1165return E;1166}11671168BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");1169return Error::success();1170}11711172/// DebugACrash - Given a predicate that determines whether a component crashes1173/// on a program, try to destructively reduce the program while still keeping1174/// the predicate true.1175static Error DebugACrash(BugDriver &BD, BugTester TestFn) {1176// See if we can get away with nuking some of the global variable initializers1177// in the program...1178if (!NoGlobalRM)1179if (Error E = ReduceGlobalInitializers(BD, TestFn))1180return E;11811182// Now try to reduce the number of functions in the module to something small.1183std::vector<Function *> Functions;1184for (Function &F : BD.getProgram())1185if (!F.isDeclaration())1186Functions.push_back(&F);11871188if (Functions.size() > 1 && !BugpointIsInterrupted) {1189outs() << "\n*** Attempting to reduce the number of functions "1190"in the testcase\n";11911192unsigned OldSize = Functions.size();1193Expected<bool> Result =1194ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);1195if (Error E = Result.takeError())1196return E;11971198if (Functions.size() < OldSize)1199BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");1200}12011202if (!NoAttributeRM) {1203// For each remaining function, try to reduce that function's attributes.1204std::vector<std::string> FunctionNames;1205for (Function &F : BD.getProgram())1206FunctionNames.push_back(std::string(F.getName()));12071208if (!FunctionNames.empty() && !BugpointIsInterrupted) {1209outs() << "\n*** Attempting to reduce the number of function attributes"1210" in the testcase\n";12111212unsigned OldSize = 0;1213unsigned NewSize = 0;1214for (std::string &Name : FunctionNames) {1215Function *Fn = BD.getProgram().getFunction(Name);1216assert(Fn && "Could not find function?");12171218std::vector<Attribute> Attrs;1219for (Attribute A : Fn->getAttributes().getFnAttrs())1220Attrs.push_back(A);12211222OldSize += Attrs.size();1223Expected<bool> Result =1224ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);1225if (Error E = Result.takeError())1226return E;12271228NewSize += Attrs.size();1229}12301231if (OldSize < NewSize)1232BD.EmitProgressBitcode(BD.getProgram(), "reduced-function-attributes");1233}1234}12351236// Attempt to change conditional branches into unconditional branches to1237// eliminate blocks.1238if (!DisableSimplifyCFG && !BugpointIsInterrupted) {1239std::vector<const BasicBlock *> Blocks;1240for (Function &F : BD.getProgram())1241for (BasicBlock &BB : F)1242Blocks.push_back(&BB);1243unsigned OldSize = Blocks.size();1244Expected<bool> Result =1245ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks);1246if (Error E = Result.takeError())1247return E;1248Result = ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks);1249if (Error E = Result.takeError())1250return E;1251if (Blocks.size() < OldSize)1252BD.EmitProgressBitcode(BD.getProgram(), "reduced-conditionals");1253}12541255// Attempt to delete entire basic blocks at a time to speed up1256// convergence... this actually works by setting the terminator of the blocks1257// to a return instruction then running simplifycfg, which can potentially1258// shrinks the code dramatically quickly1259//1260if (!DisableSimplifyCFG && !BugpointIsInterrupted) {1261std::vector<const BasicBlock *> Blocks;1262for (Function &F : BD.getProgram())1263for (BasicBlock &BB : F)1264Blocks.push_back(&BB);1265unsigned OldSize = Blocks.size();1266Expected<bool> Result = ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks);1267if (Error E = Result.takeError())1268return E;1269if (Blocks.size() < OldSize)1270BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks");1271}12721273if (!DisableSimplifyCFG && !BugpointIsInterrupted) {1274std::vector<const BasicBlock *> Blocks;1275for (Function &F : BD.getProgram())1276for (BasicBlock &BB : F)1277Blocks.push_back(&BB);1278unsigned OldSize = Blocks.size();1279Expected<bool> Result = ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks);1280if (Error E = Result.takeError())1281return E;1282if (Blocks.size() < OldSize)1283BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplifycfg");1284}12851286// Attempt to delete instructions using bisection. This should help out nasty1287// cases with large basic blocks where the problem is at one end.1288if (!BugpointIsInterrupted)1289if (Error E = ReduceInsts(BD, TestFn))1290return E;12911292// Attempt to strip debug info metadata.1293auto stripMetadata = [&](std::function<bool(Module &)> strip) {1294std::unique_ptr<Module> M = CloneModule(BD.getProgram());1295strip(*M);1296if (TestFn(BD, M.get()))1297BD.setNewProgram(std::move(M));1298};1299if (!NoStripDebugInfo && !BugpointIsInterrupted) {1300outs() << "\n*** Attempting to strip the debug info: ";1301stripMetadata(StripDebugInfo);1302}1303if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {1304outs() << "\n*** Attempting to strip the debug type info: ";1305stripMetadata(stripNonLineTableDebugInfo);1306}13071308if (!NoNamedMDRM) {1309if (!BugpointIsInterrupted) {1310// Try to reduce the amount of global metadata (particularly debug info),1311// by dropping global named metadata that anchors them1312outs() << "\n*** Attempting to remove named metadata: ";1313std::vector<std::string> NamedMDNames;1314for (auto &NamedMD : BD.getProgram().named_metadata())1315NamedMDNames.push_back(NamedMD.getName().str());1316Expected<bool> Result =1317ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);1318if (Error E = Result.takeError())1319return E;1320}13211322if (!BugpointIsInterrupted) {1323// Now that we quickly dropped all the named metadata that doesn't1324// contribute to the crash, bisect the operands of the remaining ones1325std::vector<const MDNode *> NamedMDOps;1326for (auto &NamedMD : BD.getProgram().named_metadata())1327for (auto *op : NamedMD.operands())1328NamedMDOps.push_back(op);1329Expected<bool> Result =1330ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps);1331if (Error E = Result.takeError())1332return E;1333}1334BD.EmitProgressBitcode(BD.getProgram(), "reduced-named-md");1335}13361337// Try to clean up the testcase by running funcresolve and globaldce...1338if (!BugpointIsInterrupted) {1339outs() << "\n*** Attempting to perform final cleanups: ";1340std::unique_ptr<Module> M = CloneModule(BD.getProgram());1341M = BD.performFinalCleanups(std::move(M), true);13421343// Find out if the pass still crashes on the cleaned up program...1344if (M && TestFn(BD, M.get()))1345BD.setNewProgram(1346std::move(M)); // Yup, it does, keep the reduced version...1347}13481349BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");13501351return Error::success();1352}13531354static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {1355return BD.runPasses(*M, BD.getPassesToRun());1356}13571358/// debugOptimizerCrash - This method is called when some pass crashes on input.1359/// It attempts to prune down the testcase to something reasonable, and figure1360/// out exactly which pass is crashing.1361///1362Error BugDriver::debugOptimizerCrash(const std::string &ID) {1363outs() << "\n*** Debugging optimizer crash!\n";13641365// Reduce the list of passes which causes the optimizer to crash...1366if (!BugpointIsInterrupted && !DontReducePassList) {1367Expected<bool> Result = ReducePassList(*this).reduceList(PassesToRun);1368if (Error E = Result.takeError())1369return E;1370}13711372outs() << "\n*** Found crashing pass"1373<< (PassesToRun.size() == 1 ? ": " : "es: ")1374<< getPassesString(PassesToRun) << '\n';13751376EmitProgressBitcode(*Program, ID);13771378auto Res = DebugACrash(*this, TestForOptimizerCrash);1379if (Res || DontReducePassList)1380return Res;1381// Try to reduce the pass list again. This covers additional cases1382// we failed to reduce earlier, because of more complex pass dependencies1383// triggering the crash.1384auto SecondRes = ReducePassList(*this).reduceList(PassesToRun);1385if (Error E = SecondRes.takeError())1386return E;1387outs() << "\n*** Found crashing pass"1388<< (PassesToRun.size() == 1 ? ": " : "es: ")1389<< getPassesString(PassesToRun) << '\n';13901391EmitProgressBitcode(getProgram(), "reduced-simplified");1392return Res;1393}13941395static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {1396if (Error E = BD.compileProgram(*M)) {1397if (VerboseErrors)1398errs() << toString(std::move(E)) << "\n";1399else {1400consumeError(std::move(E));1401errs() << "<crash>\n";1402}1403return true; // Tool is still crashing.1404}1405errs() << '\n';1406return false;1407}14081409/// debugCodeGeneratorCrash - This method is called when the code generator1410/// crashes on an input. It attempts to reduce the input as much as possible1411/// while still causing the code generator to crash.1412Error BugDriver::debugCodeGeneratorCrash() {1413errs() << "*** Debugging code generator crash!\n";14141415return DebugACrash(*this, TestForCodeGenCrash);1416}141714181419