LLVM API Documentation
00001 //===- TransformInternals.cpp - Implement shared functions for transforms -===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines shared functions used by the different components of the 00011 // Transforms library. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "TransformInternals.h" 00016 #include "llvm/Type.h" 00017 #include "llvm/Function.h" 00018 #include "llvm/Instructions.h" 00019 using namespace llvm; 00020 00021 static const Type *getStructOffsetStep(const StructType *STy, uint64_t &Offset, 00022 std::vector<Value*> &Indices, 00023 const TargetData &TD) { 00024 assert(Offset < TD.getTypeSize(STy) && "Offset not in composite!"); 00025 const StructLayout *SL = TD.getStructLayout(STy); 00026 00027 // This loop terminates always on a 0 <= i < MemberOffsets.size() 00028 unsigned i; 00029 for (i = 0; i < SL->MemberOffsets.size()-1; ++i) 00030 if (Offset >= SL->MemberOffsets[i] && Offset < SL->MemberOffsets[i+1]) 00031 break; 00032 00033 assert(Offset >= SL->MemberOffsets[i] && 00034 (i == SL->MemberOffsets.size()-1 || Offset < SL->MemberOffsets[i+1])); 00035 00036 // Make sure to save the current index... 00037 Indices.push_back(ConstantUInt::get(Type::UIntTy, i)); 00038 Offset = SL->MemberOffsets[i]; 00039 return STy->getContainedType(i); 00040 } 00041 00042 00043 // getStructOffsetType - Return a vector of offsets that are to be used to index 00044 // into the specified struct type to get as close as possible to index as we 00045 // can. Note that it is possible that we cannot get exactly to Offset, in which 00046 // case we update offset to be the offset we actually obtained. The resultant 00047 // leaf type is returned. 00048 // 00049 // If StopEarly is set to true (the default), the first object with the 00050 // specified type is returned, even if it is a struct type itself. In this 00051 // case, this routine will not drill down to the leaf type. Set StopEarly to 00052 // false if you want a leaf 00053 // 00054 const Type *llvm::getStructOffsetType(const Type *Ty, unsigned &Offset, 00055 std::vector<Value*> &Indices, 00056 const TargetData &TD, bool StopEarly) { 00057 if (Offset == 0 && StopEarly && !Indices.empty()) 00058 return Ty; // Return the leaf type 00059 00060 uint64_t ThisOffset; 00061 const Type *NextType; 00062 if (const StructType *STy = dyn_cast<StructType>(Ty)) { 00063 if (STy->getNumElements()) { 00064 Offset = 0; 00065 return STy; 00066 } 00067 00068 ThisOffset = Offset; 00069 NextType = getStructOffsetStep(STy, ThisOffset, Indices, TD); 00070 } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { 00071 assert(Offset == 0 || Offset < TD.getTypeSize(ATy) && 00072 "Offset not in composite!"); 00073 00074 NextType = ATy->getElementType(); 00075 unsigned ChildSize = (unsigned)TD.getTypeSize(NextType); 00076 if (ConstantSInt::isValueValidForType(Type::IntTy, Offset/ChildSize)) 00077 Indices.push_back(ConstantSInt::get(Type::IntTy, Offset/ChildSize)); 00078 else 00079 Indices.push_back(ConstantSInt::get(Type::LongTy, Offset/ChildSize)); 00080 ThisOffset = (Offset/ChildSize)*ChildSize; 00081 } else { 00082 Offset = 0; // Return the offset that we were able to achieve 00083 return Ty; // Return the leaf type 00084 } 00085 00086 unsigned SubOffs = unsigned(Offset - ThisOffset); 00087 const Type *LeafTy = getStructOffsetType(NextType, SubOffs, 00088 Indices, TD, StopEarly); 00089 Offset = unsigned(ThisOffset + SubOffs); 00090 return LeafTy; 00091 }