Extend TargetData::getIndexedOffset to support arrays and pointers!
[oota-llvm.git] / lib / Target / TargetData.cpp
1 //===-- TargetData.cpp - Data size & alignment routines --------------------==//
2 //
3 // This file defines target properties related to datatype size/offset/alignment
4 // information.  It uses lazy annotations to cache information about how 
5 // structure types are laid out and used.
6 //
7 // This structure should be created once, filled in if the defaults are not
8 // correct and then passed around by const&.  None of the members functions
9 // require modification to the object.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Target/TargetData.h"
14 #include "llvm/DerivedTypes.h"
15 #include "llvm/Constants.h"
16
17 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
18                                unsigned &Size, unsigned char &Alignment);
19
20 //===----------------------------------------------------------------------===//
21 // Support for StructLayout Annotation
22 //===----------------------------------------------------------------------===//
23
24 StructLayout::StructLayout(const StructType *ST, const TargetData &TD) 
25   : Annotation(TD.getStructLayoutAID()) {
26   StructAlignment = 0;
27   StructSize = 0;
28
29   // Loop over each of the elements, placing them in memory...
30   for (StructType::ElementTypes::const_iterator
31          TI = ST->getElementTypes().begin(), 
32          TE = ST->getElementTypes().end(); TI != TE; ++TI) {
33     const Type *Ty = *TI;
34     unsigned char A;
35     unsigned TySize, TyAlign;
36     getTypeInfo(Ty, &TD, TySize, A);  TyAlign = A;
37
38     // Add padding if neccesary to make the data element aligned properly...
39     if (StructSize % TyAlign != 0)
40       StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...
41
42     // Keep track of maximum alignment constraint
43     StructAlignment = std::max(TyAlign, StructAlignment);
44
45     MemberOffsets.push_back(StructSize);
46     StructSize += TySize;                 // Consume space for this data item...
47   }
48
49   // Add padding to the end of the struct so that it could be put in an array
50   // and all array elements would be aligned correctly.
51   if (StructSize % StructAlignment != 0)
52     StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
53
54   if (StructSize == 0) {
55     StructSize = 1;           // Empty struct is 1 byte
56     StructAlignment = 1;
57   }
58 }
59
60 Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
61                                       void *D) {
62   const TargetData &TD = *(const TargetData*)D;
63   assert(AID == TD.AID && "Target data annotation ID mismatch!");
64   const Type *Ty = cast<Type>((const Value *)T);
65   assert(isa<StructType>(Ty) && 
66          "Can only create StructLayout annotation on structs!");
67   return new StructLayout(cast<StructType>(Ty), TD);
68 }
69
70 //===----------------------------------------------------------------------===//
71 //                       TargetData Class Implementation
72 //===----------------------------------------------------------------------===//
73
74 TargetData::TargetData(const std::string &TargetName, unsigned char PtrSize = 8,
75              unsigned char PtrAl = 8, unsigned char DoubleAl = 8,
76              unsigned char FloatAl = 4, unsigned char LongAl = 8, 
77              unsigned char IntAl = 4, unsigned char ShortAl = 2,
78              unsigned char ByteAl = 1)
79   : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
80   AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
81
82   PointerSize      = PtrSize;
83   PointerAlignment = PtrAl;
84   DoubleAlignment  = DoubleAl;
85   FloatAlignment   = FloatAl;
86   LongAlignment    = LongAl;
87   IntAlignment     = IntAl;
88   ShortAlignment   = ShortAl;
89   ByteAlignment    = ByteAl;
90 }
91
92 TargetData::~TargetData() {
93   AnnotationManager::registerAnnotationFactory(AID, 0);   // Deregister factory
94 }
95
96 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
97                                unsigned &Size, unsigned char &Alignment) {
98   assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
99   switch (Ty->getPrimitiveID()) {
100   case Type::VoidTyID:
101   case Type::BoolTyID:
102   case Type::UByteTyID:
103   case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
104   case Type::UShortTyID:
105   case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
106   case Type::UIntTyID:
107   case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
108   case Type::ULongTyID:
109   case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
110   case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
111   case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
112   case Type::LabelTyID:
113   case Type::PointerTyID:
114     Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
115     return;
116   case Type::ArrayTyID: {
117     const ArrayType *ATy = (const ArrayType *)Ty;
118     getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
119     Size *= ATy->getNumElements();
120     return;
121   }
122   case Type::StructTyID: {
123     // Get the layout annotation... which is lazily created on demand.
124     const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty);
125     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
126     return;
127   }
128     
129   case Type::TypeTyID:
130   default:
131     assert(0 && "Bad type for getTypeInfo!!!");
132     return;
133   }
134 }
135
136 unsigned TargetData::getTypeSize(const Type *Ty) const {
137   unsigned Size; unsigned char Align;
138   getTypeInfo(Ty, this, Size, Align);
139   return Size;
140 }
141
142 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
143   unsigned Size; unsigned char Align;
144   getTypeInfo(Ty, this, Size, Align);
145   return Align;
146 }
147
148 unsigned TargetData::getIndexedOffset(const Type *Ty,
149                                       const std::vector<Value*> &Idx) const {
150   unsigned Result = 0;
151
152   for (unsigned CurIDX = 0, E = Idx.size(); CurIDX != E; ++CurIDX) {
153     if (const StructType *STy = dyn_cast<StructType>(Ty)) {
154       assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
155       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
156
157       // Get structure layout information...
158       const StructLayout *Layout = getStructLayout(STy);
159
160       // Add in the offset, as calculated by the structure layout info...
161       assert(FieldNo < Layout->MemberOffsets.size() && "FieldNo out of range!");
162       Result += Layout->MemberOffsets[FieldNo];
163       
164       // Update Ty to refer to current element
165       Ty = STy->getElementTypes()[FieldNo];
166
167     } else if (const SequentialType *STy = dyn_cast<SequentialType>(Ty)) {
168       assert(Idx[CurIDX]->getType() == Type::UIntTy &&"Illegal sequential idx");
169       assert(isa<ConstantUInt>(Idx[CurIDX]) &&
170              "getIndexedOffset cannot compute offset of non-constant index!");
171
172       unsigned IndexNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
173       Ty = STy->getElementType();
174       
175       Result += IndexNo*getTypeSize(Ty);
176     } else {
177       assert(0 && "Indexing type that is not struct, array, or pointer?");
178       return 0;                         // Load directly through ptr
179     }
180   }
181
182   return Result;
183 }