//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the bugpoint internals that narrow down compilation crashes
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "ListReducer.h"
#include "ToolRunner.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include <set>
using namespace llvm;

namespace {
cl::opt<bool> KeepMain("keep-main",
                       cl::desc("Force function reduction to keep main"),
                       cl::init(false));
cl::opt<bool> NoGlobalRM("disable-global-remove",
                         cl::desc("Do not remove global variables"),
                         cl::init(false));

cl::opt<bool> NoAttributeRM("disable-attribute-remove",
                         cl::desc("Do not remove function attributes"),
                         cl::init(false));

cl::opt<bool> ReplaceFuncsWithNull(
    "replace-funcs-with-null",
    cl::desc("When stubbing functions, replace all uses will null"),
    cl::init(false));
cl::opt<bool> DontReducePassList("disable-pass-list-reduction",
                                 cl::desc("Skip pass list reduction steps"),
                                 cl::init(false));

cl::opt<bool> NoNamedMDRM("disable-namedmd-remove",
                          cl::desc("Do not remove global named metadata"),
                          cl::init(false));
cl::opt<bool> NoStripDebugInfo("disable-strip-debuginfo",
                               cl::desc("Do not strip debug info metadata"),
                               cl::init(false));
cl::opt<bool> NoStripDebugTypeInfo("disable-strip-debug-types",
                               cl::desc("Do not strip debug type info metadata"),
                               cl::init(false));
cl::opt<bool> VerboseErrors("verbose-errors",
                            cl::desc("Print the output of crashing program"),
                            cl::init(false));
}

static bool isValidModule(std::unique_ptr<Module> &M,
                          bool ExitOnFailure = true) {
  if (!llvm::verifyModule(*M, &llvm::errs()))
    return true;

  if (ExitOnFailure) {
    llvm::errs() << "verify failed!\n";
    exit(1);
  }
  return false;
}

namespace llvm {
class ReducePassList : public ListReducer<std::string> {
  BugDriver &BD;

public:
  ReducePassList(BugDriver &bd) : BD(bd) {}

  // Return true iff running the "removed" passes succeeds, and running the
  // "Kept" passes fail when run on the output of the "removed" passes.  If we
  // return true, we update the current module of bugpoint.
  Expected<TestResult> doTest(std::vector<std::string> &Removed,
                              std::vector<std::string> &Kept) override;
};
}

Expected<ReducePassList::TestResult>
ReducePassList::doTest(std::vector<std::string> &Prefix,
                       std::vector<std::string> &Suffix) {
  std::string PrefixOutput;
  std::unique_ptr<Module> OrigProgram;
  if (!Prefix.empty()) {
    outs() << "Checking to see if these passes crash: "
           << getPassesString(Prefix) << ": ";
    if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))
      return KeepPrefix;

    OrigProgram = std::move(BD.Program);

    BD.Program = parseInputFile(PrefixOutput, BD.getContext());
    if (BD.Program == nullptr) {
      errs() << BD.getToolName() << ": Error reading bitcode file '"
             << PrefixOutput << "'!\n";
      exit(1);
    }
    sys::fs::remove(PrefixOutput);
  }

  outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)
         << ": ";

  if (BD.runPasses(BD.getProgram(), Suffix))
    return KeepSuffix; // The suffix crashes alone...

  // Nothing failed, restore state...
  if (OrigProgram)
    BD.Program = std::move(OrigProgram);
  return NoFailure;
}

using BugTester = bool (*)(const BugDriver &, Module *);

