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