Ejemplo n.º 1
0
bool CallAnalyzer::visitGetElementPtr(GetElementPtrInst &I) {
  Value *SROAArg;
  DenseMap<Value *, int>::iterator CostIt;
  bool SROACandidate = lookupSROAArgAndCost(I.getPointerOperand(),
                                            SROAArg, CostIt);

  // Try to fold GEPs of constant-offset call site argument pointers. This
  // requires target data and inbounds GEPs.
  if (TD && I.isInBounds()) {
    // Check if we have a base + offset for the pointer.
    Value *Ptr = I.getPointerOperand();
    std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(Ptr);
    if (BaseAndOffset.first) {
      // Check if the offset of this GEP is constant, and if so accumulate it
      // into Offset.
      if (!accumulateGEPOffset(cast<GEPOperator>(I), BaseAndOffset.second)) {
        // Non-constant GEPs aren't folded, and disable SROA.
        if (SROACandidate)
          disableSROA(CostIt);
        return false;
      }

      // Add the result as a new mapping to Base + Offset.
      ConstantOffsetPtrs[&I] = BaseAndOffset;

      // Also handle SROA candidates here, we already know that the GEP is
      // all-constant indexed.
      if (SROACandidate)
        SROAArgValues[&I] = SROAArg;

      return true;
    }
  }

  if (isGEPOffsetConstant(I)) {
    if (SROACandidate)
      SROAArgValues[&I] = SROAArg;

    // Constant GEPs are modeled as free.
    return true;
  }

  // Variable GEPs will require math and will disable SROA.
  if (SROACandidate)
    disableSROA(CostIt);
  return false;
}
Ejemplo n.º 2
0
 void visitGetElementPtrInst(GetElementPtrInst &GEP) {
   Value *pointerOperand = GEP.getPointerOperand();
   DSGraph * TDG = budsPass->getDSGraph(*(GEP.getParent()->getParent()));
   DSNode *DSN = TDG->getNodeForValue(pointerOperand).getNode();
   //FIXME DO we really need this ?      markReachableAllocas(DSN);
   if (DSN && DSN->isAllocaNode() && !DSN->isNodeCompletelyFolded()) {
     unsafeAllocaNodes.push_back(DSN);
   }
 }