namespace {
/// ReduceCrashingGlobalInitializers - This works by removing global variable
/// initializers and seeing if the program still crashes. If it does, then we
/// keep that program and try again.
class ReduceCrashingGlobalInitializers : public ListReducer<GlobalVariable *> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingGlobalInitializers(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<GlobalVariable *> &Prefix,
                              std::vector<GlobalVariable *> &Kept) override {
    if (!Kept.empty() && TestGlobalVariables(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestGlobalVariables(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestGlobalVariables(std::vector<GlobalVariable *> &GVs);
};
}

bool ReduceCrashingGlobalInitializers::TestGlobalVariables(
    std::vector<GlobalVariable *> &GVs) {
  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  std::set<GlobalVariable *> GVSet;

  for (unsigned i = 0, e = GVs.size(); i != e; ++i) {
    GlobalVariable *CMGV = cast<GlobalVariable>(VMap[GVs[i]]);
    assert(CMGV && "Global Variable not in module?!");
    GVSet.insert(CMGV);
  }

  outs() << "Checking for crash with only these global variables: ";
  PrintGlobalVariableList(GVs);
  outs() << ": ";

  // Loop over and delete any global variables which we aren't supposed to be
  // playing with...
  for (GlobalVariable &I : M->globals())
    if (I.hasInitializer() && !GVSet.count(&I)) {
      DeleteGlobalInitializer(&I);
      I.setLinkage(GlobalValue::ExternalLinkage);
      I.setComdat(nullptr);
    }

  // Try running the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use global variable pointers that point into the now-current
    // module.
    GVs.assign(GVSet.begin(), GVSet.end());
    return true;
  }

  return false;
}

namespace {
/// ReduceCrashingFunctions reducer - This works by removing functions and
/// seeing if the program still crashes. If it does, then keep the newer,
/// smaller program.
///
class ReduceCrashingFunctions : public ListReducer<Function *> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingFunctions(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<Function *> &Prefix,
                              std::vector<Function *> &Kept) override {
    if (!Kept.empty() && TestFuncs(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestFuncs(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestFuncs(std::vector<Function *> &Prefix);
};
}

static void RemoveFunctionReferences(Module *M, const char *Name) {
  auto *UsedVar = M->getGlobalVariable(Name, true);
  if (!UsedVar || !UsedVar->hasInitializer())
    return;
  if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) {
    assert(UsedVar->use_empty());
    UsedVar->eraseFromParent();
    return;
  }
  auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer());
  std::vector<Constant *> Used;
  for (Value *V : OldUsedVal->operand_values()) {
    Constant *Op = cast<Constant>(V->stripPointerCasts());
    if (!Op->isNullValue()) {
      Used.push_back(cast<Constant>(V));
    }
  }
  auto *NewValElemTy = OldUsedVal->getType()->getElementType();
  auto *NewValTy = ArrayType::get(NewValElemTy, Used.size());
  auto *NewUsedVal = ConstantArray::get(NewValTy, Used);
  UsedVar->mutateType(PointerType::getUnqual(M->getContext()));
  UsedVar->setInitializer(NewUsedVal);
}

bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
  // If main isn't present, claim there is no problem.
  if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))
    return false;

  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  std::set<Function *> Functions;
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
    Function *CMF = cast<Function>(VMap[Funcs[i]]);
    assert(CMF && "Function not in module?!");
    assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty");
    assert(CMF->getName() == Funcs[i]->getName() && "wrong name");
    Functions.insert(CMF);
  }

  outs() << "Checking for crash with only these functions: ";
  PrintFunctionList(Funcs);
  outs() << ": ";
  if (!ReplaceFuncsWithNull) {
    // Loop over and delete any functions which we aren't supposed to be playing
    // with...
    for (Function &I : *M)
      if (!I.isDeclaration() && !Functions.count(&I))
        DeleteFunctionBody(&I);
  } else {
    std::vector<GlobalValue *> ToRemove;
    // First, remove aliases to functions we're about to purge.
    for (GlobalAlias &Alias : M->aliases()) {
      GlobalObject *Root = Alias.getAliaseeObject();
      auto *F = dyn_cast<Function>(Root);
      if (F) {
        if (Functions.count(F))
          // We're keeping this function.
          continue;
      } else if (Root->isNullValue()) {
        // This referenced a globalalias that we've already replaced,
        // so we still need to replace this alias.
      } else {
        // Not a function, therefore not something we mess with.
        continue;
      }

      PointerType *Ty = cast<PointerType>(Alias.getType());
      Constant *Replacement = ConstantPointerNull::get(Ty);
      Alias.replaceAllUsesWith(Replacement);
      ToRemove.push_back(&Alias);
    }

    for (Function &I : *M) {
      if (!I.isDeclaration() && !Functions.count(&I)) {
        PointerType *Ty = cast<PointerType>(I.getType());
        Constant *Replacement = ConstantPointerNull::get(Ty);
        I.replaceAllUsesWith(Replacement);
        ToRemove.push_back(&I);
      }
    }

    for (auto *F : ToRemove) {
      F->eraseFromParent();
    }

    // Finally, remove any null members from any global intrinsic.
    RemoveFunctionReferences(M.get(), "llvm.used");
    RemoveFunctionReferences(M.get(), "llvm.compiler.used");
  }
  // Try running the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use function pointers that point into the now-current
    // module.
    Funcs.assign(Functions.begin(), Functions.end());
    return true;
  }
  return false;
}

