Initial support for packed types, contributed by Morten Ofstad
[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 using namespace llvm;
26
27 // Handle the Pass registration stuff necessary to use TargetData's.
28 namespace {
29   // Register the default SparcV9 implementation...
30   RegisterPass<TargetData> X("targetdata", "Target Data Layout");
31 }
32
33 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
34                                uint64_t &Size, unsigned char &Alignment);
35
36 //===----------------------------------------------------------------------===//
37 // Support for StructLayout
38 //===----------------------------------------------------------------------===//
39
40 StructLayout::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
78 TargetData::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
104 TargetData::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    = PointerSize;
111   IntAlignment     = 4;
112   ShortAlignment   = 2;
113   ByteAlignment    = 1;
114   BoolAlignment    = 1;
115 }
116
117 static std::map<std::pair<const TargetData*,const StructType*>,
118                 StructLayout> *Layouts = 0;
119
120
121 TargetData::~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
136 const 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
151 static 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::PackedTyID: {
179     const PackedType *PTy = cast<PackedType>(Ty);
180     getTypeInfo(PTy->getElementType(), TD, Size, Alignment);
181     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
182     Size = AlignedSize*PTy->getNumElements();
183     return;
184   }
185   case Type::StructTyID: {
186     // Get the layout annotation... which is lazily created on demand.
187     const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
188     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
189     return;
190   }
191     
192   default:
193     assert(0 && "Bad type for getTypeInfo!!!");
194     return;
195   }
196 }
197
198 uint64_t TargetData::getTypeSize(const Type *Ty) const {
199   uint64_t Size;
200   unsigned char Align;
201   getTypeInfo(Ty, this, Size, Align);
202   return Size;
203 }
204
205 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
206   uint64_t Size;
207   unsigned char Align;
208   getTypeInfo(Ty, this, Size, Align);
209   return Align;
210 }
211
212 unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
213   unsigned Align = getTypeAlignment(Ty);
214   assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
215   return log2(Align);
216 }
217
218 /// getIntPtrType - Return an unsigned integer type that is the same size or
219 /// greater to the host pointer size.
220 const Type *TargetData::getIntPtrType() const {
221   switch (getPointerSize()) {
222   default: assert(0 && "Unknown pointer size!");
223   case 2: return Type::UShortTy;
224   case 4: return Type::UIntTy;
225   case 8: return Type::ULongTy;
226   }
227 }
228
229
230 uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
231                                       const std::vector<Value*> &Idx) const {
232   const Type *Ty = ptrTy;
233   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
234   uint64_t Result = 0;
235
236   generic_gep_type_iterator<std::vector<Value*>::const_iterator>
237     TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
238   for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
239     if (const StructType *STy = dyn_cast<StructType>(*TI)) {
240       assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
241       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
242
243       // Get structure layout information...
244       const StructLayout *Layout = getStructLayout(STy);
245
246       // Add in the offset, as calculated by the structure layout info...
247       assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
248       Result += Layout->MemberOffsets[FieldNo];
249
250       // Update Ty to refer to current element
251       Ty = STy->getElementType(FieldNo);
252     } else {
253       // Update Ty to refer to current element
254       Ty = cast<SequentialType>(Ty)->getElementType();
255
256       // Get the array index and the size of each array element.
257       int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
258       Result += arrayIdx * (int64_t)getTypeSize(Ty);
259     }
260   }
261
262   return Result;
263 }
264