TargetData.cpp revision f59ce9276349598ed46bbd1bdc0011b7e2b211b4
1//===-- TargetData.cpp - Data size & alignment routines --------------------==// 2// 3// This file defines target properties related to datatype size/offset/alignment 4// information. It uses lazy annotations to cache information about how 5// structure types are laid out and used. 6// 7// This structure should be created once, filled in if the defaults are not 8// correct and then passed around by const&. None of the members functions 9// require modification to the object. 10// 11//===----------------------------------------------------------------------===// 12 13#include "llvm/Target/TargetData.h" 14#include "llvm/DerivedTypes.h" 15#include "llvm/ConstantVals.h" 16 17static inline void getTypeInfo(const Type *Ty, const TargetData *TD, 18 unsigned &Size, unsigned char &Alignment); 19 20//===----------------------------------------------------------------------===// 21// Support for StructLayout Annotation 22//===----------------------------------------------------------------------===// 23 24StructLayout::StructLayout(const StructType *ST, const TargetData &TD) 25 : Annotation(TD.getStructLayoutAID()) { 26 StructAlignment = 0; 27 StructSize = 0; 28 29 // Loop over each of the elements, placing them in memory... 30 for (StructType::ElementTypes::const_iterator 31 TI = ST->getElementTypes().begin(), 32 TE = ST->getElementTypes().end(); TI != TE; ++TI) { 33 const Type *Ty = *TI; 34 unsigned char A; 35 unsigned TySize, TyAlign; 36 getTypeInfo(Ty, &TD, TySize, A); TyAlign = A; 37 38 // Add padding if neccesary to make the data element aligned properly... 39 if (StructSize % TyAlign != 0) 40 StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding... 41 42 // Keep track of maximum alignment constraint 43 StructAlignment = max(TyAlign, StructAlignment); 44 45 MemberOffsets.push_back(StructSize); 46 StructSize += TySize; // Consume space for this data item... 47 } 48 49 // Add padding to the end of the struct so that it could be put in an array 50 // and all array elements would be aligned correctly. 51 if (StructSize % StructAlignment != 0) 52 StructSize = (StructSize/StructAlignment + 1) * StructAlignment; 53 54 if (StructSize == 0) { 55 StructSize = 1; // Empty struct is 1 byte 56 StructAlignment = 1; 57 } 58} 59 60Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T, 61 void *D) { 62 const TargetData &TD = *(const TargetData*)D; 63 assert(AID == TD.AID && "Target data annotation ID mismatch!"); 64 const Type *Ty = cast<const Type>((const Value *)T); 65 assert(Ty->isStructType() && 66 "Can only create StructLayout annotation on structs!"); 67 return new StructLayout((const StructType *)Ty, TD); 68} 69 70//===----------------------------------------------------------------------===// 71// TargetData Class Implementation 72//===----------------------------------------------------------------------===// 73 74TargetData::TargetData(const string &TargetName, unsigned char PtrSize = 8, 75 unsigned char PtrAl = 8, unsigned char DoubleAl = 8, 76 unsigned char FloatAl = 4, unsigned char LongAl = 8, 77 unsigned char IntAl = 4, unsigned char ShortAl = 2, 78 unsigned char ByteAl = 1) 79 : AID(AnnotationManager::getID("TargetData::" + TargetName)) { 80 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this); 81 82 PointerSize = PtrSize; 83 PointerAlignment = PtrAl; 84 DoubleAlignment = DoubleAl; 85 FloatAlignment = FloatAl; 86 LongAlignment = LongAl; 87 IntAlignment = IntAl; 88 ShortAlignment = ShortAl; 89 ByteAlignment = ByteAl; 90} 91 92TargetData::~TargetData() { 93 AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory 94} 95 96static inline void getTypeInfo(const Type *Ty, const TargetData *TD, 97 unsigned &Size, unsigned char &Alignment) { 98 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); 99 switch (Ty->getPrimitiveID()) { 100 case Type::VoidTyID: 101 case Type::BoolTyID: 102 case Type::UByteTyID: 103 case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return; 104 case Type::UShortTyID: 105 case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return; 106 case Type::UIntTyID: 107 case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return; 108 case Type::ULongTyID: 109 case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return; 110 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return; 111 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return; 112 case Type::LabelTyID: 113 case Type::PointerTyID: 114 Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment(); 115 return; 116 case Type::ArrayTyID: { 117 const ArrayType *ATy = (const ArrayType *)Ty; 118 getTypeInfo(ATy->getElementType(), TD, Size, Alignment); 119 Size *= ATy->getNumElements(); 120 return; 121 } 122 case Type::StructTyID: { 123 // Get the layout annotation... which is lazily created on demand. 124 const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty); 125 Size = Layout->StructSize; Alignment = Layout->StructAlignment; 126 return; 127 } 128 129 case Type::TypeTyID: 130 default: 131 assert(0 && "Bad type for getTypeInfo!!!"); 132 return; 133 } 134} 135 136unsigned TargetData::getTypeSize(const Type *Ty) const { 137 unsigned Size; unsigned char Align; 138 getTypeInfo(Ty, this, Size, Align); 139 return Size; 140} 141 142unsigned char TargetData::getTypeAlignment(const Type *Ty) const { 143 unsigned Size; unsigned char Align; 144 getTypeInfo(Ty, this, Size, Align); 145 return Align; 146} 147 148unsigned TargetData::getIndexedOffset(const Type *ptrTy, 149 const vector<Constant*> &Idx) const { 150 const PointerType *PtrTy = cast<const PointerType>(ptrTy); 151 unsigned Result = 0; 152 153 // Get the type pointed to... 154 const Type *Ty = PtrTy->getElementType(); 155 156 for (unsigned CurIDX = 0; CurIDX < Idx.size(); ++CurIDX) { 157 if (const StructType *STy = dyn_cast<const StructType>(Ty)) { 158 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx"); 159 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue(); 160 161 // Get structure layout information... 162 const StructLayout *Layout = getStructLayout(STy); 163 164 // Add in the offset, as calculated by the structure layout info... 165 assert(FieldNo < Layout->MemberOffsets.size() && "FieldNo out of range!"); 166 Result += Layout->MemberOffsets[FieldNo]; 167 168 // Update Ty to refer to current element 169 Ty = STy->getElementTypes()[FieldNo]; 170 171 } else if (const ArrayType *ATy = dyn_cast<const ArrayType>(Ty)) { 172 assert(0 && "Loading from arrays not implemented yet!"); 173 } else { 174 assert(0 && "Indexing type that is not struct or array?"); 175 return 0; // Load directly through ptr 176 } 177 } 178 179 return Result; 180} 181