namespace {
/// ReduceCrashingFunctionAttributes reducer - This works by removing
/// attributes on a particular function and seeing if the program still crashes.
/// If it does, then keep the newer, smaller program.
///
class ReduceCrashingFunctionAttributes : public ListReducer<Attribute> {
  BugDriver &BD;
  std::string FnName;
  BugTester TestFn;

public:
  ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,
                                   BugTester testFn)
      : BD(bd), FnName(FnName), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<Attribute> &Prefix,
                              std::vector<Attribute> &Kept) override {
    if (!Kept.empty() && TestFuncAttrs(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestFuncAttrs(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestFuncAttrs(std::vector<Attribute> &Attrs);
};
}

bool ReduceCrashingFunctionAttributes::TestFuncAttrs(
    std::vector<Attribute> &Attrs) {
  // Clone the program to try hacking it apart...
  std::unique_ptr<Module> M = CloneModule(BD.getProgram());
  Function *F = M->getFunction(FnName);

  // Build up an AttributeList from the attributes we've been given by the
  // reducer.
  AttrBuilder AB(M->getContext());
  for (auto A : Attrs)
    AB.addAttribute(A);
  AttributeList NewAttrs;
  NewAttrs = NewAttrs.addFnAttributes(BD.getContext(), AB);

  // Set this new list of attributes on the function.
  F->setAttributes(NewAttrs);

  // If the attribute list includes "optnone" we need to make sure it also
  // includes "noinline" otherwise we will get a verifier failure.
  if (F->hasFnAttribute(Attribute::OptimizeNone))
    F->addFnAttr(Attribute::NoInline);

  // If modifying the attribute list leads to invalid IR, revert the change
  if (!isValidModule(M, /*ExitOnFailure=*/false))
    return false;

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Pass along the set of attributes that caused the crash.
    Attrs.clear();
    for (Attribute A : NewAttrs.getFnAttrs()) {
      Attrs.push_back(A);
    }
    return true;
  }
  return false;
}

namespace {
/// Simplify the CFG without completely destroying it.
/// This is not well defined, but basically comes down to "try to eliminate
/// unreachable blocks and constant fold terminators without deciding that
/// certain undefined behavior cuts off the program at the legs".
void simpleSimplifyCfg(Function &F, SmallVectorImpl<BasicBlock *> &BBs) {
  if (F.empty())
    return;

  for (auto *BB : BBs) {
    ConstantFoldTerminator(BB);
    MergeBlockIntoPredecessor(BB);
  }

  // Remove unreachable blocks
  // removeUnreachableBlocks can't be used here, it will turn various
  // undefined behavior into unreachables, but bugpoint was the thing that
  // generated the undefined behavior, and we don't want it to kill the entire
  // program.
  SmallPtrSet<BasicBlock *, 16> Visited;
  for (auto *BB : depth_first(&F.getEntryBlock()))
    Visited.insert(BB);

  SmallVector<BasicBlock *, 16> Unreachable;
  for (auto &BB : F)
    if (!Visited.count(&BB))
      Unreachable.push_back(&BB);

  // The dead BB's may be in a dead cycle or otherwise have references to each
  // other.  Because of this, we have to drop all references first, then delete
  // them all at once.
  for (auto *BB : Unreachable) {
    for (BasicBlock *Successor : successors(&*BB))
      if (Visited.count(Successor))
        Successor->removePredecessor(&*BB);
    BB->dropAllReferences();
  }
  for (auto *BB : Unreachable)
    BB->eraseFromParent();
}
/// ReduceCrashingBlocks reducer - This works by setting the terminators of
/// all terminators except the specified basic blocks to a 'ret' instruction,
/// then running the simplifycfg pass.  This has the effect of chopping up
/// the CFG really fast which can reduce large functions quickly.
///
class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingBlocks(BugDriver &BD, BugTester testFn)
      : BD(BD), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
                              std::vector<const BasicBlock *> &Kept) override {
    if (!Kept.empty() && TestBlocks(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestBlocks(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
};
}

bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  SmallPtrSet<BasicBlock *, 8> Blocks;
  for (unsigned i = 0, e = BBs.size(); i != e; ++i)
    Blocks.insert(cast<BasicBlock>(VMap[BBs[i]]));

  outs() << "Checking for crash with only these blocks:";
  unsigned NumPrint = Blocks.size();
  if (NumPrint > 10)
    NumPrint = 10;
  for (unsigned i = 0, e = NumPrint; i != e; ++i)
    outs() << " " << BBs[i]->getName();
  if (NumPrint < Blocks.size())
    outs() << "... <" << Blocks.size() << " total>";
  outs() << ": ";

  // Loop over and delete any hack up any blocks that are not listed...
  for (Function &F : M->functions()) {
    for (BasicBlock &BB : F) {
      if (!Blocks.count(&BB) && BB.getTerminator()->getNumSuccessors()) {
        // Loop over all of the successors of this block, deleting any PHI nodes
        // that might include it.
        for (BasicBlock *Succ : successors(&BB))
          Succ->removePredecessor(&BB);

        Instruction *BBTerm = BB.getTerminator();
        if (BBTerm->isEHPad() || BBTerm->getType()->isTokenTy())
          continue;
        if (!BBTerm->getType()->isVoidTy())
          BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));

        // Replace the old terminator instruction.
        BB.back().eraseFromParent();
        new UnreachableInst(BB.getContext(), &BB);
      }
    }
  }

  // The CFG Simplifier pass may delete one of the basic blocks we are
  // interested in.  If it does we need to take the block out of the list.  Make
  // a "persistent mapping" by turning basic blocks into <function, name> pairs.
  // This won't work well if blocks are unnamed, but that is just the risk we
  // have to take. FIXME: Can we just name the blocks?
  std::vector<std::pair<std::string, std::string>> BlockInfo;

  for (BasicBlock *BB : Blocks)
    BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
                           std::string(BB->getName()));

  SmallVector<BasicBlock *, 16> ToProcess;
  for (auto &F : *M) {
    for (auto &BB : F)
      if (!Blocks.count(&BB))
        ToProcess.push_back(&BB);
    simpleSimplifyCfg(F, ToProcess);
    ToProcess.clear();
  }
  // Verify we didn't break anything
  isValidModule(M);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use basic block pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    BBs.clear();
    const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
    for (const auto &BI : BlockInfo) {
      Function *F = cast<Function>(GST.lookup(BI.first));
      Value *V = F->getValueSymbolTable()->lookup(BI.second);
      if (V && V->getType() == Type::getLabelTy(V->getContext()))
        BBs.push_back(cast<BasicBlock>(V));
    }
    return true;
  }
  // It didn't crash, try something else.
  return false;
}

