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