Ejemplo n.º 3
0
void Executor::executeGep(Instruction *i) {
    if (DisabledSymbolicExeCurRun) {
        return;
    }
    assert(i && "Expecting an instruction!");
    GetElementPtrInst *gep = (GetElementPtrInst*) i;
    assert(gep->getNumIndices()<=2 && "Unsupported gep instruction");
    if(AllocaInst *a = dyn_cast<AllocaInst>(gep->getPointerOperand())) {
        Type *ty = a->getAllocatedType();
        if (ty->isIntegerTy()) {
            // Incompleteness: pointer dereferencement on symbolic value
            AllLocDefinite = false;
            return;
        }
    }
    unsigned idx = 0;
    Type *subTy = NULL;
    Type *ptrOpTy = gep->getPointerOperandType();    
    if (ptrOpTy && ptrOpTy->getNumContainedTypes()==1) {
        subTy = ptrOpTy->getContainedType(0);
    }
    if (subTy && subTy->getNumContainedTypes()>0) {
        idx = 1;
    } else {
        assert("Unsupported gep instruction!");
    }
    Value *ptr = (Value*) i;
    if(gep->hasIndices()) {
        Value *index = gep->getOperand(idx+1);
        if (SMAP->contains(index)) {
            // P[v->sv] // sv is a new symbolic value
            // Value *a = gep->getPointerOperand();
            // ptr = (a index)  
            //SymbolPtr Sindex = SMAP->get(index);
            //PMAP->createGepOp(ptr, a, Sindex);
            
            // Incompleteness: pointer dereferencement on symbolic value
            AllLocDefinite = false;
        } else {
            // P = P - ptr
            PMAP->remove(ptr);
        }
    }
    // Global allocation
    /*else if(isa<GlobalVariable>(ptr)) {
        // ptr in domain(P)
        if (PMAP->contains(ptr)) {
            SymbolPtr Pptr = PMAP->get(ptr);
            // P' = P[ptr->S(val)]
            PMAP->update(ptr, Pptr);
        } else {
            // P = P - ptr
            PMAP->remove(ptr);
        }
    }*/
}
Ejemplo n.º 4
0
//
// Method: visitGetElementPtrInst()
//
// Description:
//  This method checks to see if the specified GEP is safe.  If it cannot prove
//  it safe, it then adds a run-time check for it.
//
void
InsertGEPChecks::visitGetElementPtrInst (GetElementPtrInst & GEP) {
  //
  // Don't insert a check if GEP only indexes into a structure and the
  // user doesn't want to do structure index checking.
  //
  if (DisableStructChecks && indexesStructsOnly (&GEP)) {
    return;
  }

  //
  // Get the function in which the GEP instruction lives.
  //
  Value * PH = ConstantPointerNull::get (getVoidPtrType(GEP.getContext()));
  BasicBlock::iterator InsertPt = &GEP;
  ++InsertPt;
  Instruction * ResultPtr = castTo (&GEP,
                                    getVoidPtrType(GEP.getContext()),
                                    GEP.getName() + ".cast",
                                    InsertPt);

  //
  // Make this an actual cast instruction; it will make it easier to update
  // DSA.
  //
  Value * SrcPtr = castTo (GEP.getPointerOperand(),
                           getVoidPtrType(GEP.getContext()),
                           GEP.getName()+".cast",
                           InsertPt);

  //
  // Create the call to the run-time check.
  //
  std::vector<Value *> args(1, PH);
  args.push_back (SrcPtr);
  args.push_back (ResultPtr);
  CallInst * CI = CallInst::Create (PoolCheckArrayUI, args, "", InsertPt);

  //
  // Add debugging info metadata to the run-time check.
  //
  if (MDNode * MD = GEP.getMetadata ("dbg"))
    CI->setMetadata ("dbg", MD);

  //
  // Update the statistics.
  //
  ++GEPChecks;
  return;
}
Ejemplo n.º 5
0
// -- handle GetElementPtr instruction -- 
void UnsafeTypeCastingCheck::handleGetElementPtrInstruction (Instruction *inst) {
  GetElementPtrInst * ginst = dyn_cast<GetElementPtrInst>(inst); 
  if (ginst == NULL) 
    utccAbort("handleGetElementPtrInstruction cannot process with a non-getelementptr instruction");       
  Value *pt = ginst->getPointerOperand(); 

  UTCC_TYPE pt_ut_self = UH_UT; 
  UTCC_TYPE pt_ut_base = UH_UT; 
  UTCC_TYPE pt_ut_element = llvmT2utccT(ginst->getType()->getPointerElementType(), ginst); 

  if (isVisitedPointer(ginst)) pt_ut_self = queryPointedType(ginst); 
  if (isVisitedPointer(pt)) pt_ut_base = queryPointedType(pt); 

  setPointedType(ginst, utSaturate(pt_ut_element, 
				   utSaturate(pt_ut_self, pt_ut_base))); 
  setExprType(ginst, llvmT2utccT(ginst->getType(), ginst)); 
}
Ejemplo n.º 6
0
void ArrayIndexChecker::visitGetElementPtrInst(GetElementPtrInst& I) {
  DEBUG(dbgs() << "ArrayIndexChecker: visiting GEP " << I << "\n");

  visitValue(*I.getPointerOperand());
  for (auto Idx = I.idx_begin(), E = I.idx_end(); Idx != E; ++Idx) {
    visitValue(**Idx);
  }

  auto pos = std::find(ptr_value_vec_.begin(), ptr_value_vec_.end(), &I);
  assert(pos != ptr_value_vec_.end());
  index_t varIdx = pos - ptr_value_vec_.begin();

  assert(idx2addr_.find(varIdx) != idx2addr_.end());
  if (addr2version_[idx2addr_[varIdx]] != 0)
    throw ArrayIndexIsNotConstant;;

  DEBUG(dbgs() << "ArrayIndexChecker: visited GEP\n");
}
Ejemplo n.º 7
0
void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) {
  ExecutionContext &SF = ECStack.back();
  SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(),
                                   gep_type_begin(I), gep_type_end(I), SF), SF);
}
Ejemplo n.º 8
0
Value *llvm::ConvertExpressionToType(Value *V, const Type *Ty, 
                                     ValueMapCache &VMC, const TargetData &TD) {
  if (V->getType() == Ty) return V;  // Already where we need to be?

  ValueMapCache::ExprMapTy::iterator VMCI = VMC.ExprMap.find(V);
  if (VMCI != VMC.ExprMap.end()) {
    const Value *GV = VMCI->second;
    const Type *GTy = VMCI->second->getType();
    assert(VMCI->second->getType() == Ty);

    if (Instruction *I = dyn_cast<Instruction>(V))
      ValueHandle IHandle(VMC, I);  // Remove I if it is unused now!

    return VMCI->second;
  }

  DEBUG(std::cerr << "CETT: " << (void*)V << " " << *V);

  Instruction *I = dyn_cast<Instruction>(V);
  if (I == 0) {
    Constant *CPV = cast<Constant>(V);
    // Constants are converted by constant folding the cast that is required.
    // We assume here that all casts are implemented for constant prop.
    Value *Result = ConstantExpr::getCast(CPV, Ty);
    // Add the instruction to the expression map
    //VMC.ExprMap[V] = Result;
    return Result;
  }


  BasicBlock *BB = I->getParent();
  std::string Name = I->getName();  if (!Name.empty()) I->setName("");
  Instruction *Res;     // Result of conversion

  ValueHandle IHandle(VMC, I);  // Prevent I from being removed!
  
  Constant *Dummy = Constant::getNullValue(Ty);

  switch (I->getOpcode()) {
  case Instruction::Cast:
    assert(VMC.NewCasts.count(ValueHandle(VMC, I)) == 0);
    Res = new CastInst(I->getOperand(0), Ty, Name);
    VMC.NewCasts.insert(ValueHandle(VMC, Res));
    break;
    
  case Instruction::Add:
  case Instruction::Sub:
    Res = BinaryOperator::create(cast<BinaryOperator>(I)->getOpcode(),
                                 Dummy, Dummy, Name);
    VMC.ExprMap[I] = Res;   // Add node to expression eagerly

    Res->setOperand(0, ConvertExpressionToType(I->getOperand(0), Ty, VMC, TD));
    Res->setOperand(1, ConvertExpressionToType(I->getOperand(1), Ty, VMC, TD));
    break;

  case Instruction::Shl:
  case Instruction::Shr:
    Res = new ShiftInst(cast<ShiftInst>(I)->getOpcode(), Dummy,
                        I->getOperand(1), Name);
    VMC.ExprMap[I] = Res;
    Res->setOperand(0, ConvertExpressionToType(I->getOperand(0), Ty, VMC, TD));
    break;

  case Instruction::Load: {
    LoadInst *LI = cast<LoadInst>(I);

    Res = new LoadInst(Constant::getNullValue(PointerType::get(Ty)), Name);
    VMC.ExprMap[I] = Res;
    Res->setOperand(0, ConvertExpressionToType(LI->getPointerOperand(),
                                               PointerType::get(Ty), VMC, TD));
    assert(Res->getOperand(0)->getType() == PointerType::get(Ty));
    assert(Ty == Res->getType());
    assert(Res->getType()->isFirstClassType() && "Load of structure or array!");
    break;
  }

  case Instruction::PHI: {
    PHINode *OldPN = cast<PHINode>(I);
    PHINode *NewPN = new PHINode(Ty, Name);

    VMC.ExprMap[I] = NewPN;   // Add node to expression eagerly
    while (OldPN->getNumOperands()) {
      BasicBlock *BB = OldPN->getIncomingBlock(0);
      Value *OldVal = OldPN->getIncomingValue(0);
      ValueHandle OldValHandle(VMC, OldVal);
      OldPN->removeIncomingValue(BB, false);
      Value *V = ConvertExpressionToType(OldVal, Ty, VMC, TD);
      NewPN->addIncoming(V, BB);
    }
    Res = NewPN;
    break;
  }

  case Instruction::Malloc: {
    Res = ConvertMallocToType(cast<MallocInst>(I), Ty, Name, VMC, TD);
    break;
  }

  case Instruction::GetElementPtr: {
    // GetElementPtr's are directly convertible to a pointer type if they have
    // a number of zeros at the end.  Because removing these values does not
    // change the logical offset of the GEP, it is okay and fair to remove them.
    // This can change this:
    //   %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0  ; <%List **>
    //   %t2 = cast %List * * %t1 to %List *
    // into
    //   %t2 = getelementptr %Hosp * %hosp, ubyte 4           ; <%List *>
    // 
    GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);

    // Check to see if there are zero elements that we can remove from the
    // index array.  If there are, check to see if removing them causes us to
    // get to the right type...
    //
    std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
    const Type *BaseType = GEP->getPointerOperand()->getType();
    const Type *PVTy = cast<PointerType>(Ty)->getElementType();
    Res = 0;
    while (!Indices.empty() &&
           Indices.back() == Constant::getNullValue(Indices.back()->getType())){
      Indices.pop_back();
      if (GetElementPtrInst::getIndexedType(BaseType, Indices, true) == PVTy) {
        if (Indices.size() == 0)
          Res = new CastInst(GEP->getPointerOperand(), BaseType); // NOOP CAST
        else
          Res = new GetElementPtrInst(GEP->getPointerOperand(), Indices, Name);
        break;
      }
    }

    if (Res == 0 && GEP->getNumOperands() == 2 &&
        GEP->getType() == PointerType::get(Type::SByteTy)) {
      
      // Otherwise, we can convert a GEP from one form to the other iff the
      // current gep is of the form 'getelementptr sbyte*, unsigned N
      // and we could convert this to an appropriate GEP for the new type.
      //
      const PointerType *NewSrcTy = PointerType::get(PVTy);
      BasicBlock::iterator It = I;

      // Check to see if 'N' is an expression that can be converted to
      // the appropriate size... if so, allow it.
      //
      std::vector<Value*> Indices;
      const Type *ElTy = ConvertibleToGEP(NewSrcTy, I->getOperand(1),
                                          Indices, TD, &It);
      if (ElTy) {        
        assert(ElTy == PVTy && "Internal error, setup wrong!");
        Res = new GetElementPtrInst(Constant::getNullValue(NewSrcTy),
                                    Indices, Name);
        VMC.ExprMap[I] = Res;
        Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),
                                                   NewSrcTy, VMC, TD));
      }
    }

    // Otherwise, it could be that we have something like this:
    //     getelementptr [[sbyte] *] * %reg115, uint %reg138    ; [sbyte]**
    // and want to convert it into something like this:
    //     getelemenptr [[int] *] * %reg115, uint %reg138      ; [int]**
    //
    if (Res == 0) {
      const PointerType *NewSrcTy = PointerType::get(PVTy);
      std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
      Res = new GetElementPtrInst(Constant::getNullValue(NewSrcTy),
                                  Indices, Name);
      VMC.ExprMap[I] = Res;
      Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),
                                                 NewSrcTy, VMC, TD));
    }


    assert(Res && "Didn't find match!");
    break;
  }

  case Instruction::Call: {
    assert(!isa<Function>(I->getOperand(0)));

    // If this is a function pointer, we can convert the return type if we can
    // convert the source function pointer.
    //
    const PointerType *PT = cast<PointerType>(I->getOperand(0)->getType());
    const FunctionType *FT = cast<FunctionType>(PT->getElementType());
    std::vector<const Type *> ArgTys(FT->param_begin(), FT->param_end());
    const FunctionType *NewTy =
      FunctionType::get(Ty, ArgTys, FT->isVarArg());
    const PointerType *NewPTy = PointerType::get(NewTy);
    if (Ty == Type::VoidTy)
      Name = "";  // Make sure not to name calls that now return void!

    Res = new CallInst(Constant::getNullValue(NewPTy),
                       std::vector<Value*>(I->op_begin()+1, I->op_end()),
                       Name);
    VMC.ExprMap[I] = Res;
    Res->setOperand(0, ConvertExpressionToType(I->getOperand(0),NewPTy,VMC,TD));
    break;
  }
  default:
    assert(0 && "Expression convertible, but don't know how to convert?");
    return 0;
  }

  assert(Res->getType() == Ty && "Didn't convert expr to correct type!");

  BB->getInstList().insert(I, Res);

  // Add the instruction to the expression map
  VMC.ExprMap[I] = Res;


  unsigned NumUses = I->use_size();
  for (unsigned It = 0; It < NumUses; ) {
    unsigned OldSize = NumUses;
    Value::use_iterator UI = I->use_begin();
    std::advance(UI, It);
    ConvertOperandToType(*UI, I, Res, VMC, TD);
    NumUses = I->use_size();
    if (NumUses == OldSize) ++It;
  }

  DEBUG(std::cerr << "ExpIn: " << (void*)I << " " << *I
                  << "ExpOut: " << (void*)Res << " " << *Res);

  return Res;
}
Ejemplo n.º 9
0
// ExpressionConvertibleToType - Return true if it is possible
bool llvm::ExpressionConvertibleToType(Value *V, const Type *Ty,
                                 ValueTypeCache &CTMap, const TargetData &TD) {
  // Expression type must be holdable in a register.
  if (!Ty->isFirstClassType())
    return false;
  
  ValueTypeCache::iterator CTMI = CTMap.find(V);
  if (CTMI != CTMap.end()) return CTMI->second == Ty;

  // If it's a constant... all constants can be converted to a different
  // type.
  //
  if (isa<Constant>(V) && !isa<GlobalValue>(V))
    return true;
  
  CTMap[V] = Ty;
  if (V->getType() == Ty) return true;  // Expression already correct type!

  Instruction *I = dyn_cast<Instruction>(V);
  if (I == 0) return false;              // Otherwise, we can't convert!

  switch (I->getOpcode()) {
  case Instruction::Cast:
    // We can convert the expr if the cast destination type is losslessly
    // convertible to the requested type.
    if (!Ty->isLosslesslyConvertibleTo(I->getType())) return false;

    // We also do not allow conversion of a cast that casts from a ptr to array
    // of X to a *X.  For example: cast [4 x %List *] * %val to %List * *
    //
    if (const PointerType *SPT = 
        dyn_cast<PointerType>(I->getOperand(0)->getType()))
      if (const PointerType *DPT = dyn_cast<PointerType>(I->getType()))
        if (const ArrayType *AT = dyn_cast<ArrayType>(SPT->getElementType()))
          if (AT->getElementType() == DPT->getElementType())
            return false;
    break;

  case Instruction::Add:
  case Instruction::Sub:
    if (!Ty->isInteger() && !Ty->isFloatingPoint()) return false;
    if (!ExpressionConvertibleToType(I->getOperand(0), Ty, CTMap, TD) ||
        !ExpressionConvertibleToType(I->getOperand(1), Ty, CTMap, TD))
      return false;
    break;
  case Instruction::Shr:
    if (!Ty->isInteger()) return false;
    if (Ty->isSigned() != V->getType()->isSigned()) return false;
    // FALL THROUGH
  case Instruction::Shl:
    if (!Ty->isInteger()) return false;
    if (!ExpressionConvertibleToType(I->getOperand(0), Ty, CTMap, TD))
      return false;
    break;

  case Instruction::Load: {
    LoadInst *LI = cast<LoadInst>(I);
    if (!ExpressionConvertibleToType(LI->getPointerOperand(),
                                     PointerType::get(Ty), CTMap, TD))
      return false;
    break;                                     
  }
  case Instruction::PHI: {
    PHINode *PN = cast<PHINode>(I);
    // Be conservative if we find a giant PHI node.
    if (PN->getNumIncomingValues() > 32) return false;

    for (unsigned i = 0; i < PN->getNumIncomingValues(); ++i)
      if (!ExpressionConvertibleToType(PN->getIncomingValue(i), Ty, CTMap, TD))
        return false;
    break;
  }

  case Instruction::Malloc:
    if (!MallocConvertibleToType(cast<MallocInst>(I), Ty, CTMap, TD))
      return false;
    break;

  case Instruction::GetElementPtr: {
    // GetElementPtr's are directly convertible to a pointer type if they have
    // a number of zeros at the end.  Because removing these values does not
    // change the logical offset of the GEP, it is okay and fair to remove them.
    // This can change this:
    //   %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0  ; <%List **>
    //   %t2 = cast %List * * %t1 to %List *
    // into
    //   %t2 = getelementptr %Hosp * %hosp, ubyte 4           ; <%List *>
    // 
    GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
    const PointerType *PTy = dyn_cast<PointerType>(Ty);
    if (!PTy) return false;  // GEP must always return a pointer...
    const Type *PVTy = PTy->getElementType();

    // Check to see if there are zero elements that we can remove from the
    // index array.  If there are, check to see if removing them causes us to
    // get to the right type...
    //
    std::vector<Value*> Indices(GEP->idx_begin(), GEP->idx_end());
    const Type *BaseType = GEP->getPointerOperand()->getType();
    const Type *ElTy = 0;

    while (!Indices.empty() &&
           Indices.back() == Constant::getNullValue(Indices.back()->getType())){
      Indices.pop_back();
      ElTy = GetElementPtrInst::getIndexedType(BaseType, Indices, true);
      if (ElTy == PVTy)
        break;  // Found a match!!
      ElTy = 0;
    }

    if (ElTy) break;   // Found a number of zeros we can strip off!

    // Otherwise, we can convert a GEP from one form to the other iff the
    // current gep is of the form 'getelementptr sbyte*, long N
    // and we could convert this to an appropriate GEP for the new type.
    //
    if (GEP->getNumOperands() == 2 &&
        GEP->getType() == PointerType::get(Type::SByteTy)) {

      // Do not Check to see if our incoming pointer can be converted
      // to be a ptr to an array of the right type... because in more cases than
      // not, it is simply not analyzable because of pointer/array
      // discrepancies.  To fix this, we will insert a cast before the GEP.
      //

      // Check to see if 'N' is an expression that can be converted to
      // the appropriate size... if so, allow it.
      //
      std::vector<Value*> Indices;
      const Type *ElTy = ConvertibleToGEP(PTy, I->getOperand(1), Indices, TD);
      if (ElTy == PVTy) {
        if (!ExpressionConvertibleToType(I->getOperand(0),
                                         PointerType::get(ElTy), CTMap, TD))
          return false;  // Can't continue, ExConToTy might have polluted set!
        break;
      }
    }

    // Otherwise, it could be that we have something like this:
    //     getelementptr [[sbyte] *] * %reg115, long %reg138    ; [sbyte]**
    // and want to convert it into something like this:
    //     getelemenptr [[int] *] * %reg115, long %reg138      ; [int]**
    //
    if (GEP->getNumOperands() == 2 && 
        PTy->getElementType()->isSized() &&
        TD.getTypeSize(PTy->getElementType()) == 
        TD.getTypeSize(GEP->getType()->getElementType())) {
      const PointerType *NewSrcTy = PointerType::get(PVTy);
      if (!ExpressionConvertibleToType(I->getOperand(0), NewSrcTy, CTMap, TD))
        return false;
      break;
    }

    return false;   // No match, maybe next time.
  }

  case Instruction::Call: {
    if (isa<Function>(I->getOperand(0)))
      return false;  // Don't even try to change direct calls.

    // If this is a function pointer, we can convert the return type if we can
    // convert the source function pointer.
    //
    const PointerType *PT = cast<PointerType>(I->getOperand(0)->getType());
    const FunctionType *FT = cast<FunctionType>(PT->getElementType());
    std::vector<const Type *> ArgTys(FT->param_begin(), FT->param_end());
    const FunctionType *NewTy =
      FunctionType::get(Ty, ArgTys, FT->isVarArg());
    if (!ExpressionConvertibleToType(I->getOperand(0),
                                     PointerType::get(NewTy), CTMap, TD))
      return false;
    break;
  }
  default:
    return false;
  }

  // Expressions are only convertible if all of the users of the expression can
  // have this value converted.  This makes use of the map to avoid infinite
  // recursion.
  //
  for (Value::use_iterator It = I->use_begin(), E = I->use_end(); It != E; ++It)
    if (!OperandConvertibleToType(*It, I, Ty, CTMap, TD))
      return false;

  return true;
}
Ejemplo n.º 10
0
bool Aa::LowerGepPass::runOnFunction(Function &F)
{
  const llvm::Type *ptr_int_type = TD->getIntPtrType(F.getContext());

  for (Function::iterator bi = F.begin(), be = F.end(); bi != be; ++bi) {
    BasicBlock *bb = bi;

    BasicBlock::iterator ii = bb->begin();
    while (ii != bb->end()) {
      GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(ii);
      BasicBlock::iterator gi = ii++;
      if (!gep) {
	continue;
      }

      for (llvm::Value::use_iterator ui = gep->use_begin(), ue = gep->use_end();
           ui != ue; ++ui) {
        Use &u = ui.getUse();

        IOCode ioc = get_io_code(u);

        if (ioc == NOT_IO)
          continue;

        u.set(CastInst::CreatePointerCast(gep->getPointerOperand()
                                          , gep->getType()
                                          , "", gep));
      }

      assert(gep->hasIndices() && "GEP without indices??");
      llvm::Value *ptr = gep->getPointerOperand();
      const Type *ctype = ptr->getType();

      // deal with the base pointer first
      llvm::Value *base = gep->getPointerOperand();
      std::string base_name = gep->getNameStr() + ".base";
      llvm::Value *address = new PtrToIntInst(base, ptr_int_type, base_name + ".cast", gi);
      
      unsigned i = 0;
      for (User::op_iterator oi = gep->idx_begin(), oe = gep->idx_end();
	   oi != oe; ++oi, ++i) {
	llvm::Value *index = *oi;
	llvm::Value *offset = NULL;

	std::stringstream index_name;
	index_name << gep->getNameStr() << ".idx." << i;
	
	if (const SequentialType *qtype = dyn_cast<SequentialType>(ctype)) {
	  // multiply index by size of element

	  unsigned element_size = getTypePaddedSize(TD, qtype->getElementType());
	  const llvm::IntegerType *index_type = cast<IntegerType>(index->getType());
	  ConstantInt *cint = ConstantInt::get(index_type, element_size);
	  assert(cint && "uh oh!");
	  offset = BinaryOperator::Create(Instruction::Mul
					  , cint
					  , index
					  , index_name.str()
					  , gi);
	  ctype = qtype->getElementType();
	} else if (const StructType *stype = dyn_cast<StructType>(ctype)) {
	  // calculate offset into the struct

	  const StructLayout *layout = TD->getStructLayout(stype);
	  unsigned idx = cast<ConstantInt>(index)->getValue().getZExtValue();
	  unsigned struct_offset = layout->getElementOffset(idx);
	  offset = ConstantInt::get(ptr_int_type, struct_offset);
	  ctype = stype->getElementType(idx);
	} else
	  assert(false && "unhandled offset into composite type");
	
	// add offset to the address

	assert(address && "uh oh!");
	std::stringstream add_name;
	add_name << gep->getNameStr() << ".lvl." << i;
	
	if (offset->getType() != address->getType()) {
	  offset = CastInst::CreateIntegerCast(offset, address->getType()
					       , false, offset->getName() + ".resized"
					       , gi);
	}
	
	address = BinaryOperator::Create(Instruction::Add
					 , address, offset
					 , add_name.str(), gi);
      }

      if (address->getType() != ptr_int_type)
	address = CastInst::CreateIntegerCast(address, ptr_int_type
					      , false, address->getName() + ".final", gi);
      Instruction *new_ptr = new IntToPtrInst(address, gep->getType()
					  , gep->getName() + ".cast");
      ReplaceInstWithInst(bb->getInstList(), gi, new_ptr);
    }
  }

  return true;
}
Ejemplo n.º 11
0
//
// Methods: insertBadIndexing()
//
// Description:
//  This method modifieds GEP indexing expressions so that their indices are
//  (most likely) below the bounds of the object pointed to by the source
//  pointer.  It does this by modifying the first index to be -1.
//
// Return value:
//  true  - One or more changes were made to the program.
//  false - No changes were made to the program.
//
bool
FaultInjector::insertBadIndexing (Function & F) {
  // Worklist of allocation sites to rewrite
  std::vector<GetElementPtrInst *> WorkList;

  //
  // Find GEP instructions that index into an array.  Add these to the
  // worklist.
  //
  for (Function::iterator fI = F.begin(), fE = F.end(); fI != fE; ++fI) {
    BasicBlock & BB = *fI;
    for (BasicBlock::iterator I = BB.begin(), bE = BB.end(); I != bE; ++I) {
      if (GetElementPtrInst * GEP = dyn_cast<GetElementPtrInst>(I)) {
        // Skip if we should not insert a fault.
        if (!doFault()) continue;

        WorkList.push_back (GEP);
      }
    }
  }

  // Flag whether the program was modified
  bool modified = (WorkList.size() > 0);

  //
  // Iterator through the worklist and transform each GEP.
  //
  while (WorkList.size()) {
    GetElementPtrInst * GEP = WorkList.back();
    WorkList.pop_back();

    //
    // Print out where the fault will be inserted in the source code.
    //
    printSourceInfo ("Bad indexing", GEP);

    // The index arguments to the new GEP
    std::vector<Value *> args;

    //
    // Create a copy of the GEP's indices.
    //
    User::op_iterator i = GEP->idx_begin();
    if (i == GEP->idx_end()) continue;
    args.push_back (ConstantInt::get (Int32Type, INT_MAX, true));
    for (++i; i != GEP->idx_end(); ++i) {
      args.push_back (*i);
    }

    //
    // Create the new GEP instruction.
    //
    Value * Pointer = GEP->getPointerOperand();
    Twine name = GEP->getName() + "badindex";
    GetElementPtrInst * NewGEP = GetElementPtrInst::Create (Pointer,
                                                            args.begin(),
                                                            args.end(),
                                                            name,
                                                            GEP);
    GEP->replaceAllUsesWith (NewGEP);
    GEP->eraseFromParent();
    ++BadIndices;
  }

  return modified;
}