namespace {
/// ReduceCrashingConditionals reducer - This works by changing
/// conditional branches to unconditional ones, then simplifying the CFG
/// This has the effect of chopping up the CFG really fast which can reduce
/// large functions quickly.
///
class ReduceCrashingConditionals : public ListReducer<const BasicBlock *> {
  BugDriver &BD;
  BugTester TestFn;
  bool Direction;

public:
  ReduceCrashingConditionals(BugDriver &bd, BugTester testFn, bool Direction)
      : BD(bd), TestFn(testFn), Direction(Direction) {}

  Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
                              std::vector<const BasicBlock *> &Kept) override {
    if (!Kept.empty() && TestBlocks(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestBlocks(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
};
}

bool ReduceCrashingConditionals::TestBlocks(
    std::vector<const BasicBlock *> &BBs) {
  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  SmallPtrSet<const BasicBlock *, 8> Blocks;
  for (const auto *BB : BBs)
    Blocks.insert(cast<BasicBlock>(VMap[BB]));

  outs() << "Checking for crash with changing conditionals to always jump to "
         << (Direction ? "true" : "false") << ":";
  unsigned NumPrint = Blocks.size();
  if (NumPrint > 10)
    NumPrint = 10;
  for (unsigned i = 0, e = NumPrint; i != e; ++i)
    outs() << " " << BBs[i]->getName();
  if (NumPrint < Blocks.size())
    outs() << "... <" << Blocks.size() << " total>";
  outs() << ": ";

  // Loop over and delete any hack up any blocks that are not listed...
  for (auto &F : *M)
    for (auto &BB : F)
      if (!Blocks.count(&BB)) {
        auto *BR = dyn_cast<BranchInst>(BB.getTerminator());
        if (!BR || !BR->isConditional())
          continue;
        if (Direction)
          BR->setCondition(ConstantInt::getTrue(BR->getContext()));
        else
          BR->setCondition(ConstantInt::getFalse(BR->getContext()));
      }

  // The following may destroy some blocks, so we save them first
  std::vector<std::pair<std::string, std::string>> BlockInfo;

  for (const BasicBlock *BB : Blocks)
    BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
                           std::string(BB->getName()));

  SmallVector<BasicBlock *, 16> ToProcess;
  for (auto &F : *M) {
    for (auto &BB : F)
      if (!Blocks.count(&BB))
        ToProcess.push_back(&BB);
    simpleSimplifyCfg(F, ToProcess);
    ToProcess.clear();
  }
  // Verify we didn't break anything
  isValidModule(M);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use basic block pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    BBs.clear();
    const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
    for (auto &BI : BlockInfo) {
      auto *F = cast<Function>(GST.lookup(BI.first));
      Value *V = F->getValueSymbolTable()->lookup(BI.second);
      if (V && V->getType() == Type::getLabelTy(V->getContext()))
        BBs.push_back(cast<BasicBlock>(V));
    }
    return true;
  }
  // It didn't crash, try something else.
  return false;
}

namespace {
/// SimplifyCFG reducer - This works by calling SimplifyCFG on each basic block
/// in the program.

class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {
  BugDriver &BD;
  BugTester TestFn;
  TargetTransformInfo TTI;

public:
  ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}

  Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
                              std::vector<const BasicBlock *> &Kept) override {
    if (!Kept.empty() && TestBlocks(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestBlocks(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
};
}

bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  SmallPtrSet<const BasicBlock *, 8> Blocks;
  for (const auto *BB : BBs)
    Blocks.insert(cast<BasicBlock>(VMap[BB]));

  outs() << "Checking for crash with CFG simplifying:";
  unsigned NumPrint = Blocks.size();
  if (NumPrint > 10)
    NumPrint = 10;
  for (unsigned i = 0, e = NumPrint; i != e; ++i)
    outs() << " " << BBs[i]->getName();
  if (NumPrint < Blocks.size())
    outs() << "... <" << Blocks.size() << " total>";
  outs() << ": ";

  // The following may destroy some blocks, so we save them first
  std::vector<std::pair<std::string, std::string>> BlockInfo;

  for (const BasicBlock *BB : Blocks)
    BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
                           std::string(BB->getName()));

  // Loop over and delete any hack up any blocks that are not listed...
  for (auto &F : *M)
    // Loop over all of the basic blocks and remove them if they are unneeded.
    for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {
      if (!Blocks.count(&*BBIt)) {
        ++BBIt;
        continue;
      }
      simplifyCFG(&*BBIt++, TTI);
    }
  // Verify we didn't break anything
  isValidModule(M);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use basic block pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    BBs.clear();
    const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
    for (auto &BI : BlockInfo) {
      auto *F = cast<Function>(GST.lookup(BI.first));
      Value *V = F->getValueSymbolTable()->lookup(BI.second);
      if (V && V->getType() == Type::getLabelTy(V->getContext()))
        BBs.push_back(cast<BasicBlock>(V));
    }
    return true;
  }
  // It didn't crash, try something else.
  return false;
}

