dsa算法(7)

1.3.3.2.2.2. GetElementPtrInst

LlvmIR有个有趣的地方:GlobalValue代表全局变量或函数的地址,而且它们是内存对象,总是通过地址来援引它们。正因为如此,一个全局对象的类型总是指向其内容的一个指针。在使用GetElementPtrInst指令时,记住这点很重要,因为这个指针必须首先被解除引用。例如,如果你有一个为24个int数组的GlobalVariable(GlobalValue的派生类),类型为[24×i32],那么该GlobalVariable是指向该数组的指针。虽然该数组第一个元素的地址与这个GlobalVariable的值相同,但它们具有不同的类型。这个GlobalVariable的类型是[24×i32],第一个元素的类型是i32。因为这样,访问一个全局值要求你首先使用GetElementPtrInst解除引用这个指针的引用,然后才可以访问其元素。

GraphBuilder::visitGetElementPtrInst方法为GetElementPtrInst指令(缩写为GEP)产生DSNode。在这个指令中,第一个参数是指向作为这个计算的基址的对象指针。

 

685    void GraphBuilder::visitGetElementPtrInst(User&GEP) {

686      //

687      // Ensure that theindexed pointer has a DSNode.

688      //

689      DSNodeHandle NodeH = getValueDest(GEP.getOperand(0));

690      if (NodeH.isNull())

691        NodeH = createNode();

692   

693      //

694      // There are a fewquick and easy cases to handle.  If theDSNode of the

695      // indexed pointeris already folded, then we know that the result of the

696      // GEP will havethe same offset into the same DSNode

697      // as the indexedpointer.

698      //

699   

700      if (!NodeH.isNull() &&

701         NodeH.getNode()->isNodeCompletelyFolded()) {

702        setDestTo(GEP,NodeH);

703        return;

704      }

 

注意,691行的createNode方法只返回DSNode对象的指针,因此这里会调用一次如下的DSNodeHandle的构造函数,绑定DSNode与DSNodeHandle。

 

63        DSNodeHandle(DSNode *n, unsigned offs = 0) :N(0), Offset(0) {

64          setTo(n,offs);

65        }

 

然后再调用DSNodeHandle的“=”操作符。

 

71        DSNodeHandle &operator=(const DSNodeHandle &H) {

71          if (&H == this) return *this;  // Don't set offset to 0 if self assigning.

71          DSNode *NN = H.getNode();  // Call getNode()before .Offset

71          setTo(NN,H.Offset);

71          return*this;

71        }

 

这样,700行的isNull测试必定返回false。如果这个对象已经被缩合(700~701行条件,类似于C中的类型void*),那么就不需要进一步的处理,只需在下面把代表该对象与这个GEP对象的DSNode简并起来。

 

353    void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) {

354      G.getNodeForValue(&V).mergeWith(NH);

355    }

 

如果该对象的DSNode没有被缩合,那么GEP指令的后续参数将指定目标域的索引,比如,上面提到的[24×i32]的数组,如果要获取其第3个元素,使用的GEP将是(假定数组变量是A,目标变量是B):

%B= getelementPtr [24×i32]* %A, i32 0, i32 2

其中,第一个索引总是针对对象的解除引用,以上例来说,索引0表示与A地址相同的[24×i32]的数组对象,索引1表示与A+1地址(即A的地址+sizeof(A))相同的[24×i32]的数组对象;而第二个索引则是数组元素的序号(对于struct,则是域的序号);如果结果的类型还是一个struct,则可以有第三个索引来标记目的对象的序号,以此类推。

 

GraphBuilder::visitGetElementPtrInst(续)

 

711      int Offset = 0;

712   

713      // FIXME: I am notsure if the code below is completely correct (especially

714      //        if we start doing fancy analysis onnon-constant array indices).

715      //        What if the array is indexed using alarger index than its declared

716      //        size? Does the LLVM verifier catch such issues?

717      //

718   

719      //

720      // Determine theoffset (in bytes) between the result of the GEP and the

721      // GEP's pointer operand.

722      //

723      // Note: All ofthese subscripts are indexing INTO the elements we have...

724      //

725      // FIXME: We can dobetter for array indexing.  First, if thearray index is

726      //        constant, we can determine how muchfarther we're moving the

727      //        pointer.  Second, we can try to use the results ofother analysis

