//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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/Transforms/Utils/Local.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.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 <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> 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));
}

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(NewUsedVal->getType()->getPointerTo());
  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.getBaseObject();
      Function *F = dyn_cast_or_null<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 if (!F) {
        // 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 {
/// 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 simplify-cfg 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);

        TerminatorInst *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.getInstList().pop_back();
        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(BB->getParent()->getName(), 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
  std::vector<std::string> Passes;
  Passes.push_back("verify");
  std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
  if (!New) {
    errs() << "verify failed!\n";
    exit(1);
  }
  M = std::move(New);

  // 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(BB->getParent()->getName(), 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
  std::vector<std::string> Passes;
  Passes.push_back("verify");
  std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
  if (!New) {
    errs() << "verify failed!\n";
    exit(1);
  }
  M = std::move(New);

  // 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(BB->getParent()->getName(), 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
  std::vector<std::string> Passes;
  Passes.push_back("verify");
  std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
  if (!New) {
    errs() << "verify failed!\n";
    exit(1);
  }
  M = std::move(New);

  // 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(!isa<TerminatorInst>(Insts[i]));
    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 (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) {
        Instruction *Inst = &*I++;
        if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst) &&
            !Inst->isEHPad() && !Inst->getType()->isTokenTy() &&
            !Inst->isSwiftError()) {
          if (!Inst->getType()->isVoidTy())
            Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
          Inst->eraseFromParent();
        }
      }

  // Verify that this is still valid.
  legacy::PassManager Passes;
  Passes.add(createVerifierPass(/*FatalErrors=*/false));
  Passes.run(*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 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 {
// 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.
  legacy::PassManager Passes;
  Passes.add(createVerifierPass(/*FatalErrors=*/false));
  Passes.run(*M);

  // 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.
  legacy::PassManager Passes;
  Passes.add(createVerifierPass(/*FatalErrors=*/false));
  Passes.run(*M);

  // 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 (!isa<TerminatorInst>(&I))
            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);
  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");
  }

  // 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);

  return DebugACrash(*this, TestForOptimizerCrash);
}

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);
}
