Fix sign-extension: it needs to happen *after* multiplying by type size.
[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                                uint64_t &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 TyAlign;
36     uint64_t TySize;
37     getTypeInfo(Ty, &TD, TySize, A);
38     TyAlign = A;
39
40     // Add padding if neccesary to make the data element aligned properly...
41     if (StructSize % TyAlign != 0)
42       StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...
43
44     // Keep track of maximum alignment constraint
45     StructAlignment = std::max(TyAlign, StructAlignment);
46
47     MemberOffsets.push_back(StructSize);
48     StructSize += TySize;                 // Consume space for this data item
49   }
50
51   // Add padding to the end of the struct so that it could be put in an array
52   // and all array elements would be aligned correctly.
53   if (StructSize % StructAlignment != 0)
54     StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
55
56   if (StructSize == 0) {
57     StructSize = 1;           // Empty struct is 1 byte
58     StructAlignment = 1;
59   }
60 }
61
62 Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
63                                       void *D) {
64   const TargetData &TD = *(const TargetData*)D;
65   assert(AID == TD.AID && "Target data annotation ID mismatch!");
66   const Type *Ty = cast<const Type>((const Value *)T);
67   assert(isa<StructType>(Ty) && 
68          "Can only create StructLayout annotation on structs!");
69   return new StructLayout((const StructType *)Ty, TD);
70 }
71
72 //===----------------------------------------------------------------------===//
73 //                       TargetData Class Implementation
74 //===----------------------------------------------------------------------===//
75
76 TargetData::TargetData(const std::string &TargetName,
77              unsigned char IntRegSize, unsigned char PtrSize,
78              unsigned char PtrAl, unsigned char DoubleAl,
79              unsigned char FloatAl, unsigned char LongAl, 
80              unsigned char IntAl, unsigned char ShortAl,
81              unsigned char ByteAl)
82   : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
83   AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
84
85   IntegerRegSize   = IntRegSize;
86   PointerSize      = PtrSize;
87   PointerAlignment = PtrAl;
88   DoubleAlignment  = DoubleAl;
89   FloatAlignment   = FloatAl;
90   LongAlignment    = LongAl;
91   IntAlignment     = IntAl;
92   ShortAlignment   = ShortAl;
93   ByteAlignment    = ByteAl;
94 }
95
96 TargetData::~TargetData() {
97   AnnotationManager::registerAnnotationFactory(AID, 0);   // Deregister factory
98 }
99
100 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
101                                uint64_t &Size, unsigned char &Alignment) {
102   assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
103   switch (Ty->getPrimitiveID()) {
104   case Type::VoidTyID:
105   case Type::BoolTyID:
106   case Type::UByteTyID:
107   case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
108   case Type::UShortTyID:
109   case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
110   case Type::UIntTyID:
111   case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
112   case Type::ULongTyID:
113   case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
114   case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
115   case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
116   case Type::LabelTyID:
117   case Type::PointerTyID:
118     Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
119     return;
120   case Type::ArrayTyID: {
121     const ArrayType *ATy = (const ArrayType *)Ty;
122     getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
123     Size *= ATy->getNumElements();
124     return;
125   }
126   case Type::StructTyID: {
127     // Get the layout annotation... which is lazily created on demand.
128     const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty);
129     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
130     return;
131   }
132     
133   case Type::TypeTyID:
134   default:
135     assert(0 && "Bad type for getTypeInfo!!!");
136     return;
137   }
138 }
139
140 uint64_t TargetData::getTypeSize(const Type *Ty) const {
141   uint64_t Size;
142   unsigned char Align;
143   getTypeInfo(Ty, this, Size, Align);
144   return Size;
145 }
146
147 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
148   uint64_t Size;
149   unsigned char Align;
150   getTypeInfo(Ty, this, Size, Align);
151   return Align;
152 }
153
154 uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
155                                       const std::vector<Value*> &Idx) const {
156   const Type *Ty = ptrTy;
157   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
158   uint64_t Result = 0;
159
160   for (unsigned CurIDX = 0; CurIDX < Idx.size(); ++CurIDX) {
161     if (Idx[CurIDX]->getType() == Type::UIntTy) {
162       // Update Ty to refer to current element
163       Ty = cast<SequentialType>(Ty)->getElementType();
164
165       // Get the array index and the size of each array element.
166       // Both must be known constants, or this will fail.
167       // Also, the product needs to be sign-extended from 32 to 64 bits.
168       uint64_t elementSize = this->getTypeSize(Ty);
169       uint64_t arrayIdx = cast<ConstantUInt>(Idx[CurIDX])->getValue();
170       Result += (uint64_t) (int) (arrayIdx * elementSize); // sign-extend
171
172     } else if (const StructType *STy = dyn_cast<const StructType>(Ty)) {
173       assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
174       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
175
176       // Get structure layout information...
177       const StructLayout *Layout = getStructLayout(STy);
178
179       // Add in the offset, as calculated by the structure layout info...
180       assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
181       Result += Layout->MemberOffsets[FieldNo];
182
183       // Update Ty to refer to current element
184       Ty = STy->getElementTypes()[FieldNo];
185
186     } else if (isa<const ArrayType>(Ty)) {
187       assert(0 && "Loading from arrays not implemented yet!");
188     } else {
189       assert(0 && "Indexing type that is not struct or array?");
190       return 0;                         // Load directly through ptr
191     }
192   }
193
194   return Result;
195 }