TargetData.cpp revision d2b0bb41f45c1d2381904221c780da8f750d2823
1//===-- TargetData.cpp - Data size & alignment routines --------------------==// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines target properties related to datatype size/offset/alignment 11// information. 12// 13// This structure should be created once, filled in if the defaults are not 14// correct and then passed around by const&. None of the members functions 15// require modification to the object. 16// 17//===----------------------------------------------------------------------===// 18 19#include "llvm/Target/TargetData.h" 20#include "llvm/Module.h" 21#include "llvm/DerivedTypes.h" 22#include "llvm/Constants.h" 23#include "llvm/Support/GetElementPtrTypeIterator.h" 24#include "Support/MathExtras.h" 25using namespace llvm; 26 27// Handle the Pass registration stuff necessary to use TargetData's. 28namespace { 29 // Register the default SparcV9 implementation... 30 RegisterPass<TargetData> X("targetdata", "Target Data Layout"); 31} 32 33static inline void getTypeInfo(const Type *Ty, const TargetData *TD, 34 uint64_t &Size, unsigned char &Alignment); 35 36//===----------------------------------------------------------------------===// 37// Support for StructLayout 38//===----------------------------------------------------------------------===// 39 40StructLayout::StructLayout(const StructType *ST, const TargetData &TD) { 41 StructAlignment = 0; 42 StructSize = 0; 43 44 // Loop over each of the elements, placing them in memory... 45 for (StructType::element_iterator TI = ST->element_begin(), 46 TE = ST->element_end(); TI != TE; ++TI) { 47 const Type *Ty = *TI; 48 unsigned char A; 49 unsigned TyAlign; 50 uint64_t TySize; 51 getTypeInfo(Ty, &TD, TySize, A); 52 TyAlign = A; 53 54 // Add padding if necessary to make the data element aligned properly... 55 if (StructSize % TyAlign != 0) 56 StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding... 57 58 // Keep track of maximum alignment constraint 59 StructAlignment = std::max(TyAlign, StructAlignment); 60 61 MemberOffsets.push_back(StructSize); 62 StructSize += TySize; // Consume space for this data item 63 } 64 65 // Empty structures have alignment of 1 byte. 66 if (StructAlignment == 0) StructAlignment = 1; 67 68 // Add padding to the end of the struct so that it could be put in an array 69 // and all array elements would be aligned correctly. 70 if (StructSize % StructAlignment != 0) 71 StructSize = (StructSize/StructAlignment + 1) * StructAlignment; 72} 73 74//===----------------------------------------------------------------------===// 75// TargetData Class Implementation 76//===----------------------------------------------------------------------===// 77 78TargetData::TargetData(const std::string &TargetName, 79 bool isLittleEndian, unsigned char PtrSize, 80 unsigned char PtrAl, unsigned char DoubleAl, 81 unsigned char FloatAl, unsigned char LongAl, 82 unsigned char IntAl, unsigned char ShortAl, 83 unsigned char ByteAl, unsigned char BoolAl) { 84 85 // If this assert triggers, a pass "required" TargetData information, but the 86 // top level tool did not provide one for it. We do not want to default 87 // construct, or else we might end up using a bad endianness or pointer size! 88 // 89 assert(!TargetName.empty() && 90 "ERROR: Tool did not specify a target data to use!"); 91 92 LittleEndian = isLittleEndian; 93 PointerSize = PtrSize; 94 PointerAlignment = PtrAl; 95 DoubleAlignment = DoubleAl; 96 FloatAlignment = FloatAl; 97 LongAlignment = LongAl; 98 IntAlignment = IntAl; 99 ShortAlignment = ShortAl; 100 ByteAlignment = ByteAl; 101 BoolAlignment = BoolAl; 102} 103 104TargetData::TargetData(const std::string &ToolName, const Module *M) { 105 LittleEndian = M->getEndianness() != Module::BigEndian; 106 PointerSize = M->getPointerSize() != Module::Pointer64 ? 4 : 8; 107 PointerAlignment = PointerSize; 108 DoubleAlignment = PointerSize; 109 FloatAlignment = 4; 110 LongAlignment = 8; 111 IntAlignment = 4; 112 ShortAlignment = 2; 113 ByteAlignment = 1; 114 BoolAlignment = 1; 115} 116 117static std::map<std::pair<const TargetData*,const StructType*>, 118 StructLayout> *Layouts = 0; 119 120 121TargetData::~TargetData() { 122 if (Layouts) { 123 // Remove any layouts for this TD. 124 std::map<std::pair<const TargetData*, 125 const StructType*>, StructLayout>::iterator 126 I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0)); 127 while (I != Layouts->end() && I->first.first == this) 128 Layouts->erase(I++); 129 if (Layouts->empty()) { 130 delete Layouts; 131 Layouts = 0; 132 } 133 } 134} 135 136const StructLayout *TargetData::getStructLayout(const StructType *Ty) const { 137 if (Layouts == 0) 138 Layouts = new std::map<std::pair<const TargetData*,const StructType*>, 139 StructLayout>(); 140 std::map<std::pair<const TargetData*,const StructType*>, 141 StructLayout>::iterator 142 I = Layouts->lower_bound(std::make_pair(this, Ty)); 143 if (I != Layouts->end() && I->first.first == this && I->first.second == Ty) 144 return &I->second; 145 else { 146 return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty), 147 StructLayout(Ty, *this)))->second; 148 } 149} 150 151static inline void getTypeInfo(const Type *Ty, const TargetData *TD, 152 uint64_t &Size, unsigned char &Alignment) { 153 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); 154 switch (Ty->getTypeID()) { 155 case Type::BoolTyID: Size = 1; Alignment = TD->getBoolAlignment(); return; 156 case Type::VoidTyID: 157 case Type::UByteTyID: 158 case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return; 159 case Type::UShortTyID: 160 case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return; 161 case Type::UIntTyID: 162 case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return; 163 case Type::ULongTyID: 164 case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return; 165 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return; 166 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return; 167 case Type::LabelTyID: 168 case Type::PointerTyID: 169 Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment(); 170 return; 171 case Type::ArrayTyID: { 172 const ArrayType *ATy = cast<ArrayType>(Ty); 173 getTypeInfo(ATy->getElementType(), TD, Size, Alignment); 174 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; 175 Size = AlignedSize*ATy->getNumElements(); 176 return; 177 } 178 case Type::StructTyID: { 179 // Get the layout annotation... which is lazily created on demand. 180 const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty)); 181 Size = Layout->StructSize; Alignment = Layout->StructAlignment; 182 return; 183 } 184 185 default: 186 assert(0 && "Bad type for getTypeInfo!!!"); 187 return; 188 } 189} 190 191uint64_t TargetData::getTypeSize(const Type *Ty) const { 192 uint64_t Size; 193 unsigned char Align; 194 getTypeInfo(Ty, this, Size, Align); 195 return Size; 196} 197 198unsigned char TargetData::getTypeAlignment(const Type *Ty) const { 199 uint64_t Size; 200 unsigned char Align; 201 getTypeInfo(Ty, this, Size, Align); 202 return Align; 203} 204 205unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const { 206 unsigned Align = getTypeAlignment(Ty); 207 assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); 208 return log2(Align); 209} 210 211/// getIntPtrType - Return an unsigned integer type that is the same size or 212/// greater to the host pointer size. 213const Type *TargetData::getIntPtrType() const { 214 switch (getPointerSize()) { 215 default: assert(0 && "Unknown pointer size!"); 216 case 2: return Type::UShortTy; 217 case 4: return Type::UIntTy; 218 case 8: return Type::ULongTy; 219 } 220} 221 222 223uint64_t TargetData::getIndexedOffset(const Type *ptrTy, 224 const std::vector<Value*> &Idx) const { 225 const Type *Ty = ptrTy; 226 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()"); 227 uint64_t Result = 0; 228 229 generic_gep_type_iterator<std::vector<Value*>::const_iterator> 230 TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end()); 231 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) { 232 if (const StructType *STy = dyn_cast<StructType>(*TI)) { 233 assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx"); 234 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue(); 235 236 // Get structure layout information... 237 const StructLayout *Layout = getStructLayout(STy); 238 239 // Add in the offset, as calculated by the structure layout info... 240 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!"); 241 Result += Layout->MemberOffsets[FieldNo]; 242 243 // Update Ty to refer to current element 244 Ty = STy->getElementType(FieldNo); 245 } else { 246 // Update Ty to refer to current element 247 Ty = cast<SequentialType>(Ty)->getElementType(); 248 249 // Get the array index and the size of each array element. 250 int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue(); 251 Result += arrayIdx * (int64_t)getTypeSize(Ty); 252 } 253 } 254 255 return Result; 256} 257 258