namespace {
/// ReduceCrashingInstructions reducer - This works by removing the specified
/// non-terminator instructions and replacing them with undef.
///
class ReduceCrashingInstructions : public ListReducer<const Instruction *> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingInstructions(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<const Instruction *> &Prefix,
                              std::vector<const Instruction *> &Kept) override {
    if (!Kept.empty() && TestInsts(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestInsts(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestInsts(std::vector<const Instruction *> &Prefix);
};
}

bool ReduceCrashingInstructions::TestInsts(
    std::vector<const Instruction *> &Insts) {
  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  SmallPtrSet<Instruction *, 32> Instructions;
  for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
    assert(!Insts[i]->isTerminator());
    Instructions.insert(cast<Instruction>(VMap[Insts[i]]));
  }

  outs() << "Checking for crash with only " << Instructions.size();
  if (Instructions.size() == 1)
    outs() << " instruction: ";
  else
    outs() << " instructions: ";

  for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI)
    for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI)
      for (Instruction &Inst : llvm::make_early_inc_range(*FI)) {
        if (!Instructions.count(&Inst) && !Inst.isTerminator() &&
            !Inst.isEHPad() && !Inst.getType()->isTokenTy() &&
            !Inst.isSwiftError()) {
          if (!Inst.getType()->isVoidTy())
            Inst.replaceAllUsesWith(PoisonValue::get(Inst.getType()));
          Inst.eraseFromParent();
        }
      }

  // Verify that this is still valid.
  isValidModule(M, /*ExitOnFailure=*/false);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use instruction pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    Insts.clear();
    for (Instruction *Inst : Instructions)
      Insts.push_back(Inst);
    return true;
  }
  // It didn't crash, try something else.
  return false;
}

namespace {
/// ReduceCrashingMetadata reducer - This works by removing all metadata from
/// the specified instructions.
///
class ReduceCrashingMetadata : public ListReducer<Instruction *> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingMetadata(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<Instruction *> &Prefix,
                              std::vector<Instruction *> &Kept) override {
    if (!Kept.empty() && TestInsts(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestInsts(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestInsts(std::vector<Instruction *> &Prefix);
};
} // namespace

bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {
  // Clone the program to try hacking it apart...
  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // Convert list to set for fast lookup...
  SmallPtrSet<Instruction *, 32> Instructions;
  for (Instruction *I : Insts)
    Instructions.insert(cast<Instruction>(VMap[I]));

  outs() << "Checking for crash with metadata retained from "
         << Instructions.size();
  if (Instructions.size() == 1)
    outs() << " instruction: ";
  else
    outs() << " instructions: ";

  // Try to drop instruction metadata from all instructions, except the ones
  // selected in Instructions.
  for (Function &F : *M)
    for (Instruction &Inst : instructions(F)) {
      if (!Instructions.count(&Inst)) {
        Inst.dropUnknownNonDebugMetadata();
        Inst.setDebugLoc({});
      }
    }

  // Verify that this is still valid.
  isValidModule(M, /*ExitOnFailure=*/false);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...

    // Make sure to use instruction pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    Insts.clear();
    for (Instruction *I : Instructions)
      Insts.push_back(I);
    return true;
  }
  // It didn't crash, try something else.
  return false;
}

namespace {
// Reduce the list of Named Metadata nodes. We keep this as a list of
// names to avoid having to convert back and forth every time.
class ReduceCrashingNamedMD : public ListReducer<std::string> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingNamedMD(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<std::string> &Prefix,
                              std::vector<std::string> &Kept) override {
    if (!Kept.empty() && TestNamedMDs(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestNamedMDs(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestNamedMDs(std::vector<std::string> &NamedMDs);
};
}

bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {

  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  outs() << "Checking for crash with only these named metadata nodes:";
  unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
  for (unsigned i = 0, e = NumPrint; i != e; ++i)
    outs() << " " << NamedMDs[i];
  if (NumPrint < NamedMDs.size())
    outs() << "... <" << NamedMDs.size() << " total>";
  outs() << ": ";

  // Make a StringMap for faster lookup
  StringSet<> Names;
  for (const std::string &Name : NamedMDs)
    Names.insert(Name);

  // First collect all the metadata to delete in a vector, then
  // delete them all at once to avoid invalidating the iterator
  std::vector<NamedMDNode *> ToDelete;
  ToDelete.reserve(M->named_metadata_size() - Names.size());
  for (auto &NamedMD : M->named_metadata())
    // Always keep a nonempty llvm.dbg.cu because the Verifier would complain.
    if (!Names.count(NamedMD.getName()) &&
        (!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0)))
      ToDelete.push_back(&NamedMD);

  for (auto *NamedMD : ToDelete)
    NamedMD->eraseFromParent();

  // Verify that this is still valid.
  isValidModule(M, /*ExitOnFailure=*/false);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
    return true;
  }
  return false;
}

namespace {
// Reduce the list of operands to named metadata nodes
class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {
  BugDriver &BD;
  BugTester TestFn;

public:
  ReduceCrashingNamedMDOps(BugDriver &bd, BugTester testFn)
      : BD(bd), TestFn(testFn) {}

  Expected<TestResult> doTest(std::vector<const MDNode *> &Prefix,
                              std::vector<const MDNode *> &Kept) override {
    if (!Kept.empty() && TestNamedMDOps(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestNamedMDOps(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps);
};
}

bool ReduceCrashingNamedMDOps::TestNamedMDOps(
    std::vector<const MDNode *> &NamedMDOps) {
  // Convert list to set for fast lookup...
  SmallPtrSet<const MDNode *, 32> OldMDNodeOps;
  for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) {
    OldMDNodeOps.insert(NamedMDOps[i]);
  }

  outs() << "Checking for crash with only " << OldMDNodeOps.size();
  if (OldMDNodeOps.size() == 1)
    outs() << " named metadata operand: ";
  else
    outs() << " named metadata operands: ";

  ValueToValueMapTy VMap;
  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);

  // This is a little wasteful. In the future it might be good if we could have
  // these dropped during cloning.
  for (auto &NamedMD : BD.getProgram().named_metadata()) {
    // Drop the old one and create a new one
    M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
    NamedMDNode *NewNamedMDNode =
        M->getOrInsertNamedMetadata(NamedMD.getName());
    for (MDNode *op : NamedMD.operands())
      if (OldMDNodeOps.count(op))
        NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap)));
  }

  // Verify that this is still valid.
  isValidModule(M, /*ExitOnFailure=*/false);

  // Try running on the hacked up program...
  if (TestFn(BD, M.get())) {
    // Make sure to use instruction pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    NamedMDOps.clear();
    for (const MDNode *Node : OldMDNodeOps)
      NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));

    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
    return true;
  }
  // It didn't crash, try something else.
  return false;
}

