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

  // 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 (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB)
      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 (succ_iterator SI = succ_begin(&*BB), E = succ_end(&*BB); SI != E;
             ++SI)
          (*SI)->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.
  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, Passes);
  delete M;
  if (!New) {
    errs() << "verify failed!\n";
    exit(1);
  }
  M = New.release();

  // Try running on the hacked up program...
  if (TestFn(BD, M)) {
    BD.setNewProgram(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 = M->getValueSymbolTable();
    for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
      Function *F = cast<Function>(GST.lookup(BlockInfo[i].first));
      Value *V = F->getValueSymbolTable()->lookup(BlockInfo[i].second);
      if (V && V->getType() == Type::getLabelTy(V->getContext()))
        BBs.push_back(cast<BasicBlock>(V));
    }
    return true;
  }
  delete M; // It didn't crash, try something else.
  return false;
}