728      //        passes (e.g., ScalarEvolution) to findmin/max values to do less

729      //        conservative type-folding.

730      //

731      for(gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP);

732           I != E; ++I)

 

731行的for循环开始遍历GEP余下的参数,并计算偏移。gep_type_begin与gep_type_end分别返回头尾的迭代器。94行的getScalarType,对非vector类型不做任何操作,返回this。

 

92        inlinegep_type_iterator gep_type_begin(const User &GEP) {

93          returngep_type_iterator::begin

94           (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1);

95        }

96        inlinegep_type_iterator gep_type_end(const User &GEP) {

97          returngep_type_iterator::end(GEP.op_end());

98        }

 

迭代器gep_type_iterator则是generic_gep_type_iterator对User::const_op_iterator(即constUser*)的具现(这是使用缺省模板参数的具现)。

 

83        typedefgeneric_gep_type_iterator<> gep_type_iterator;

 

generic_gep_type_iterator继承关系如下,它的基类是std::iterator,是一个前向迭代器。

 

22        template<typename ItTy = User::const_op_iterator>

23        classgeneric_gep_type_iterator

24          : publicstd::iterator<std::forward_iterator_tag, Type *, ptrdiff_t>

 

在下面36及42行,I.OpIt中OpIt的类型是模板参数ItTy,即迭代器的类型,而35及41行的I.CurTy中CurTy的类型则是Type*,显然begin方法设置CurTy指向GEP援引的对象,OpIt指向跟在对象后的索引。

 

33          staticgeneric_gep_type_iterator begin(Type *Ty,ItTy It) {

34            generic_gep_type_iterator I;

35            I.CurTy = Ty;

36            I.OpIt = It;

37            return I;

38          }

39          staticgeneric_gep_type_iterator end(ItTy It) {

40            generic_gep_type_iterator I;

41            I.CurTy = 0;

42            I.OpIt = It;

43            return I;

44          }

 

在for循环中的递增操作涉及以下的操作符。其中CompositeType是StructType的基类(llvm使用StructType表示struct/union/class),同时还是PointerType的基类。

 

68          generic_gep_type_iterator& operator++() {  // Preincrement

69            if (CompositeType *CT =dyn_cast<CompositeType>(CurTy)) {

70              CurTy = CT->getTypeAtIndex(getOperand());

71            } else {

72              CurTy = 0;

73            }

74            ++OpIt;

75            return*this;

76          }

 

78          generic_gep_type_iterator operator++(int) {// Postincrement

79            generic_gep_type_iterator tmp = *this;++*this; return tmp;

80          }

 

GEP余下的参数必须是整数。如果当前(子)对象是一个复合类型,把CurTy更新为当前索引参数所指定的子对象。70行的getOperand()直接返回迭代器指向的对象(即*OpIt),它是当前类型(CurTy指向)成员(域)的索引(通常是ConstantInt)。getTypeAtIndex返回指定索引位置的子对象类型。

 