/// Attempt to eliminate as many global initializers as possible.
static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
  Module &OrigM = BD.getProgram();
  if (OrigM.global_empty())
    return Error::success();

  // Now try to reduce the number of global variable initializers in the
  // module to something small.
  std::unique_ptr<Module> M = CloneModule(OrigM);
  bool DeletedInit = false;

  for (GlobalVariable &GV : M->globals()) {
    if (GV.hasInitializer()) {
      DeleteGlobalInitializer(&GV);
      GV.setLinkage(GlobalValue::ExternalLinkage);
      GV.setComdat(nullptr);
      DeletedInit = true;
    }
  }

  if (!DeletedInit)
    return Error::success();

  // See if the program still causes a crash...
  outs() << "\nChecking to see if we can delete global inits: ";

  if (TestFn(BD, M.get())) { // Still crashes?
    BD.setNewProgram(std::move(M));
    outs() << "\n*** Able to remove all global initializers!\n";
    return Error::success();
  }

  // No longer crashes.
  outs() << "  - Removing all global inits hides problem!\n";

  std::vector<GlobalVariable *> GVs;
  for (GlobalVariable &GV : OrigM.globals())
    if (GV.hasInitializer())
      GVs.push_back(&GV);

  if (GVs.size() > 1 && !BugpointIsInterrupted) {
    outs() << "\n*** Attempting to reduce the number of global initializers "
           << "in the testcase\n";

    unsigned OldSize = GVs.size();
    Expected<bool> Result =
        ReduceCrashingGlobalInitializers(BD, TestFn).reduceList(GVs);
    if (Error E = Result.takeError())
      return E;

    if (GVs.size() < OldSize)
      BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");
  }
  return Error::success();
}

