|  | //===- TransformInternals.cpp - Implement shared functions for transforms -===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file was developed by the LLVM research group and is distributed under | 
|  | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | //  This file defines shared functions used by the different components of the | 
|  | //  Transforms library. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "TransformInternals.h" | 
|  | #include "llvm/Type.h" | 
|  | #include "llvm/Analysis/Expressions.h" | 
|  | #include "llvm/Function.h" | 
|  | #include "llvm/Instructions.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | static const Type *getStructOffsetStep(const StructType *STy, uint64_t &Offset, | 
|  | std::vector<Value*> &Indices, | 
|  | const TargetData &TD) { | 
|  | assert(Offset < TD.getTypeSize(STy) && "Offset not in composite!"); | 
|  | const StructLayout *SL = TD.getStructLayout(STy); | 
|  |  | 
|  | // This loop terminates always on a 0 <= i < MemberOffsets.size() | 
|  | unsigned i; | 
|  | for (i = 0; i < SL->MemberOffsets.size()-1; ++i) | 
|  | if (Offset >= SL->MemberOffsets[i] && Offset < SL->MemberOffsets[i+1]) | 
|  | break; | 
|  |  | 
|  | assert(Offset >= SL->MemberOffsets[i] && | 
|  | (i == SL->MemberOffsets.size()-1 || Offset < SL->MemberOffsets[i+1])); | 
|  |  | 
|  | // Make sure to save the current index... | 
|  | Indices.push_back(ConstantUInt::get(Type::UIntTy, i)); | 
|  | Offset = SL->MemberOffsets[i]; | 
|  | return STy->getContainedType(i); | 
|  | } | 
|  |  | 
|  |  | 
|  | // getStructOffsetType - Return a vector of offsets that are to be used to index | 
|  | // into the specified struct type to get as close as possible to index as we | 
|  | // can.  Note that it is possible that we cannot get exactly to Offset, in which | 
|  | // case we update offset to be the offset we actually obtained.  The resultant | 
|  | // leaf type is returned. | 
|  | // | 
|  | // If StopEarly is set to true (the default), the first object with the | 
|  | // specified type is returned, even if it is a struct type itself.  In this | 
|  | // case, this routine will not drill down to the leaf type.  Set StopEarly to | 
|  | // false if you want a leaf | 
|  | // | 
|  | const Type *llvm::getStructOffsetType(const Type *Ty, unsigned &Offset, | 
|  | std::vector<Value*> &Indices, | 
|  | const TargetData &TD, bool StopEarly) { | 
|  | if (Offset == 0 && StopEarly && !Indices.empty()) | 
|  | return Ty;    // Return the leaf type | 
|  |  | 
|  | uint64_t ThisOffset; | 
|  | const Type *NextType; | 
|  | if (const StructType *STy = dyn_cast<StructType>(Ty)) { | 
|  | if (STy->getNumElements()) { | 
|  | Offset = 0; | 
|  | return STy; | 
|  | } | 
|  |  | 
|  | ThisOffset = Offset; | 
|  | NextType = getStructOffsetStep(STy, ThisOffset, Indices, TD); | 
|  | } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { | 
|  | assert(Offset == 0 || Offset < TD.getTypeSize(ATy) && | 
|  | "Offset not in composite!"); | 
|  |  | 
|  | NextType = ATy->getElementType(); | 
|  | unsigned ChildSize = TD.getTypeSize(NextType); | 
|  | if (ConstantSInt::isValueValidForType(Type::IntTy, Offset/ChildSize)) | 
|  | Indices.push_back(ConstantSInt::get(Type::IntTy, Offset/ChildSize)); | 
|  | else | 
|  | Indices.push_back(ConstantSInt::get(Type::LongTy, Offset/ChildSize)); | 
|  | ThisOffset = (Offset/ChildSize)*ChildSize; | 
|  | } else { | 
|  | Offset = 0;   // Return the offset that we were able to achieve | 
|  | return Ty;    // Return the leaf type | 
|  | } | 
|  |  | 
|  | unsigned SubOffs = Offset - ThisOffset; | 
|  | const Type *LeafTy = getStructOffsetType(NextType, SubOffs, | 
|  | Indices, TD, StopEarly); | 
|  | Offset = ThisOffset + SubOffs; | 
|  | return LeafTy; | 
|  | } | 
|  |  | 
|  | // ConvertibleToGEP - This function returns true if the specified value V is | 
|  | // a valid index into a pointer of type Ty.  If it is valid, Idx is filled in | 
|  | // with the values that would be appropriate to make this a getelementptr | 
|  | // instruction.  The type returned is the root type that the GEP would point to | 
|  | // | 
|  | const Type *llvm::ConvertibleToGEP(const Type *Ty, Value *OffsetVal, | 
|  | std::vector<Value*> &Indices, | 
|  | const TargetData &TD, | 
|  | BasicBlock::iterator *BI) { | 
|  | return 0; | 
|  | } | 
|  |  |