Exemplo n.º 1
0
BasicBlock::~BasicBlock() {
  // If the address of the block is taken and it is being deleted (e.g. because
  // it is dead), this means that there is either a dangling constant expr
  // hanging off the block, or an undefined use of the block (source code
  // expecting the address of a label to keep the block alive even though there
  // is no indirect branch).  Handle these cases by zapping the BlockAddress
  // nodes.  There are no other possible uses at this point.
  if (hasAddressTaken()) {
    assert(!use_empty() && "There should be at least one blockaddress!");
    Constant *Replacement =
      ConstantInt::get(llvm::Type::getInt32Ty(getContext()), 1);
    while (!use_empty()) {
      BlockAddress *BA = cast<BlockAddress>(user_back());
      BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(Replacement,
                                                       BA->getType()));
      BA->destroyConstant();
    }
  }

  assert(getParent() == nullptr && "BasicBlock still linked into the program!");
  dropAllReferences();
  InstList.clear();
}
static bool convertFunction(Function *Func) {
  bool Changed = false;
  IntegerType *I32 = Type::getInt32Ty(Func->getContext());

  // Skip zero in case programs treat a null pointer as special.
  uint32_t NextNum = 1;
  DenseMap<BasicBlock *, ConstantInt *> LabelNums;
  BasicBlock *DefaultBB = NULL;

  // Replace each indirectbr with a switch.
  //
  // If there are multiple indirectbr instructions in the function,
  // this could be expensive.  While an indirectbr is usually
  // converted to O(1) machine instructions, the switch we generate
  // here will be O(n) in the number of target labels.
  //
  // However, Clang usually generates just a single indirectbr per
  // function anyway when compiling C computed gotos.
  //
  // We could try to generate one switch to handle all the indirectbr
  // instructions in the function, but that would be complicated to
  // implement given that variables that are live at one indirectbr
  // might not be live at others.
  for (llvm::Function::iterator BB = Func->begin(), E = Func->end();
       BB != E; ++BB) {
    if (IndirectBrInst *Br = dyn_cast<IndirectBrInst>(BB->getTerminator())) {
      Changed = true;

      if (!DefaultBB) {
        DefaultBB = BasicBlock::Create(Func->getContext(),
                                       "indirectbr_default", Func);
        new UnreachableInst(Func->getContext(), DefaultBB);
      }

      // An indirectbr can list the same target block multiple times.
      // Keep track of the basic blocks we've handled to avoid adding
      // the same case multiple times.
      DenseSet<BasicBlock *> BlocksSeen;

      Value *Cast = new PtrToIntInst(Br->getAddress(), I32,
                                     "indirectbr_cast", Br);
      unsigned Count = Br->getNumSuccessors();
      SwitchInst *Switch = SwitchInst::Create(Cast, DefaultBB, Count, Br);
      for (unsigned I = 0; I < Count; ++I) {
        BasicBlock *Dest = Br->getSuccessor(I);
        if (!BlocksSeen.insert(Dest).second) {
          // Remove duplicated entries from phi nodes.
          for (BasicBlock::iterator Inst = Dest->begin(); ; ++Inst) {
            PHINode *Phi = dyn_cast<PHINode>(Inst);
            if (!Phi)
              break;
            Phi->removeIncomingValue(Br->getParent());
          }
          continue;
        }
        ConstantInt *Val;
        if (LabelNums.count(Dest) == 0) {
          Val = ConstantInt::get(I32, NextNum++);
          LabelNums[Dest] = Val;

          BlockAddress *BA = BlockAddress::get(Func, Dest);
          Value *ValAsPtr = ConstantExpr::getIntToPtr(Val, BA->getType());
          BA->replaceAllUsesWith(ValAsPtr);
          BA->destroyConstant();
        } else {
          Val = LabelNums[Dest];
        }
        Switch->addCase(Val, Br->getSuccessor(I));
      }
      Br->eraseFromParent();
    }
  }

  // If there are any blockaddresses that are never used by an
  // indirectbr, replace them with dummy values.
  SmallVector<Value *, 20> Users(Func->user_begin(), Func->user_end());
  for (auto U : Users) {
    if (BlockAddress *BA = dyn_cast<BlockAddress>(U)) {
      Changed = true;
      Value *DummyVal = ConstantExpr::getIntToPtr(ConstantInt::get(I32, ~0L),
                                                  BA->getType());
      BA->replaceAllUsesWith(DummyVal);
      BA->destroyConstant();
    }
  }
  return Changed;
}