static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
  // Attempt to delete instructions using bisection. This should help out nasty
  // cases with large basic blocks where the problem is at one end.
  if (!BugpointIsInterrupted) {
    std::vector<const Instruction *> Insts;
    for (const Function &F : BD.getProgram())
      for (const BasicBlock &BB : F)
        for (const Instruction &I : BB)
          if (!I.isTerminator())
            Insts.push_back(&I);

    Expected<bool> Result =
        ReduceCrashingInstructions(BD, TestFn).reduceList(Insts);
    if (Error E = Result.takeError())
      return E;
  }

  unsigned Simplification = 2;
  do {
    if (BugpointIsInterrupted)
      // TODO: Should we distinguish this with an "interrupted error"?
      return Error::success();
    --Simplification;
    outs() << "\n*** Attempting to reduce testcase by deleting instruc"
           << "tions: Simplification Level #" << Simplification << '\n';

    // Now that we have deleted the functions that are unnecessary for the
    // program, try to remove instructions that are not necessary to cause the
    // crash.  To do this, we loop through all of the instructions in the
    // remaining functions, deleting them (replacing any values produced with
    // nulls), and then running ADCE and SimplifyCFG.  If the transformed input
    // still triggers failure, keep deleting until we cannot trigger failure
    // anymore.
    //
    unsigned InstructionsToSkipBeforeDeleting = 0;
  TryAgain:

    // Loop over all of the (non-terminator) instructions remaining in the
    // function, attempting to delete them.
    unsigned CurInstructionNum = 0;
    for (Module::const_iterator FI = BD.getProgram().begin(),
                                E = BD.getProgram().end();
         FI != E; ++FI)
      if (!FI->isDeclaration())
        for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;
             ++BI)
          for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end();
               I != E; ++I, ++CurInstructionNum) {
            if (InstructionsToSkipBeforeDeleting) {
              --InstructionsToSkipBeforeDeleting;
            } else {
              if (BugpointIsInterrupted)
                // TODO: Should this be some kind of interrupted error?
                return Error::success();

              if (I->isEHPad() || I->getType()->isTokenTy() ||
                  I->isSwiftError())
                continue;

              outs() << "Checking instruction: " << *I;
              std::unique_ptr<Module> M =
                  BD.deleteInstructionFromProgram(&*I, Simplification);

              // Find out if the pass still crashes on this pass...
              if (TestFn(BD, M.get())) {
                // Yup, it does, we delete the old module, and continue trying
                // to reduce the testcase...
                BD.setNewProgram(std::move(M));
                InstructionsToSkipBeforeDeleting = CurInstructionNum;
                goto TryAgain; // I wish I had a multi-level break here!
              }
            }
          }

    if (InstructionsToSkipBeforeDeleting) {
      InstructionsToSkipBeforeDeleting = 0;
      goto TryAgain;
    }

  } while (Simplification);

  // Attempt to drop metadata from instructions that does not contribute to the
  // crash.
  if (!BugpointIsInterrupted) {
    std::vector<Instruction *> Insts;
    for (Function &F : BD.getProgram())
      for (Instruction &I : instructions(F))
        Insts.push_back(&I);

    Expected<bool> Result =
        ReduceCrashingMetadata(BD, TestFn).reduceList(Insts);
    if (Error E = Result.takeError())
      return E;
  }

  BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");
  return Error::success();
}

/// DebugACrash - Given a predicate that determines whether a component crashes
/// on a program, try to destructively reduce the program while still keeping
/// the predicate true.
static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
  // See if we can get away with nuking some of the global variable initializers
  // in the program...
  if (!NoGlobalRM)
    if (Error E = ReduceGlobalInitializers(BD, TestFn))
      return E;

  // Now try to reduce the number of functions in the module to something small.
  std::vector<Function *> Functions;
  for (Function &F : BD.getProgram())
    if (!F.isDeclaration())
      Functions.push_back(&F);

  if (Functions.size() > 1 && !BugpointIsInterrupted) {
    outs() << "\n*** Attempting to reduce the number of functions "
              "in the testcase\n";

    unsigned OldSize = Functions.size();
    Expected<bool> Result =
        ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);
    if (Error E = Result.takeError())
      return E;

    if (Functions.size() < OldSize)
      BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");
  }

  if (!NoAttributeRM) {
    // For each remaining function, try to reduce that function's attributes.
    std::vector<std::string> FunctionNames;
    for (Function &F : BD.getProgram())
      FunctionNames.push_back(std::string(F.getName()));

    if (!FunctionNames.empty() && !BugpointIsInterrupted) {
      outs() << "\n*** Attempting to reduce the number of function attributes"
                " in the testcase\n";

      unsigned OldSize = 0;
      unsigned NewSize = 0;
      for (std::string &Name : FunctionNames) {
        Function *Fn = BD.getProgram().getFunction(Name);
        assert(Fn && "Could not find function?");

        std::vector<Attribute> Attrs;
        for (Attribute A : Fn->getAttributes().getFnAttrs())
          Attrs.push_back(A);

        OldSize += Attrs.size();
        Expected<bool> Result =
          ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);
        if (Error E = Result.takeError())
          return E;

        NewSize += Attrs.size();
      }

      if (OldSize < NewSize)
        BD.EmitProgressBitcode(BD.getProgram(), "reduced-function-attributes");
    }
  }

  // Attempt to change conditional branches into unconditional branches to
  // eliminate blocks.
  if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
    std::vector<const BasicBlock *> Blocks;
    for (Function &F : BD.getProgram())
      for (BasicBlock &BB : F)
        Blocks.push_back(&BB);
    unsigned OldSize = Blocks.size();
    Expected<bool> Result =
        ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks);
    if (Error E = Result.takeError())
      return E;
    Result = ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks);
    if (Error E = Result.takeError())
      return E;
    if (Blocks.size() < OldSize)
      BD.EmitProgressBitcode(BD.getProgram(), "reduced-conditionals");
  }

  // Attempt to delete entire basic blocks at a time to speed up
  // convergence... this actually works by setting the terminator of the blocks
  // to a return instruction then running simplifycfg, which can potentially
  // shrinks the code dramatically quickly
  //
  if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
    std::vector<const BasicBlock *> Blocks;
    for (Function &F : BD.getProgram())
      for (BasicBlock &BB : F)
        Blocks.push_back(&BB);
    unsigned OldSize = Blocks.size();
    Expected<bool> Result = ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks);
    if (Error E = Result.takeError())
      return E;
    if (Blocks.size() < OldSize)
      BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks");
  }

  if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
    std::vector<const BasicBlock *> Blocks;
    for (Function &F : BD.getProgram())
      for (BasicBlock &BB : F)
        Blocks.push_back(&BB);
    unsigned OldSize = Blocks.size();
    Expected<bool> Result = ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks);
    if (Error E = Result.takeError())
      return E;
    if (Blocks.size() < OldSize)
      BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplifycfg");
  }

  // Attempt to delete instructions using bisection. This should help out nasty
  // cases with large basic blocks where the problem is at one end.
  if (!BugpointIsInterrupted)
    if (Error E = ReduceInsts(BD, TestFn))
      return E;

  // Attempt to strip debug info metadata.
  auto stripMetadata = [&](std::function<bool(Module &)> strip) {
    std::unique_ptr<Module> M = CloneModule(BD.getProgram());
    strip(*M);
    if (TestFn(BD, M.get()))
      BD.setNewProgram(std::move(M));
  };
  if (!NoStripDebugInfo && !BugpointIsInterrupted) {
    outs() << "\n*** Attempting to strip the debug info: ";
    stripMetadata(StripDebugInfo);
  }
  if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {
    outs() << "\n*** Attempting to strip the debug type info: ";
    stripMetadata(stripNonLineTableDebugInfo);
  }

  if (!NoNamedMDRM) {
    if (!BugpointIsInterrupted) {
      // Try to reduce the amount of global metadata (particularly debug info),
      // by dropping global named metadata that anchors them
      outs() << "\n*** Attempting to remove named metadata: ";
      std::vector<std::string> NamedMDNames;
      for (auto &NamedMD : BD.getProgram().named_metadata())
        NamedMDNames.push_back(NamedMD.getName().str());
      Expected<bool> Result =
          ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);
      if (Error E = Result.takeError())
        return E;
    }

    if (!BugpointIsInterrupted) {
      // Now that we quickly dropped all the named metadata that doesn't
      // contribute to the crash, bisect the operands of the remaining ones
      std::vector<const MDNode *> NamedMDOps;
      for (auto &NamedMD : BD.getProgram().named_metadata())
        for (auto *op : NamedMD.operands())
          NamedMDOps.push_back(op);
      Expected<bool> Result =
          ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps);
      if (Error E = Result.takeError())
        return E;
    }
    BD.EmitProgressBitcode(BD.getProgram(), "reduced-named-md");
  }

  // Try to clean up the testcase by running funcresolve and globaldce...
  if (!BugpointIsInterrupted) {
    outs() << "\n*** Attempting to perform final cleanups: ";
    std::unique_ptr<Module> M = CloneModule(BD.getProgram());
    M = BD.performFinalCleanups(std::move(M), true);

    // Find out if the pass still crashes on the cleaned up program...
    if (M && TestFn(BD, M.get()))
      BD.setNewProgram(
          std::move(M)); // Yup, it does, keep the reduced version...
  }

  BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");

  return Error::success();
}

