LLVM API Documentation
00001 //===-- TargetData.cpp - Data size & alignment routines --------------------==// 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 target properties related to datatype size/offset/alignment 00011 // information. 00012 // 00013 // This structure should be created once, filled in if the defaults are not 00014 // correct and then passed around by const&. None of the members functions 00015 // require modification to the object. 00016 // 00017 //===----------------------------------------------------------------------===// 00018 00019 #include "llvm/Target/TargetData.h" 00020 #include "llvm/Module.h" 00021 #include "llvm/DerivedTypes.h" 00022 #include "llvm/Constants.h" 00023 #include "llvm/Support/GetElementPtrTypeIterator.h" 00024 #include "llvm/Support/MathExtras.h" 00025 using namespace llvm; 00026 00027 // Handle the Pass registration stuff necessary to use TargetData's. 00028 namespace { 00029 // Register the default SparcV9 implementation... 00030 RegisterPass<TargetData> X("targetdata", "Target Data Layout"); 00031 } 00032 00033 static inline void getTypeInfo(const Type *Ty, const TargetData *TD, 00034 uint64_t &Size, unsigned char &Alignment); 00035 00036 //===----------------------------------------------------------------------===// 00037 // Support for StructLayout 00038 //===----------------------------------------------------------------------===// 00039 00040 StructLayout::StructLayout(const StructType *ST, const TargetData &TD) { 00041 StructAlignment = 0; 00042 StructSize = 0; 00043 00044 // Loop over each of the elements, placing them in memory... 00045 for (StructType::element_iterator TI = ST->element_begin(), 00046 TE = ST->element_end(); TI != TE; ++TI) { 00047 const Type *Ty = *TI; 00048 unsigned char A; 00049 unsigned TyAlign; 00050 uint64_t TySize; 00051 getTypeInfo(Ty, &TD, TySize, A); 00052 TyAlign = A; 00053 00054 // Add padding if necessary to make the data element aligned properly... 00055 if (StructSize % TyAlign != 0) 00056 StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding... 00057 00058 // Keep track of maximum alignment constraint 00059 StructAlignment = std::max(TyAlign, StructAlignment); 00060 00061 MemberOffsets.push_back(StructSize); 00062 StructSize += TySize; // Consume space for this data item 00063 } 00064 00065 // Empty structures have alignment of 1 byte. 00066 if (StructAlignment == 0) StructAlignment = 1; 00067 00068 // Add padding to the end of the struct so that it could be put in an array 00069 // and all array elements would be aligned correctly. 00070 if (StructSize % StructAlignment != 0) 00071 StructSize = (StructSize/StructAlignment + 1) * StructAlignment; 00072 } 00073 00074 //===----------------------------------------------------------------------===// 00075 // TargetData Class Implementation 00076 //===----------------------------------------------------------------------===// 00077 00078 TargetData::TargetData(const std::string &TargetName, 00079 bool isLittleEndian, unsigned char PtrSize, 00080 unsigned char PtrAl, unsigned char DoubleAl, 00081 unsigned char FloatAl, unsigned char LongAl, 00082 unsigned char IntAl, unsigned char ShortAl, 00083 unsigned char ByteAl, unsigned char BoolAl) { 00084 00085 // If this assert triggers, a pass "required" TargetData information, but the 00086 // top level tool did not provide one for it. We do not want to default 00087 // construct, or else we might end up using a bad endianness or pointer size! 00088 // 00089 assert(!TargetName.empty() && 00090 "ERROR: Tool did not specify a target data to use!"); 00091 00092 LittleEndian = isLittleEndian; 00093 PointerSize = PtrSize; 00094 PointerAlignment = PtrAl; 00095 DoubleAlignment = DoubleAl; 00096 FloatAlignment = FloatAl; 00097 LongAlignment = LongAl; 00098 IntAlignment = IntAl; 00099 ShortAlignment = ShortAl; 00100 ByteAlignment = ByteAl; 00101 BoolAlignment = BoolAl; 00102 } 00103 00104 TargetData::TargetData(const std::string &ToolName, const Module *M) { 00105 LittleEndian = M->getEndianness() != Module::BigEndian; 00106 PointerSize = M->getPointerSize() != Module::Pointer64 ? 4 : 8; 00107 PointerAlignment = PointerSize; 00108 DoubleAlignment = PointerSize; 00109 FloatAlignment = 4; 00110 LongAlignment = PointerSize; 00111 IntAlignment = 4; 00112 ShortAlignment = 2; 00113 ByteAlignment = 1; 00114 BoolAlignment = 1; 00115 } 00116 00117 static std::map<std::pair<const TargetData*,const StructType*>, 00118 StructLayout> *Layouts = 0; 00119 00120 00121 TargetData::~TargetData() { 00122 if (Layouts) { 00123 // Remove any layouts for this TD. 00124 std::map<std::pair<const TargetData*, 00125 const StructType*>, StructLayout>::iterator 00126 I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0)); 00127 while (I != Layouts->end() && I->first.first == this) 00128 Layouts->erase(I++); 00129 if (Layouts->empty()) { 00130 delete Layouts; 00131 Layouts = 0; 00132 } 00133 } 00134 } 00135 00136 const StructLayout *TargetData::getStructLayout(const StructType *Ty) const { 00137 if (Layouts == 0) 00138 Layouts = new std::map<std::pair<const TargetData*,const StructType*>, 00139 StructLayout>(); 00140 std::map<std::pair<const TargetData*,const StructType*>, 00141 StructLayout>::iterator 00142 I = Layouts->lower_bound(std::make_pair(this, Ty)); 00143 if (I != Layouts->end() && I->first.first == this && I->first.second == Ty) 00144 return &I->second; 00145 else { 00146 return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty), 00147 StructLayout(Ty, *this)))->second; 00148 } 00149 } 00150 00151 static inline void getTypeInfo(const Type *Ty, const TargetData *TD, 00152 uint64_t &Size, unsigned char &Alignment) { 00153 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); 00154 switch (Ty->getTypeID()) { 00155 case Type::BoolTyID: Size = 1; Alignment = TD->getBoolAlignment(); return; 00156 case Type::VoidTyID: 00157 case Type::UByteTyID: 00158 case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return; 00159 case Type::UShortTyID: 00160 case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return; 00161 case Type::UIntTyID: 00162 case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return; 00163 case Type::ULongTyID: 00164 case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return; 00165 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return; 00166 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return; 00167 case Type::LabelTyID: 00168 case Type::PointerTyID: 00169 Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment(); 00170 return; 00171 case Type::ArrayTyID: { 00172 const ArrayType *ATy = cast<ArrayType>(Ty); 00173 getTypeInfo(ATy->getElementType(), TD, Size, Alignment); 00174 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; 00175 Size = AlignedSize*ATy->getNumElements(); 00176 return; 00177 } 00178 case Type::PackedTyID: { 00179 const PackedType *PTy = cast<PackedType>(Ty); 00180 getTypeInfo(PTy->getElementType(), TD, Size, Alignment); 00181 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; 00182 Size = AlignedSize*PTy->getNumElements(); 00183 return; 00184 } 00185 case Type::StructTyID: { 00186 // Get the layout annotation... which is lazily created on demand. 00187 const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty)); 00188 Size = Layout->StructSize; Alignment = Layout->StructAlignment; 00189 return; 00190 } 00191 00192 default: 00193 assert(0 && "Bad type for getTypeInfo!!!"); 00194 return; 00195 } 00196 } 00197 00198 uint64_t TargetData::getTypeSize(const Type *Ty) const { 00199 uint64_t Size; 00200 unsigned char Align; 00201 getTypeInfo(Ty, this, Size, Align); 00202 return Size; 00203 } 00204 00205 unsigned char TargetData::getTypeAlignment(const Type *Ty) const { 00206 uint64_t Size; 00207 unsigned char Align; 00208 getTypeInfo(Ty, this, Size, Align); 00209 return Align; 00210 } 00211 00212 unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const { 00213 unsigned Align = getTypeAlignment(Ty); 00214 assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); 00215 return log2(Align); 00216 } 00217 00218 /// getIntPtrType - Return an unsigned integer type that is the same size or 00219 /// greater to the host pointer size. 00220 const Type *TargetData::getIntPtrType() const { 00221 switch (getPointerSize()) { 00222 default: assert(0 && "Unknown pointer size!"); 00223 case 2: return Type::UShortTy; 00224 case 4: return Type::UIntTy; 00225 case 8: return Type::ULongTy; 00226 } 00227 } 00228 00229 00230 uint64_t TargetData::getIndexedOffset(const Type *ptrTy, 00231 const std::vector<Value*> &Idx) const { 00232 const Type *Ty = ptrTy; 00233 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()"); 00234 uint64_t Result = 0; 00235 00236 generic_gep_type_iterator<std::vector<Value*>::const_iterator> 00237 TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end()); 00238 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) { 00239 if (const StructType *STy = dyn_cast<StructType>(*TI)) { 00240 assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx"); 00241 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue(); 00242 00243 // Get structure layout information... 00244 const StructLayout *Layout = getStructLayout(STy); 00245 00246 // Add in the offset, as calculated by the structure layout info... 00247 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!"); 00248 Result += Layout->MemberOffsets[FieldNo]; 00249 00250 // Update Ty to refer to current element 00251 Ty = STy->getElementType(FieldNo); 00252 } else { 00253 // Update Ty to refer to current element 00254 Ty = cast<SequentialType>(Ty)->getElementType(); 00255 00256 // Get the array index and the size of each array element. 00257 int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue(); 00258 Result += arrayIdx * (int64_t)getTypeSize(Ty); 00259 } 00260 } 00261 00262 return Result; 00263 } 00264