Make TargetData strings less redundant.
[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 "llvm/ADT/StringExtras.h"
26 #include <algorithm>
27 #include <cstdlib>
28 #include <sstream>
29 using namespace llvm;
30
31 // Handle the Pass registration stuff necessary to use TargetData's.
32 namespace {
33   // Register the default SparcV9 implementation...
34   RegisterPass<TargetData> X("targetdata", "Target Data Layout");
35 }
36
37 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
38                                uint64_t &Size, unsigned char &Alignment);
39
40 //===----------------------------------------------------------------------===//
41 // Support for StructLayout
42 //===----------------------------------------------------------------------===//
43
44 StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
45   StructAlignment = 0;
46   StructSize = 0;
47
48   // Loop over each of the elements, placing them in memory...
49   for (StructType::element_iterator TI = ST->element_begin(),
50          TE = ST->element_end(); TI != TE; ++TI) {
51     const Type *Ty = *TI;
52     unsigned char A;
53     unsigned TyAlign;
54     uint64_t TySize;
55     getTypeInfo(Ty, &TD, TySize, A);
56     TyAlign = A;
57
58     // Add padding if necessary to make the data element aligned properly...
59     if (StructSize % TyAlign != 0)
60       StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...
61
62     // Keep track of maximum alignment constraint
63     StructAlignment = std::max(TyAlign, StructAlignment);
64
65     MemberOffsets.push_back(StructSize);
66     StructSize += TySize;                 // Consume space for this data item
67   }
68
69   // Empty structures have alignment of 1 byte.
70   if (StructAlignment == 0) StructAlignment = 1;
71
72   // Add padding to the end of the struct so that it could be put in an array
73   // and all array elements would be aligned correctly.
74   if (StructSize % StructAlignment != 0)
75     StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
76 }
77
78
79 /// getElementContainingOffset - Given a valid offset into the structure,
80 /// return the structure index that contains it.
81 unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
82   std::vector<uint64_t>::const_iterator SI =
83     std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(),
84                      Offset);
85   assert(SI != MemberOffsets.begin() && "Offset not in structure type!");
86   --SI;
87   assert(*SI <= Offset && "upper_bound didn't work");
88   assert((SI == MemberOffsets.begin() || *(SI-1) < Offset) &&
89          (SI+1 == MemberOffsets.end() || *(SI+1) > Offset) &&
90          "Upper bound didn't work!");
91   return SI-MemberOffsets.begin();
92 }
93
94 //===----------------------------------------------------------------------===//
95 //                       TargetData Class Implementation
96 //===----------------------------------------------------------------------===//
97
98 TargetData::TargetData(const std::string &TargetName,
99                        bool isLittleEndian, unsigned char PtrSize,
100                        unsigned char PtrAl, unsigned char DoubleAl,
101                        unsigned char FloatAl, unsigned char LongAl,
102                        unsigned char IntAl, unsigned char ShortAl,
103                        unsigned char ByteAl, unsigned char BoolAl) {
104
105   // If this assert triggers, a pass "required" TargetData information, but the
106   // top level tool did not provide one for it.  We do not want to default
107   // construct, or else we might end up using a bad endianness or pointer size!
108   //
109   assert(!TargetName.empty() &&
110          "ERROR: Tool did not specify a target data to use!");
111
112   LittleEndian     = isLittleEndian;
113   PointerSize      = PtrSize;
114   PointerAlignment = PtrAl;
115   DoubleAlignment  = DoubleAl;
116   FloatAlignment   = FloatAl;
117   LongAlignment    = LongAl;
118   IntAlignment     = IntAl;
119   ShortAlignment   = ShortAl;
120   ByteAlignment    = ByteAl;
121   BoolAlignment    = BoolAl;
122 }
123
124 TargetData::TargetData(const std::string &TargetName,
125                        const std::string &TargetDescription) {
126   assert(!TargetName.empty() &&
127          "ERROR: Tool did not specify a target data to use!");
128
129                        
130   std::string temp = TargetDescription;
131   
132   LittleEndian = false;
133   PointerSize = 8;
134   PointerAlignment   = 8;
135   DoubleAlignment = 8;
136   FloatAlignment = 4;
137   LongAlignment   = 8;
138   IntAlignment   = 4;
139   ShortAlignment  = 2;
140   ByteAlignment  = 1;
141   BoolAlignment   = 1;
142   
143   while (!temp.empty()) {
144     std::string token = getToken(temp, "-");
145     
146     char signal = getToken(token, ":")[0];
147     
148     switch(signal) {
149     case 'E':
150       LittleEndian = false;
151       break;
152     case 'e':
153       LittleEndian = true;
154       break;
155     case 'p':
156       PointerSize = atoi(getToken(token,":").c_str()) / 8;
157       PointerAlignment = atoi(getToken(token,":").c_str()) / 8;
158       break;
159     case 'd':
160       DoubleAlignment = atoi(getToken(token,":").c_str()) / 8;
161       break;
162     case 'f':
163       FloatAlignment = atoi(getToken(token, ":").c_str()) / 8;
164       break;
165     case 'l':
166       LongAlignment = atoi(getToken(token, ":").c_str()) / 8;
167       break;
168     case 'i':
169       IntAlignment = atoi(getToken(token, ":").c_str()) / 8;
170       break;
171     case 's':
172       ShortAlignment = atoi(getToken(token, ":").c_str()) / 8;
173       break;
174     case 'b':
175       ByteAlignment = atoi(getToken(token, ":").c_str()) / 8;
176       break;
177     case 'B':
178       BoolAlignment = atoi(getToken(token, ":").c_str()) / 8;
179       break;
180     default:
181       break;
182     }
183   }
184 }
185
186 TargetData::TargetData(const std::string &ToolName, const Module *M) {
187   LittleEndian     = M->getEndianness() != Module::BigEndian;
188   PointerSize      = M->getPointerSize() != Module::Pointer64 ? 4 : 8;
189   PointerAlignment = PointerSize;
190   DoubleAlignment  = PointerSize;
191   FloatAlignment   = 4;
192   LongAlignment    = PointerSize;
193   IntAlignment     = 4;
194   ShortAlignment   = 2;
195   ByteAlignment    = 1;
196   BoolAlignment    = 1;
197 }
198
199 /// Layouts - The lazy cache of structure layout information maintained by
200 /// TargetData.
201 ///
202 static std::map<std::pair<const TargetData*,const StructType*>,
203                 StructLayout> *Layouts = 0;
204
205
206 TargetData::~TargetData() {
207   if (Layouts) {
208     // Remove any layouts for this TD.
209     std::map<std::pair<const TargetData*,
210       const StructType*>, StructLayout>::iterator
211       I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0));
212     while (I != Layouts->end() && I->first.first == this)
213       Layouts->erase(I++);
214     if (Layouts->empty()) {
215       delete Layouts;
216       Layouts = 0;
217     }
218   }
219 }
220
221 std::string TargetData::getStringRepresentation() const {
222   std::stringstream repr;
223   
224   if (LittleEndian)
225     repr << "e";
226   else
227     repr << "E";
228   
229   repr << "-p:" << (PointerSize * 8) << ":" << (PointerAlignment * 8);
230   repr << "-d:64:" << (DoubleAlignment * 8);
231   repr << "-f:32:" << (FloatAlignment * 8);
232   repr << "-l:64:" << (LongAlignment * 8);
233   repr << "-i:32:" << (IntAlignment * 8);
234   repr << "-s:16:" << (ShortAlignment * 8);
235   repr << "-b:8:" << (ByteAlignment * 8);
236   repr << "-B:8:" << (BoolAlignment * 8);
237   
238   return repr.str();
239 }
240
241 const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
242   if (Layouts == 0)
243     Layouts = new std::map<std::pair<const TargetData*,const StructType*>,
244                            StructLayout>();
245   std::map<std::pair<const TargetData*,const StructType*>,
246                      StructLayout>::iterator
247     I = Layouts->lower_bound(std::make_pair(this, Ty));
248   if (I != Layouts->end() && I->first.first == this && I->first.second == Ty)
249     return &I->second;
250   else {
251     return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty),
252                                               StructLayout(Ty, *this)))->second;
253   }
254 }
255
256 /// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
257 /// objects.  If a TargetData object is alive when types are being refined and
258 /// removed, this method must be called whenever a StructType is removed to
259 /// avoid a dangling pointer in this cache.
260 void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
261   if (!Layouts) return;  // No cache.
262
263   std::map<std::pair<const TargetData*,const StructType*>,
264            StructLayout>::iterator I = Layouts->find(std::make_pair(this, Ty));
265   if (I != Layouts->end())
266     Layouts->erase(I);
267 }
268
269
270
271 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
272                                uint64_t &Size, unsigned char &Alignment) {
273   assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
274   switch (Ty->getTypeID()) {
275   case Type::BoolTyID:   Size = 1; Alignment = TD->getBoolAlignment(); return;
276   case Type::VoidTyID:
277   case Type::UByteTyID:
278   case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
279   case Type::UShortTyID:
280   case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
281   case Type::UIntTyID:
282   case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
283   case Type::ULongTyID:
284   case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
285   case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
286   case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
287   case Type::LabelTyID:
288   case Type::PointerTyID:
289     Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
290     return;
291   case Type::ArrayTyID: {
292     const ArrayType *ATy = cast<ArrayType>(Ty);
293     getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
294     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
295     Size = AlignedSize*ATy->getNumElements();
296     return;
297   }
298   case Type::PackedTyID: {
299     const PackedType *PTy = cast<PackedType>(Ty);
300     getTypeInfo(PTy->getElementType(), TD, Size, Alignment);
301     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
302     Size = AlignedSize*PTy->getNumElements();
303     // FIXME: The alignments of specific packed types are target dependent.
304     // For now, just set it to be equal to Size.
305     Alignment = Size;
306     return;
307   }
308   case Type::StructTyID: {
309     // Get the layout annotation... which is lazily created on demand.
310     const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
311     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
312     return;
313   }
314
315   default:
316     assert(0 && "Bad type for getTypeInfo!!!");
317     return;
318   }
319 }
320
321 uint64_t TargetData::getTypeSize(const Type *Ty) const {
322   uint64_t Size;
323   unsigned char Align;
324   getTypeInfo(Ty, this, Size, Align);
325   return Size;
326 }
327
328 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
329   uint64_t Size;
330   unsigned char Align;
331   getTypeInfo(Ty, this, Size, Align);
332   return Align;
333 }
334
335 unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
336   unsigned Align = getTypeAlignment(Ty);
337   assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
338   return Log2_32(Align);
339 }
340
341 /// getIntPtrType - Return an unsigned integer type that is the same size or
342 /// greater to the host pointer size.
343 const Type *TargetData::getIntPtrType() const {
344   switch (getPointerSize()) {
345   default: assert(0 && "Unknown pointer size!");
346   case 2: return Type::UShortTy;
347   case 4: return Type::UIntTy;
348   case 8: return Type::ULongTy;
349   }
350 }
351
352
353 uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
354                                       const std::vector<Value*> &Idx) const {
355   const Type *Ty = ptrTy;
356   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
357   uint64_t Result = 0;
358
359   generic_gep_type_iterator<std::vector<Value*>::const_iterator>
360     TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
361   for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
362     if (const StructType *STy = dyn_cast<StructType>(*TI)) {
363       assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
364       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
365
366       // Get structure layout information...
367       const StructLayout *Layout = getStructLayout(STy);
368
369       // Add in the offset, as calculated by the structure layout info...
370       assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
371       Result += Layout->MemberOffsets[FieldNo];
372
373       // Update Ty to refer to current element
374       Ty = STy->getElementType(FieldNo);
375     } else {
376       // Update Ty to refer to current element
377       Ty = cast<SequentialType>(Ty)->getElementType();
378
379       // Get the array index and the size of each array element.
380       int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
381       Result += arrayIdx * (int64_t)getTypeSize(Ty);
382     }
383   }
384
385   return Result;
386 }
387