631    Type *CompositeType::getTypeAtIndex(const Value *V) {

632      if (StructType *STy = dyn_cast<StructType>(this)){

633        unsigned Idx =

634         (unsigned)cast<Constant>(V)->getUniqueInteger().getZExtValue();

635        assert(indexValid(Idx)&& "Invalid structure index!");

636        returnSTy->getElementType(Idx);

637      }

 

对于ConstantInt,634行的getUniqueInteger仅仅是返回其值,getUniqueInteger主要是处理常量整数向量,636行则是返回在索引位置上成员的类型。注意,这个类型在上面70行设置给了CurTy,即当前处理的类型被更新为指定成员的类型,并且在74行递增迭代器。注意,这里的迭代器实际上是const User*,++使该指针指向下一个对象。这是因为在GEP中操作数存放在一个数组中(User的方法getOperand,op_end与op_begin都使用这个数组。这使得遍历能正确结束)。因此,这个++操作符的作用是按照索引的指示把迭代器的CurTy设置为指定的成员的类型(如果不是复合类型,则设置为0,因为大小已知),并把OpIt设置为GEP中的下一个索引参数。

 

GraphBuilder::visitGetElementPtrInst(续)

 

733        if (StructType *STy =dyn_cast<StructType>(*I)) {

734          // indexinginto a structure

735          // next indexmust be a constant

736          const ConstantInt* CUI =cast<ConstantInt>(I.getOperand());

737          int FieldNo = CUI->getSExtValue();

738          // incrementthe offset by the actual byte offset being accessed

739   

740          unsigned requiredSize =TD.getTypeAllocSize(STy) + NodeH.getOffset() + Offset;

741   

742          //

743          // Grow theDSNode size as needed.

744          //

745          if (!NodeH.getNode()->isArrayNode() ||NodeH.getNode()->getSize() <= 0){

746            if (requiredSize >NodeH.getNode()->getSize())

747              NodeH.getNode()->growSize(requiredSize);

748          }

749   

750          Offset +=(unsigned)TD.getStructLayout(STy)->getElementOffset(FieldNo);

751          if (TypeInferenceOptimize) {

752            if (ArrayType* AT =dyn_cast<ArrayType>(STy->getTypeAtIndex(FieldNo))) {

753              NodeH.getNode()->mergeTypeInfo(AT, NodeH.getOffset() +Offset);

754              if ((++I) == E) {

755                break;

756              }

757   

758              // Check ifwe are still indexing into an array.

759              // We onlyrecord the topmost array type of any nested array.

760              // Keepskipping indexes till we reach a non-array type.

761              // J is thetype of the next index.

762              //Uncomment the line below to get all the nested types.

763              gep_type_iterator J = I;

764              while(isa<ArrayType>(*(++J))) {

765                //      NodeH.getNode()->mergeTypeInfo(AT1,NodeH.getOffset() + Offset);

766                if((++I) == E) {

767                  break;

768                }

769                J = I;

770              }

771              if ((I) == E) {

772                break;

773              }

774            }

775          }

 

在733行,迭代器generic_gep_type_iterator把操作符“*”的定义重载为:

 

53          Type *operator*()const {

54            returnCurTy;

55          }

 

因此,这行检查当前处理的类型是否是struct/union/class。如果是,跟在后面的整数参数则是其中成员的索引,这个索引被提取到737行的FieldNo。而740行的NodeH是GEP对象的DSNodeHandle(在689行获得),其方法getOffset返回它在所援引的DSNode中的偏移(DSNodeHandle相当于指针,指向相关DSNode的指定偏移)。那么要容纳这个域,740行计算的requiredSize就是对象的最小尺寸。

745行的条件,对于数组而言,只有其大小小于0时才进行调整,在其它情况下,其DSNode中的Size就是其元素的大小。这样,requiredSize大于Size也是合理的。750行调整偏移,因为我们进入FieldNo所指定的子对象。

751行的TypeInferenceOptimize可以通过选项enable-type-inference-opts来激活类型推理优化(typeinference optimization)。在激活这个优化时,对这个StructType直接包含的数组调用下面的方法。

 

432    void DSNode::mergeTypeInfo(Type *NewTy, unsignedOffset) {

433      if (!NewTy || NewTy->isVoidTy()) return;

434      if (isCollapsedNode()) return;

435   

436      growSizeForType(NewTy,Offset);

437   

438      // Clang generatesloads and stores of struct types.

439      // %tmp12 = load%struct.demand* %retval, align 1

440   

441      // In such cases,merge type information for each struct field

442      // individually(atthe appropriate offset), instead of the

443      // struct type.

444      if(NewTy->isStructTy()) {

445        constDataLayout &TD = getParentGraph()->getDataLayout();

446        StructType *STy =cast<StructType>(NewTy);

447        constStructLayout *SL = TD.getStructLayout(cast<StructType>(STy));

448        unsigned count = 0;

449        for(Type::subtype_iteratorii = STy->element_begin(), ee = STy->element_end(); ii!= ee; ++ii,++count) {

450          unsigned FieldOffset =SL->getElementOffset(count);

451          mergeTypeInfo(*ii, Offset + FieldOffset);

452        }

453      } else {

454        TyMap[Offset] = getParentGraph()->getTypeSS().getOrCreate(TyMap[Offset],NewTy);

455      }

456   

457      assert(TyMap[Offset]);

458    }

 

436行的growSizeForType根据在偏移Offset处出现的类型NewTy来调整这个DSNode的尺寸。对于数组节点,其DSNode中的Size是其元素的大小,因此,Offset要对这个Size取模,更新为相对于某个元素的偏移。

 

410    void DSNode::growSizeForType(Type *NewTy, unsignedOffset) {

411   

412      if (!NewTy || NewTy->isVoidTy()) return;

413   

414      if (isCollapsedNode()) return;

415      if (isArrayNode() && getSize() >0) {

416        Offset %= getSize();

417      }

418      constDataLayout &TD = getParentGraph()->getDataLayout();

419      if (Offset + TD.getTypeAllocSize(NewTy) >=getSize())

420        growSize(Offset +TD.getTypeAllocSize(NewTy));

421   

422    }

 

在上面的DSNode::mergeTypeInfo函数中,449行的循环遍历指定的StructType所包含的类型,并对该类型递归调用这个DSNode::mergeTypeInfo函数(注意新的偏移)。递归的最终结果是在454行,当前DSNode节点的TyMap在指定偏移位置记录这个类型。

回到GraphBuilder::visitGetElementPtrInst对StructType处理。对于连续嵌套的、更深的ArrayType,目前的代码(764行的while循环)只是跳过,不做处理(也就避开了下面对它们的处理)。

 

GraphBuilder::visitGetElementPtrInst(续)

 

776        } else if (ArrayType *ATy =dyn_cast<ArrayType>(*I)) {

777          // indexinginto an array.

778          NodeH.getNode()->setArrayMarker();

779          Type *CurTy = ATy->getElementType();

780   

781          //

782          // Ensure thatthe DSNode's size is large enough to contain one

783          // element ofthe type to which the pointer points.

784          //

785          if (!isa<ArrayType>(CurTy)&& NodeH.getNode()->getSize() <= 0) {

786            NodeH.getNode()->growSize(TD.getTypeAllocSize(CurTy));

787          } else if(isa<ArrayType>(CurTy)&& NodeH.getNode()->getSize() <= 0){

788            Type *ETy =(cast<ArrayType>(CurTy))->getElementType();

789            while(isa<ArrayType>(ETy)){

790              ETy = (cast<ArrayType>(ETy))->getElementType();

791            }

792           NodeH.getNode()->growSize(TD.getTypeAllocSize(ETy));

793          }

794   

795          // Find if theDSNode belongs to the array

796          // If not fold.

797          if((NodeH.getOffset() || Offset != 0)

798             || (!isa<ArrayType>(CurTy)

799                 &&(NodeH.getNode()->getSize() != TD.getTypeAllocSize(CurTy)))) {

800            NodeH.getNode()->foldNodeCompletely();

801            NodeH.getNode();

802            Offset = 0;

803            break;

804          }

 

如果成员的类型是数组,把包含该成员的DSNode标记为数组节点,并获取其元素的类型。如果元素的类型还是数组,那么继续寻找其元素,直到元素不是数组,因为数组类型的DSNode的Size是其非数组类型元素的类型大小。797行则是测试是否需要缩合该对象的DSNode节点。如果该数组不是在GetElementPtrInst作用的内存对象的偏移0处(797行第1个条件),或者该内存对象在另一个内存对象的非0偏移处(797行第2个条件),或者对于一维数组,该内存对象的DSNode还代表另一个大小不同的对象(因为786及796行只有在DSNode的大小不大于0时才执行),都要缩合。既然已经缩为一个大小为1的节点,就无需继续处理,从803行处结束731行的for循环。

 

GraphBuilder::visitGetElementPtrInst(续)

 

805        } else if (constPointerType *PtrTy = dyn_cast<PointerType>(*I)) {

806          // Get the typepointed to by the pointer

807          Type *CurTy = PtrTy->getElementType();

808   

809          //

810          // Some LLVMtransforms lower structure indexing into byte-level

811          //indexing.  Try to recognize forms of thathere.

812          //

813          Type * Int8Type  = Type::getInt8Ty(CurTy->getContext());

814          ConstantInt * IS =dyn_cast<ConstantInt>(I.getOperand());

815          if (IS &&

816              (NodeH.getOffset() == 0) &&

817             (!(NodeH.getNode()->isArrayNode())) &&

818              (CurTy == Int8Type)) {

819            // Calculatethe offset of the field

820            Offset += IS->getSExtValue() *TD.getTypeAllocSize (Int8Type);

821   

822            //

823            // Grow theDSNode size as needed.

824            //

825            unsigned requiredSize = Offset +TD.getTypeAllocSize (Int8Type);

826            if (NodeH.getNode()->getSize() <=requiredSize){

827              NodeH.getNode()->growSize(requiredSize);

828            }

829   

830            // Add in theoffset calculated...

831            NodeH.setOffset(NodeH.getOffset()+Offset);

832   

833            // Check theoffset

834            DSNode *N = NodeH.getNode();

835            if (N) N->checkOffsetFoldIfNeeded(NodeH.getOffset());

836   

837            // NodeH isnow the pointer we want to GEP to be...

838            setDestTo(GEP,NodeH);

839            return;

840          }

 

对于指针类型的成员,首先检查它是否为字节指针加常量索引的形式。807行获取指针指向对象的类型,814行的getOperand得到在该指针指向对象内的常量偏移值。这其实就是char*/unsigned char*,810~811行注释说到,某些llvm转换会把struct索引变形为字节索引,这段代码就是处理这种情形,825~831行相应地调整偏移及DSNode的大小。

我们知道DSNodeHandle相当于指针,它是DSNode+Offset的形式,上面我们计算出了Offset,但这个Offset可能会超出对应DSNode的大小,这时需要缩合这个DSNode节点,因为我们无法处理这些访问。

 

727    void DSNode::checkOffsetFoldIfNeeded(intOffset) {

728      if (!isNodeCompletelyFolded() &&

729          (Size != 0 || Offset != 0) &&

730          !isForwarding()) {

731        if ((Offset >= (int)Size) || Offset <0) {

732          // Accessingoffsets out of node size range

733          // This is seenin the "magic" struct in named (from bind), where the

734          // fourth fieldis an array of length 0, presumably used to create struct

735          // instances ofdifferent sizes

736          // Moregenerally this happens whenever code indexes past the end

737          // of a structtype.  We don't model this, so fold!

738   

739          // Collapse thenode since its size is now variable

740          foldNodeCompletely();

741   

742          ++NumFoldsOOBOffset;

743        }

744      }

745    }

 

如果不是字节指针加索引的形式,继续往下。如果子对象指针的索引不是常量或不是0(850~851行条件),就把对应的内存对象(DSNode)处理做数组(但不是数组类型!),比如*ptr+5这样。

 

GraphBuilder::visitGetElementPtrInst(续)

 

842          //

843          // Unless we'readvancing the pointer by zero bytes via array indexing,

844          // fold thenode (i.e., mark it type-unknown) and indicate that we're

845          // indexingzero bytes into the object (because all fields are aliased).

846          //

847          // Note that we break out of the loop if we fold thenode.  Once

848          // something isfolded, all values within it are considered to alias.

849          //

850          if (!isa<Constant>(I.getOperand())||

851             !cast<Constant>(I.getOperand())->isNullValue()) {

852   

853            //

854            // Treat thememory object (DSNode) as an array.

855            //

856            NodeH.getNode()->setArrayMarker();

857   

858            //

859            // Ensurethat the DSNode's size is large enough to contain one

860            // element ofthe type to which the pointer points.

861            //

862            if (!isa<ArrayType>(CurTy)&& NodeH.getNode()->getSize() <= 0){

863             NodeH.getNode()->growSize(TD.getTypeAllocSize(CurTy));

864            } else if (isa<ArrayType>(CurTy)&& NodeH.getNode()->getSize() <= 0){

865              Type *ETy =(cast<ArrayType>(CurTy))->getElementType();

866              while(isa<ArrayType>(ETy)) {

867                ETy =(cast<ArrayType>(ETy))->getElementType();

868              }

869              NodeH.getNode()->growSize(TD.getTypeAllocSize(ETy));

870            }

871   

872            //

873            // Fold theDSNode if we're indexing into it in a type-incompatible

874            //manner.  That can occur if:

875            //  1) The DSNode represents a pointer into theobject at a non-zero

876            //     offset.

877            //  2) The offset of the pointer is alreadynon-zero.

878            //  3) The size of the array element does notmatch the size into which

879            //     the pointer indexing is indexing.

880            //

881            if (NodeH.getOffset() || Offset != 0 ||

882                (!isa<ArrayType>(CurTy)&&

883                 (NodeH.getNode()->getSize() !=TD.getTypeAllocSize(CurTy)))) {

884              NodeH.getNode()->foldNodeCompletely();

885              NodeH.getNode();

886              Offset = 0;

887              break;

888            }

889          }

890        }

 

这里的处理与前面看到的与数组的处理类似。注意,如果节点最后缩合了,那么856行设置的数组标记将被清除。

 

GraphBuilder::visitGetElementPtrInst(续)

 

892      // Add in theoffset calculated...

893      NodeH.setOffset(NodeH.getOffset()+Offset);

894   

895      // Check the offset

896      DSNode *N = NodeH.getNode();

897      if (N) N->checkOffsetFoldIfNeeded(NodeH.getOffset());

898   

899      // NodeH is now thepointer we want to GEP to be...

900      setDestTo(GEP,NodeH);

901    }

 

