Added LLVM project notice to the top of every C++ source file.
[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.  It uses lazy annotations to cache information about how 
12 // structure types are laid out and used.
13 //
14 // This structure should be created once, filled in if the defaults are not
15 // correct and then passed around by const&.  None of the members functions
16 // require modification to the object.
17 //
18 //===----------------------------------------------------------------------===//
19
20 #include "llvm/Target/TargetData.h"
21 #include "llvm/Module.h"
22 #include "llvm/DerivedTypes.h"
23 #include "llvm/Constants.h"
24
25 // Handle the Pass registration stuff necessary to use TargetData's.
26 namespace {
27   // Register the default SparcV9 implementation...
28   RegisterPass<TargetData> X("targetdata", "Target Data Layout");
29 }
30
31
32 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
33                                uint64_t &Size, unsigned char &Alignment);
34
35 //===----------------------------------------------------------------------===//
36 // Support for StructLayout Annotation
37 //===----------------------------------------------------------------------===//
38
39 StructLayout::StructLayout(const StructType *ST, const TargetData &TD) 
40   : Annotation(TD.getStructLayoutAID()) {
41   StructAlignment = 0;
42   StructSize = 0;
43
44   // Loop over each of the elements, placing them in memory...
45   for (StructType::ElementTypes::const_iterator
46          TI = ST->getElementTypes().begin(), 
47          TE = ST->getElementTypes().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 Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
76                                       void *D) {
77   const TargetData &TD = *(const TargetData*)D;
78   assert(AID == TD.AID && "Target data annotation ID mismatch!");
79   const Type *Ty = cast<Type>((const Value *)T);
80   assert(isa<StructType>(Ty) && 
81          "Can only create StructLayout annotation on structs!");
82   return new StructLayout(cast<StructType>(Ty), TD);
83 }
84
85 //===----------------------------------------------------------------------===//
86 //                       TargetData Class Implementation
87 //===----------------------------------------------------------------------===//
88
89 TargetData::TargetData(const std::string &TargetName,
90                        bool isLittleEndian, unsigned char PtrSize,
91                        unsigned char PtrAl, unsigned char DoubleAl,
92                        unsigned char FloatAl, unsigned char LongAl, 
93                        unsigned char IntAl, unsigned char ShortAl,
94                        unsigned char ByteAl)
95   : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
96   AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
97
98   // If this assert triggers, a pass "required" TargetData information, but the
99   // top level tool did not provide once for it.  We do not want to default
100   // construct, or else we might end up using a bad endianness or pointer size!
101   //
102   assert(!TargetName.empty() &&
103          "ERROR: Tool did not specify a target data to use!");
104
105   LittleEndian     = isLittleEndian;
106   PointerSize      = PtrSize;
107   PointerAlignment = PtrAl;
108   DoubleAlignment  = DoubleAl;
109   assert(DoubleAlignment == PtrAl &&
110          "Double alignment and pointer alignment agree for now!");
111   FloatAlignment   = FloatAl;
112   LongAlignment    = LongAl;
113   IntAlignment     = IntAl;
114   ShortAlignment   = ShortAl;
115   ByteAlignment    = ByteAl;
116 }
117
118 TargetData::TargetData(const std::string &ToolName, const Module *M)
119   : AID(AnnotationManager::getID("TargetData::" + ToolName)) {
120   AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
121
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    = 8;
128   IntAlignment     = 4;
129   ShortAlignment   = 2;
130   ByteAlignment    = 1;
131 }
132
133 TargetData::~TargetData() {
134   AnnotationManager::registerAnnotationFactory(AID, 0);   // Deregister factory
135 }
136
137 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
138                                uint64_t &Size, unsigned char &Alignment) {
139   assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
140   switch (Ty->getPrimitiveID()) {
141   case Type::VoidTyID:
142   case Type::BoolTyID:
143   case Type::UByteTyID:
144   case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
145   case Type::UShortTyID:
146   case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
147   case Type::UIntTyID:
148   case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
149   case Type::ULongTyID:
150   case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
151   case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
152   case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
153   case Type::LabelTyID:
154   case Type::PointerTyID:
155     Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
156     return;
157   case Type::ArrayTyID: {
158     const ArrayType *ATy = (const ArrayType *)Ty;
159     getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
160     Size *= ATy->getNumElements();
161     return;
162   }
163   case Type::StructTyID: {
164     // Get the layout annotation... which is lazily created on demand.
165     const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty);
166     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
167     return;
168   }
169     
170   case Type::TypeTyID:
171   default:
172     assert(0 && "Bad type for getTypeInfo!!!");
173     return;
174   }
175 }
176
177 uint64_t TargetData::getTypeSize(const Type *Ty) const {
178   uint64_t Size;
179   unsigned char Align;
180   getTypeInfo(Ty, this, Size, Align);
181   return Size;
182 }
183
184 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
185   uint64_t Size;
186   unsigned char Align;
187   getTypeInfo(Ty, this, Size, Align);
188   return Align;
189 }
190
191 uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
192                                       const std::vector<Value*> &Idx) const {
193   const Type *Ty = ptrTy;
194   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
195   uint64_t Result = 0;
196
197   for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
198     if (Idx[CurIDX]->getType() == Type::LongTy) {
199       // Update Ty to refer to current element
200       Ty = cast<SequentialType>(Ty)->getElementType();
201
202       // Get the array index and the size of each array element.
203       int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
204       Result += arrayIdx * (int64_t)getTypeSize(Ty);
205     } else {
206       const StructType *STy = cast<StructType>(Ty);
207       assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
208       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
209
210       // Get structure layout information...
211       const StructLayout *Layout = getStructLayout(STy);
212
213       // Add in the offset, as calculated by the structure layout info...
214       assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
215       Result += Layout->MemberOffsets[FieldNo];
216
217       // Update Ty to refer to current element
218       Ty = STy->getElementTypes()[FieldNo];
219     }
220   }
221
222   return Result;
223 }