static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {
  return BD.runPasses(*M, BD.getPassesToRun());
}

/// debugOptimizerCrash - This method is called when some pass crashes on input.
/// It attempts to prune down the testcase to something reasonable, and figure
/// out exactly which pass is crashing.
///
Error BugDriver::debugOptimizerCrash(const std::string &ID) {
  outs() << "\n*** Debugging optimizer crash!\n";

  // Reduce the list of passes which causes the optimizer to crash...
  if (!BugpointIsInterrupted && !DontReducePassList) {
    Expected<bool> Result = ReducePassList(*this).reduceList(PassesToRun);
    if (Error E = Result.takeError())
      return E;
  }

  outs() << "\n*** Found crashing pass"
         << (PassesToRun.size() == 1 ? ": " : "es: ")
         << getPassesString(PassesToRun) << '\n';

  EmitProgressBitcode(*Program, ID);

  auto Res = DebugACrash(*this, TestForOptimizerCrash);
  if (Res || DontReducePassList)
    return Res;
  // Try to reduce the pass list again. This covers additional cases
  // we failed to reduce earlier, because of more complex pass dependencies
  // triggering the crash.
  auto SecondRes = ReducePassList(*this).reduceList(PassesToRun);
  if (Error E = SecondRes.takeError())
    return E;
  outs() << "\n*** Found crashing pass"
         << (PassesToRun.size() == 1 ? ": " : "es: ")
         << getPassesString(PassesToRun) << '\n';

  EmitProgressBitcode(getProgram(), "reduced-simplified");
  return Res;
}

static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
  if (Error E = BD.compileProgram(*M)) {
    if (VerboseErrors)
      errs() << toString(std::move(E)) << "\n";
    else {
      consumeError(std::move(E));
      errs() << "<crash>\n";
    }
    return true; // Tool is still crashing.
  }
  errs() << '\n';
  return false;
}

/// debugCodeGeneratorCrash - This method is called when the code generator
/// crashes on an input.  It attempts to reduce the input as much as possible
/// while still causing the code generator to crash.
Error BugDriver::debugCodeGeneratorCrash() {
  errs() << "*** Debugging code generator crash!\n";

  return DebugACrash(*this, TestForCodeGenCrash);
}