在处理完所有的域后(可能发生了缩合),更新偏移的数据,因为我们已经到达目标元素了。同样需要检查这个偏移是否已经超出节点的大小。最后,注意900行的setDestTo。它把GEP所带的DSNodeHandle与NodeH进行简并,因为这条GEP指令可能在多处使用,简并使得这些引用被汇集起来。同时,如果出现不兼容的情形,会自动进行安全的缩合。

1.3.3.2.2.3. 其他

UndefValue对应于llvm IR中的undef,这又类似于C++标准中的undefinedbehavor。UndefValue可以用于任何适用常量的地方,表示该值可能没是指定的比特形式。它向编译器表示不管它使用了哪个值,这个程序是定义良好的。这使得编译器有更大的优化自由度。因此,在这里我们无需考虑它。

 

GraphBuilder::getValueDest(续)

 

293        } else if (isa<UndefValue>(C)) {

294          G.eraseNodeForValue(V);

295          return 0;

296        } else if (isa<GlobalAlias>(C)) {

297          // XXX: Needmore investigation

298          // According toAndrew, DSA is broken on global aliasing, since it does

299          // not handlethe aliases of parameters correctly. Here is only a quick

300          // fix for somespecial cases.

301          NH= getValueDest(cast<GlobalAlias>(C)->getAliasee());

302          returnNH;

303        } else if (isa<BlockAddress>(C)) {

304          //

305          // FIXME: Thismay not be quite right; we should probably add a

306          // BlockAddressflag to the DSNode instead of using the unknown flag.

307          //

308          N = createNode();

309          N->setUnknownMarker();

310        } else if (isa<ConstantStruct>(C) ||isa<ConstantArray>(C) ||

311                  isa<ConstantDataSequential>(C) || isa<ConstantDataArray>(C)||

312                  isa<ConstantDataVector>(C)) {

313          // Treat thesethe same way we treat global initializers

314          N = createNode();

315          NH.mergeWith(N);

316          MergeConstantInitIntoNode(NH,C->getType(), C);

317        } else {

318          errs() << "Unknown constant:" << *C << "\n";

319          assert(0&& "Unknown constant type!");

320        }

