示例#1
0
文件: Local.cpp 项目: brills/pfpa
void GraphBuilder::visitGetElementPtrInst(User &GEP) {
  //
  // Ensure that the indexed pointer has a DSNode.
  //
  DSNodeHandle Value = getValueDest(GEP.getOperand(0));
  if (Value.isNull())
    Value = createNode();

  //
  // There are a few quick and easy cases to handle.  If  the DSNode of the 
  // indexed pointer is already folded, then we know that the result of the 
  // GEP will have the same offset into the same DSNode 
  // as the indexed pointer.
  //

  if (!Value.isNull() &&
      Value.getNode()->isNodeCompletelyFolded()) {
    setDestTo(GEP, Value);
    return;
  }

  //
  // Okay, no easy way out.  Calculate the offset into the object being
  // indexed.
  //

  int Offset = 0;

  // FIXME: I am not sure if the code below is completely correct (especially
  //        if we start doing fancy analysis on non-constant array indices).
  //        What if the array is indexed using a larger index than its declared
  //        size?  Does the LLVM verifier catch such issues?
  //

  //
  // Determine the offset (in bytes) between the result of the GEP and the
  // GEP's pointer operand.
  //
  // Note: All of these subscripts are indexing INTO the elements we have...
  //
  // FIXME: We can do better for array indexing.  First, if the array index is
  //        constant, we can determine how much farther we're moving the
  //        pointer.  Second, we can try to use the results of other analysis
  //        passes (e.g., ScalarEvolution) to find min/max values to do less
  //        conservative type-folding.
  //
  for (gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP);
       I != E; ++I)
    if (StructType *STy = dyn_cast<StructType>(*I)) {
      // indexing into a structure
      // next index must be a constant
      const ConstantInt* CUI = cast<ConstantInt>(I.getOperand());
      int FieldNo = CUI->getSExtValue();
      // increment the offset by the actual byte offset being accessed

      unsigned requiredSize = TD.getTypeAllocSize(STy) + Value.getOffset() + Offset;
      if(!Value.getNode()->isArrayNode() || Value.getNode()->getSize() <= 0){
        if (requiredSize > Value.getNode()->getSize())
          Value.getNode()->growSize(requiredSize);
      }
      Offset += (unsigned)TD.getStructLayout(STy)->getElementOffset(FieldNo);
      if(TypeInferenceOptimize) {
        if(ArrayType* AT = dyn_cast<ArrayType>(STy->getTypeAtIndex(FieldNo))) {
          Value.getNode()->mergeTypeInfo(AT, Value.getOffset() + Offset);
          if((++I) == E) {
            break;
          }
          // Check if we are still indexing into an array.
          // We only record the topmost array type of any nested array.
          // Keep skipping indexes till we reach a non-array type.
          // J is the type of the next index.
          // Uncomment the line below to get all the nested types.
          gep_type_iterator J = I;
          while(isa<ArrayType>(*(++J))) {
            //      Value.getNode()->mergeTypeInfo(AT1, Value.getOffset() + Offset);
            if((++I) == E) {
              break;
            }
            J = I;
          }
          if((I) == E) {
            break;
          }
        }
      }
    } else if(ArrayType *ATy = dyn_cast<ArrayType>(*I)) {
      // indexing into an array.
      Value.getNode()->setArrayMarker();
      Type *CurTy = ATy->getElementType();

      if(!isa<ArrayType>(CurTy) &&
         Value.getNode()->getSize() <= 0) {
        Value.getNode()->growSize(TD.getTypeAllocSize(CurTy));
      } else if(isa<ArrayType>(CurTy) && Value.getNode()->getSize() <= 0){
        Type *ETy = (cast<ArrayType>(CurTy))->getElementType();
        while(isa<ArrayType>(ETy)) {
          ETy = (cast<ArrayType>(ETy))->getElementType();
        }
        Value.getNode()->growSize(TD.getTypeAllocSize(ETy));
      }

      // Find if the DSNode belongs to the array
      // If not fold.
      if((Value.getOffset() || Offset != 0)
         || (!isa<ArrayType>(CurTy)
             && (Value.getNode()->getSize() != TD.getTypeAllocSize(CurTy)))) {
        Value.getNode()->foldNodeCompletely();
        Value.getNode();
        Offset = 0;
        break;
      }
    } else if (const PointerType *PtrTy = dyn_cast<PointerType>(*I)) {
      Type *CurTy = PtrTy->getElementType();

      //
      // Unless we're advancing the pointer by zero bytes via array indexing,
      // fold the node (i.e., mark it type-unknown) and indicate that we're
      // indexing zero bytes into the object.
      //
      // Note that we break out of the loop if we fold the node.  Once
      // something is folded, all values within it are considered to alias.
      //

      if (!isa<Constant>(I.getOperand()) ||
          !cast<Constant>(I.getOperand())->isNullValue()) {
        Value.getNode()->setArrayMarker();


        if(!isa<ArrayType>(CurTy) && Value.getNode()->getSize() <= 0){
          Value.getNode()->growSize(TD.getTypeAllocSize(CurTy));
        } else if(isa<ArrayType>(CurTy) && Value.getNode()->getSize() <= 0){
          Type *ETy = (cast<ArrayType>(CurTy))->getElementType();
          while(isa<ArrayType>(ETy)) {
            ETy = (cast<ArrayType>(ETy))->getElementType();
          }
          Value.getNode()->growSize(TD.getTypeAllocSize(ETy));
        }
        if(Value.getOffset() || Offset != 0
           || (!isa<ArrayType>(CurTy)
               && (Value.getNode()->getSize() != TD.getTypeAllocSize(CurTy)))) {
          Value.getNode()->foldNodeCompletely();
          Value.getNode();
          Offset = 0;
          break;
        }
      }
    }

  // Add in the offset calculated...
  Value.setOffset(Value.getOffset()+Offset);

  // Check the offset
  DSNode *N = Value.getNode();
  if (N) N->checkOffsetFoldIfNeeded(Value.getOffset());

  // Value is now the pointer we want to GEP to be...
  setDestTo(GEP, Value);
}