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