321        N = createNode();// just create a shadow node

322      } else {

323        // Otherwise justcreate a shadow node

324        N = createNode();

325      }

326   

327      NH.setTo(N,0);      //Remember that we are pointing to it...

328      return NH;

329    }

 

310行的ConstantStruct,ConstantArray,ConstantDataSequential,ConstantDataArray及ConstantDataVector都是llvm IR用来表示常量的构造。在315行,NH.isNull一定是true,否则在前面255行就应该退出这个函数,因此,mergeWith只是把N赋给了NH。最后,还要通过下面的函数把这个常量的信息整合入这些DSNode、DSNodeHandle节点。

 

1253  void

1254  GraphBuilder::MergeConstantInitIntoNode(DSNodeHandle &NH,

1255                                          Type*Ty,

1256                                         Constant *C) {

1257    //

1258    // Ensure atype-record exists...

1259    //

1260    DSNode *NHN = NH.getNode();

1261    //NHN->mergeTypeInfo(Ty,NH.getOffset());

1262 

1263    //

1264    // If we've foundsomething of pointer type, create or find its DSNode and

1265    // make a link from the specified DSNode tothe new DSNode describing the

1266    // pointer we'vejust found.

1267    //

1268    if (isa<PointerType>(Ty)) {

1269      NHN->mergeTypeInfo(Ty,NH.getOffset());

1270      NH.addEdgeTo(getValueDest(C));

1271      return;

1272    }

 

我们在前面314行通过createNode创建这些节点时没有提供类型信息。如果常量C是一个指针类型,在1269行把这个类型信息(Type*)记录到节点中,这需要mergeTypeInfo,因为这个类型信息最终是要保存在GlobalsGraph的TypeSS域中。注意,在1270行C的类型是Constant*(是公共基类),这样它将满足GraphBuilder::getValueDest 273行处的条件,不会陷入无穷递归(llvm自己的类型转换系统允许它们到Constant的转换)。

 

GraphBuilder::MergeConstantInitIntoNode(续)

 

1274    //

1275    // If the type ofthe object (array element, structure field, etc.) is an

1276    // integer orfloating point type, then just ignore it. It has no DSNode.

1277    //

1278    if (Ty->isIntOrIntVectorTy() ||Ty->isFPOrFPVectorTy()) return;

1279 

1280    //

1281    // Handle aggregateconstants.

1282    //

1283    if (ConstantArray *CA =dyn_cast<ConstantArray>(C)) {

1284      //

1285      // For an array,we don't worry about different elements pointing to

1286      // differentobjects; we essentially pretend that all array elements alias.

1287      //

1288      Type * ElementType =cast<ArrayType>(Ty)->getElementType();

1289      for(unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {

1290        Constant * ConstElement = cast<Constant>(CA->getOperand(i));

1291        MergeConstantInitIntoNode(NH,ElementType, ConstElement);

1292      }

1293    } else if (ConstantStruct *CS =dyn_cast<ConstantStruct>(C)) {

1294      //

1295      // For astructure, we need to merge each element of the constant structure

1296      // into thespecified DSNode.  However, we must alsohandle structures that

1297      // end with azero-length array ([0 x sbyte]); this is a common C idiom

1298      // that continuesto plague the world.

1299      //

1300     //NHN->mergeTypeInfo(Ty,NH.getOffset());

1301 

1302      constStructLayout *SL = TD.getStructLayout(cast<StructType>(Ty));

1303 

1304      for(unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {

1305        DSNode *NHN = NH.getNode();

1306        if (SL->getElementOffset(i) <SL->getSizeInBytes()) {

1307          //

1308          // Get thetype and constant value of this particular element of the

1309          // constantstructure.

1310          //

1311          Type * ElementType =cast<StructType>(Ty)->getElementType(i);

1312          Constant * ConstElement =cast<Constant>(CS->getOperand(i));

1313 

1314          //

1315          // Get theoffset (in bytes) into the memory object that we're

1316          // analyzing.

1317          //

1318          unsigned offset =NH.getOffset()+(unsigned)SL->getElementOffset(i);

1319          NHN->mergeTypeInfo(ElementType,offset);

1320          //

1321          // Create anew DSNodeHandle.  This DSNodeHandle willpoint to the same

1322          // DSNode asthe one we're constructing for our caller; however, it

1323          // will pointinto a different offset into that DSNode.

1324          //

1325          DSNodeHandle NewNH (NHN, offset);

1326          assert((NHN->isNodeCompletelyFolded() || (NewNH.getOffset() == offset))

1327                  && "Need to resizeDSNode!");

1328 

1329          //

1330          //Recursively merge in this element of the constant struture into the

1331          // DSNode.

1332          //

1333          MergeConstantInitIntoNode(NewNH,ElementType, ConstElement);

1334        } else if (SL->getElementOffset(i) ==SL->getSizeInBytes()) {

1335          //

1336          // If this isone of those cute structures that ends with a zero-length

1337          // array, justfold the DSNode now and get it over with.

1338          //

1339          DEBUG(errs() << "Zero sizeelement at end of struct\n" );

1340          NHN->foldNodeCompletely();

1341        } else {

1342          assert(0&& "type was smaller than offsets of struct layoutindicate");

1343        }

1344      }

1345    } else if(isa<ConstantAggregateZero>(C) || isa<UndefValue>(C)) {

1346      //

1347      // Undefinedvalues and NULL pointers have no DSNodes, so they do nothing.

1348      //

1349    } else if(isa<ConstantDataSequential>(C)) {

1350      //

1351      //ConstantDataSequential's are arrays of integers or floats, so they

1352      // have noDSNodes.  Nothing to do here.

1353      //

1354    } else {

1355      assert(0&& "Unknown constant type!");

1356    }

1357  }

 

对于常量数组,因为元素类型都是一样的,我们把所有元素都处理做互为别名。对于常量结构,也是按域逐个处理。注意,常量结构体中不允许以长度为0的数组结尾。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值