/// WriteInstruction - Emit an instruction to the specified stream.
/// Returns true if instruction actually emitted.
static bool WriteInstruction(const Instruction &I, unsigned InstID,
                             NaClValueEnumerator &VE,
                             NaClBitstreamWriter &Stream,
                             SmallVector<unsigned, 64> &Vals) {
  unsigned Code = 0;
  unsigned AbbrevToUse = 0;
  VE.setInstructionID(&I);
  switch (I.getOpcode()) {
  default:
    if (Instruction::isCast(I.getOpcode())) {
      // CAST:       [opval, destty, castopc]
      if (VE.IsElidedCast(&I))
        return false;
      Code = naclbitc::FUNC_CODE_INST_CAST;
      AbbrevToUse = FUNCTION_INST_CAST_ABBREV;
      pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
      Vals.push_back(VE.getTypeID(I.getType()));
      unsigned Opcode = I.getOpcode();
      Vals.push_back(GetEncodedCastOpcode(Opcode, I));
      if (Opcode == Instruction::PtrToInt ||
          Opcode == Instruction::IntToPtr ||
          (Opcode == Instruction::BitCast &&
           (I.getOperand(0)->getType()->isPointerTy() ||
            I.getType()->isPointerTy()))) {
        ReportIllegalValue("(PNaCl ABI) pointer cast", I);
      }
    } else if (isa<BinaryOperator>(I)) {
      // BINOP:      [opval, opval, opcode]
      Code = naclbitc::FUNC_CODE_INST_BINOP;
      AbbrevToUse = FUNCTION_INST_BINOP_ABBREV;
      pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
      pushValue(I.getOperand(1), InstID, Vals, VE, Stream);
      Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode(), I));
    } else {
      ReportIllegalValue("instruction", I);
    }
    break;
  case Instruction::Select:
    Code = naclbitc::FUNC_CODE_INST_VSELECT;
    pushValue(I.getOperand(1), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(2), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
    break;
  case Instruction::ExtractElement:
    Code = naclbitc::FUNC_CODE_INST_EXTRACTELT;
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(1), InstID, Vals, VE, Stream);
    break;
  case Instruction::InsertElement:
    Code = naclbitc::FUNC_CODE_INST_INSERTELT;
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(1), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(2), InstID, Vals, VE, Stream);
    break;
  case Instruction::ICmp:
  case Instruction::FCmp:
    // compare returning Int1Ty or vector of Int1Ty
    Code = naclbitc::FUNC_CODE_INST_CMP2;
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(1), InstID, Vals, VE, Stream);
    Vals.push_back(GetEncodedCmpPredicate(cast<CmpInst>(I)));
    break;

  case Instruction::Ret:
    {
      Code = naclbitc::FUNC_CODE_INST_RET;
      unsigned NumOperands = I.getNumOperands();
      if (NumOperands == 0)
        AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV;
      else if (NumOperands == 1) {
        pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
        AbbrevToUse = FUNCTION_INST_RET_VAL_ABBREV;
      } else {
        for (unsigned i = 0, e = NumOperands; i != e; ++i)
          pushValue(I.getOperand(i), InstID, Vals, VE, Stream);
      }
    }
    break;
  case Instruction::Br:
    {
      Code = naclbitc::FUNC_CODE_INST_BR;
      const BranchInst &II = cast<BranchInst>(I);
      Vals.push_back(VE.getValueID(II.getSuccessor(0)));
      if (II.isConditional()) {
        Vals.push_back(VE.getValueID(II.getSuccessor(1)));
        pushValue(II.getCondition(), InstID, Vals, VE, Stream);
      }
    }
    break;
  case Instruction::Switch:
    {
      // Redefine Vals, since here we need to use 64 bit values
      // explicitly to store large APInt numbers.
      SmallVector<uint64_t, 128> Vals64;

      Code = naclbitc::FUNC_CODE_INST_SWITCH;
      const SwitchInst &SI = cast<SwitchInst>(I);

      Vals64.push_back(VE.getTypeID(SI.getCondition()->getType()));
      pushValue64(SI.getCondition(), InstID, Vals64, VE, Stream);
      Vals64.push_back(VE.getValueID(SI.getDefaultDest()));
      Vals64.push_back(SI.getNumCases());
      for (SwitchInst::ConstCaseIt i = SI.case_begin(), e = SI.case_end();
           i != e; ++i) {
        // The PNaCl bitcode format has vestigial support for case
        // ranges, but we no longer support reading or writing them,
        // so the next two fields always have the same values.
        // See https://code.google.com/p/nativeclient/issues/detail?id=3758
        Vals64.push_back(1/*NumItems = 1*/);
        Vals64.push_back(true/*IsSingleNumber = true*/);

        emitSignedInt64(Vals64, i.getCaseValue()->getSExtValue());
        Vals64.push_back(VE.getValueID(i.getCaseSuccessor()));
      }

      Stream.EmitRecord(Code, Vals64, AbbrevToUse);

      // Also do expected action - clear external Vals collection:
      Vals.clear();
      return true;
    }
    break;
  case Instruction::Unreachable:
    Code = naclbitc::FUNC_CODE_INST_UNREACHABLE;
    AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
    break;

  case Instruction::PHI: {
    const PHINode &PN = cast<PHINode>(I);
    Code = naclbitc::FUNC_CODE_INST_PHI;
    // With the newer instruction encoding, forward references could give
    // negative valued IDs.  This is most common for PHIs, so we use
    // signed VBRs.
    SmallVector<uint64_t, 128> Vals64;
    Vals64.push_back(VE.getTypeID(PN.getType()));
    for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
      pushValueSigned(PN.getIncomingValue(i), InstID, Vals64, VE, Stream);
      Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i)));
    }
    // Emit a Vals64 vector and exit.
    Stream.EmitRecord(Code, Vals64, AbbrevToUse);
    Vals64.clear();
    return true;
  }

  case Instruction::Alloca:
    if (!cast<AllocaInst>(&I)->getAllocatedType()->isIntegerTy(8))
      report_fatal_error("Type of alloca instruction is not i8");
    Code = naclbitc::FUNC_CODE_INST_ALLOCA;
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream); // size.
    Vals.push_back(Log2_32(cast<AllocaInst>(I).getAlignment())+1);
    break;
  case Instruction::Load:
    // LOAD: [op, align, ty]
    Code = naclbitc::FUNC_CODE_INST_LOAD;
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
    AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
    Vals.push_back(Log2_32(cast<LoadInst>(I).getAlignment())+1);
    Vals.push_back(VE.getTypeID(I.getType()));
    break;
  case Instruction::Store:
    // STORE: [ptr, val, align]
    Code = naclbitc::FUNC_CODE_INST_STORE;
    AbbrevToUse = FUNCTION_INST_STORE_ABBREV;
    pushValue(I.getOperand(1), InstID, Vals, VE, Stream);
    pushValue(I.getOperand(0), InstID, Vals, VE, Stream);
    Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1);
    break;
  case Instruction::Call: {
    // CALL: [cc, fnid, args...]
    // CALL_INDIRECT: [cc, fnid, fnty, args...]

    const CallInst &Call = cast<CallInst>(I);
    const Value* Callee = Call.getCalledValue();
    Vals.push_back((GetEncodedCallingConv(Call.getCallingConv()) << 1)
                   | unsigned(Call.isTailCall()));

    pushValue(Callee, InstID, Vals, VE, Stream);

    if (Callee == VE.ElideCasts(Callee)) {
      // Since the call pointer has not been elided, we know that
      // the call pointer has the type signature of the called
      // function.  This implies that the reader can use the type
      // signature of the callee to figure out how to add casts to
      // the arguments.
      Code = naclbitc::FUNC_CODE_INST_CALL;
    } else {
      // If the cast was elided, a pointer conversion to a pointer
      // was applied, meaning that this is an indirect call. For the
      // reader, this implies that we can't use the type signature
      // of the callee to resolve elided call arguments, since it is
      // not known. Hence, we must send the type signature to the
      // reader.
      Code = naclbitc::FUNC_CODE_INST_CALL_INDIRECT;
      Vals.push_back(VE.getTypeID(I.getType()));
    }

    for (unsigned I = 0, E = Call.getNumArgOperands(); I < E; ++I) {
      pushValue(Call.getArgOperand(I), InstID, Vals, VE, Stream);
    }
    break;
  }
  }

  Stream.EmitRecord(Code, Vals, AbbrevToUse);
  Vals.clear();
  return true;
}
示例#2
0
/// The specified block is found to be reachable, clone it and
/// anything that it can reach.
void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
                                       BasicBlock::const_iterator StartingInst,
                                       std::vector<const BasicBlock*> &ToClone){
  WeakVH &BBEntry = VMap[BB];

  // Have we already cloned this block?
  if (BBEntry) return;
  
  // Nope, clone it now.
  BasicBlock *NewBB;
  BBEntry = NewBB = BasicBlock::Create(BB->getContext());
  if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix);

  // It is only legal to clone a function if a block address within that
  // function is never referenced outside of the function.  Given that, we
  // want to map block addresses from the old function to block addresses in
  // the clone. (This is different from the generic ValueMapper
  // implementation, which generates an invalid blockaddress when
  // cloning a function.)
  //
  // Note that we don't need to fix the mapping for unreachable blocks;
  // the default mapping there is safe.
  if (BB->hasAddressTaken()) {
    Constant *OldBBAddr = BlockAddress::get(const_cast<Function*>(OldFunc),
                                            const_cast<BasicBlock*>(BB));
    VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
  }

  bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;

  // Loop over all instructions, and copy them over, DCE'ing as we go.  This
  // loop doesn't include the terminator.
  for (BasicBlock::const_iterator II = StartingInst, IE = --BB->end();
       II != IE; ++II) {

    Instruction *NewInst = II->clone();

    // Eagerly remap operands to the newly cloned instruction, except for PHI
    // nodes for which we defer processing until we update the CFG.
    if (!isa<PHINode>(NewInst)) {
      RemapInstruction(NewInst, VMap,
                       ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges);

      // If we can simplify this instruction to some other value, simply add
      // a mapping to that value rather than inserting a new instruction into
      // the basic block.
      if (Value *V =
              SimplifyInstruction(NewInst, BB->getModule()->getDataLayout())) {
        // On the off-chance that this simplifies to an instruction in the old
        // function, map it back into the new function.
        if (Value *MappedV = VMap.lookup(V))
          V = MappedV;

        VMap[&*II] = V;
        delete NewInst;
        continue;
      }
    }

    if (II->hasName())
      NewInst->setName(II->getName()+NameSuffix);
    VMap[&*II] = NewInst; // Add instruction map to value.
    NewBB->getInstList().push_back(NewInst);
    hasCalls |= (isa<CallInst>(II) && !isa<DbgInfoIntrinsic>(II));

    if (CodeInfo)
      if (auto CS = ImmutableCallSite(&*II))
        if (CS.hasOperandBundles())
          CodeInfo->OperandBundleCallSites.push_back(NewInst);

    if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
      if (isa<ConstantInt>(AI->getArraySize()))
        hasStaticAllocas = true;
      else
        hasDynamicAllocas = true;
    }
  }
  
  // Finally, clone over the terminator.
  const TerminatorInst *OldTI = BB->getTerminator();
  bool TerminatorDone = false;
  if (const BranchInst *BI = dyn_cast<BranchInst>(OldTI)) {
    if (BI->isConditional()) {
      // If the condition was a known constant in the callee...
      ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());
      // Or is a known constant in the caller...
      if (!Cond) {
        Value *V = VMap[BI->getCondition()];
        Cond = dyn_cast_or_null<ConstantInt>(V);
      }

      // Constant fold to uncond branch!
      if (Cond) {
        BasicBlock *Dest = BI->getSuccessor(!Cond->getZExtValue());
        VMap[OldTI] = BranchInst::Create(Dest, NewBB);
        ToClone.push_back(Dest);
        TerminatorDone = true;
      }
    }
  } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(OldTI)) {
    // If switching on a value known constant in the caller.
    ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition());
    if (!Cond) { // Or known constant after constant prop in the callee...
      Value *V = VMap[SI->getCondition()];
      Cond = dyn_cast_or_null<ConstantInt>(V);
    }
    if (Cond) {     // Constant fold to uncond branch!
      SwitchInst::ConstCaseIt Case = SI->findCaseValue(Cond);
      BasicBlock *Dest = const_cast<BasicBlock*>(Case.getCaseSuccessor());
      VMap[OldTI] = BranchInst::Create(Dest, NewBB);
      ToClone.push_back(Dest);
      TerminatorDone = true;
    }
  }
  
  if (!TerminatorDone) {
    Instruction *NewInst = OldTI->clone();
    if (OldTI->hasName())
      NewInst->setName(OldTI->getName()+NameSuffix);
    NewBB->getInstList().push_back(NewInst);
    VMap[OldTI] = NewInst;             // Add instruction map to value.

    if (CodeInfo)
      if (auto CS = ImmutableCallSite(OldTI))
        if (CS.hasOperandBundles())
          CodeInfo->OperandBundleCallSites.push_back(NewInst);

    // Recursively clone any reachable successor blocks.
    const TerminatorInst *TI = BB->getTerminator();
    for (const BasicBlock *Succ : TI->successors())
      ToClone.push_back(Succ);
  }
  
  if (CodeInfo) {
    CodeInfo->ContainsCalls          |= hasCalls;
    CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
    CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas && 
      BB != &BB->getParent()->front();
  }
}
示例#3
0
/// CloneBlock - The specified block is found to be reachable, clone it and
/// anything that it can reach.
void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
                                       std::vector<const BasicBlock*> &ToClone) {
    TrackingVH<Value> &BBEntry = VMap[BB];

    // Have we already cloned this block?
    if (BBEntry) return;

    // Nope, clone it now.
    BasicBlock *NewBB;
    BBEntry = NewBB = BasicBlock::Create(BB->getContext());
    if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix);

    // It is only legal to clone a function if a block address within that
    // function is never referenced outside of the function.  Given that, we
    // want to map block addresses from the old function to block addresses in
    // the clone. (This is different from the generic ValueMapper
    // implementation, which generates an invalid blockaddress when
    // cloning a function.)
    //
    // Note that we don't need to fix the mapping for unreachable blocks;
    // the default mapping there is safe.
    if (BB->hasAddressTaken()) {
        Constant *OldBBAddr = BlockAddress::get(const_cast<Function*>(OldFunc),
                                                const_cast<BasicBlock*>(BB));
        VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
    }


    bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;

    // Loop over all instructions, and copy them over, DCE'ing as we go.  This
    // loop doesn't include the terminator.
    for (BasicBlock::const_iterator II = BB->begin(), IE = --BB->end();
            II != IE; ++II) {
        // If this instruction constant folds, don't bother cloning the instruction,
        // instead, just add the constant to the value map.
        if (Constant *C = ConstantFoldMappedInstruction(II)) {
            VMap[II] = C;
            continue;
        }

        Instruction *NewInst = II->clone();
        if (II->hasName())
            NewInst->setName(II->getName()+NameSuffix);
        NewBB->getInstList().push_back(NewInst);
        VMap[II] = NewInst;                // Add instruction map to value.

        hasCalls |= (isa<CallInst>(II) && !isa<DbgInfoIntrinsic>(II));
        if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
            if (isa<ConstantInt>(AI->getArraySize()))
                hasStaticAllocas = true;
            else
                hasDynamicAllocas = true;
        }
    }

    // Finally, clone over the terminator.
    const TerminatorInst *OldTI = BB->getTerminator();
    bool TerminatorDone = false;
    if (const BranchInst *BI = dyn_cast<BranchInst>(OldTI)) {
        if (BI->isConditional()) {
            // If the condition was a known constant in the callee...
            ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());
            // Or is a known constant in the caller...
            if (Cond == 0) {
                Value *V = VMap[BI->getCondition()];
                Cond = dyn_cast_or_null<ConstantInt>(V);
            }

            // Constant fold to uncond branch!
            if (Cond) {
                BasicBlock *Dest = BI->getSuccessor(!Cond->getZExtValue());
                VMap[OldTI] = BranchInst::Create(Dest, NewBB);
                ToClone.push_back(Dest);
                TerminatorDone = true;
            }
        }
    } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(OldTI)) {
        // If switching on a value known constant in the caller.
        ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition());
        if (Cond == 0) { // Or known constant after constant prop in the callee...
            Value *V = VMap[SI->getCondition()];
            Cond = dyn_cast_or_null<ConstantInt>(V);
        }
        if (Cond) {     // Constant fold to uncond branch!
            SwitchInst::ConstCaseIt Case = SI->findCaseValue(Cond);
            BasicBlock *Dest = const_cast<BasicBlock*>(Case.getCaseSuccessor());
            VMap[OldTI] = BranchInst::Create(Dest, NewBB);
            ToClone.push_back(Dest);
            TerminatorDone = true;
        }
    }

    if (!TerminatorDone) {
        Instruction *NewInst = OldTI->clone();
        if (OldTI->hasName())
            NewInst->setName(OldTI->getName()+NameSuffix);
        NewBB->getInstList().push_back(NewInst);
        VMap[OldTI] = NewInst;             // Add instruction map to value.

        // Recursively clone any reachable successor blocks.
        const TerminatorInst *TI = BB->getTerminator();
        for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
            ToClone.push_back(TI->getSuccessor(i));
    }

    if (CodeInfo) {
        CodeInfo->ContainsCalls          |= hasCalls;
        CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
        CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas &&
                                            BB != &BB->getParent()->front();
    }

    if (ReturnInst *RI = dyn_cast<ReturnInst>(NewBB->getTerminator()))
        Returns.push_back(RI);
}