blob: 923031c4005d35b119488307a53049521282cfe4 [file] [log] [blame]
Chris Lattnere7fb3602001-08-27 16:00:15 +00001//===-- 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
Vikram S. Adve0799fc42001-09-18 12:58:33 +000013#include "llvm/Target/TargetData.h"
Chris Lattner53a0c382003-04-24 19:09:05 +000014#include "llvm/Module.h"
Chris Lattnere7fb3602001-08-27 16:00:15 +000015#include "llvm/DerivedTypes.h"
Chris Lattner31bcdb82002-04-28 19:55:58 +000016#include "llvm/Constants.h"
Chris Lattnere7fb3602001-08-27 16:00:15 +000017
Chris Lattneraa31ad02002-09-25 23:46:55 +000018// Handle the Pass registration stuff neccesary to use TargetData's.
19namespace {
20 // Register the default SparcV9 implementation...
21 RegisterPass<TargetData> X("targetdata", "Target Data Layout");
22}
23
24
Chris Lattnere7fb3602001-08-27 16:00:15 +000025static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +000026 uint64_t &Size, unsigned char &Alignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000027
28//===----------------------------------------------------------------------===//
29// Support for StructLayout Annotation
30//===----------------------------------------------------------------------===//
31
32StructLayout::StructLayout(const StructType *ST, const TargetData &TD)
33 : Annotation(TD.getStructLayoutAID()) {
34 StructAlignment = 0;
35 StructSize = 0;
36
37 // Loop over each of the elements, placing them in memory...
38 for (StructType::ElementTypes::const_iterator
39 TI = ST->getElementTypes().begin(),
40 TE = ST->getElementTypes().end(); TI != TE; ++TI) {
41 const Type *Ty = *TI;
42 unsigned char A;
Vikram S. Advef66723f2002-05-19 15:28:02 +000043 unsigned TyAlign;
44 uint64_t TySize;
45 getTypeInfo(Ty, &TD, TySize, A);
46 TyAlign = A;
Chris Lattnere7fb3602001-08-27 16:00:15 +000047
48 // Add padding if neccesary to make the data element aligned properly...
49 if (StructSize % TyAlign != 0)
50 StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding...
51
52 // Keep track of maximum alignment constraint
Chris Lattner697954c2002-01-20 22:54:45 +000053 StructAlignment = std::max(TyAlign, StructAlignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000054
55 MemberOffsets.push_back(StructSize);
Vikram S. Advef66723f2002-05-19 15:28:02 +000056 StructSize += TySize; // Consume space for this data item
Chris Lattnere7fb3602001-08-27 16:00:15 +000057 }
58
59 // Add padding to the end of the struct so that it could be put in an array
60 // and all array elements would be aligned correctly.
61 if (StructSize % StructAlignment != 0)
62 StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
63
64 if (StructSize == 0) {
65 StructSize = 1; // Empty struct is 1 byte
66 StructAlignment = 1;
67 }
68}
69
Chris Lattner97b73112001-09-07 16:40:04 +000070Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
71 void *D) {
Chris Lattnere7fb3602001-08-27 16:00:15 +000072 const TargetData &TD = *(const TargetData*)D;
73 assert(AID == TD.AID && "Target data annotation ID mismatch!");
Vikram S. Advef66723f2002-05-19 15:28:02 +000074 const Type *Ty = cast<const Type>((const Value *)T);
Chris Lattner9b625032002-05-06 16:15:30 +000075 assert(isa<StructType>(Ty) &&
Chris Lattnere7fb3602001-08-27 16:00:15 +000076 "Can only create StructLayout annotation on structs!");
Vikram S. Advef66723f2002-05-19 15:28:02 +000077 return new StructLayout((const StructType *)Ty, TD);
Chris Lattnere7fb3602001-08-27 16:00:15 +000078}
79
80//===----------------------------------------------------------------------===//
81// TargetData Class Implementation
82//===----------------------------------------------------------------------===//
83
Vikram S. Advef66723f2002-05-19 15:28:02 +000084TargetData::TargetData(const std::string &TargetName,
Chris Lattnerc56406c2002-10-29 21:48:17 +000085 bool isLittleEndian, unsigned char SubWordSize,
Chris Lattner85131c82002-10-14 22:41:13 +000086 unsigned char IntRegSize, unsigned char PtrSize,
87 unsigned char PtrAl, unsigned char DoubleAl,
88 unsigned char FloatAl, unsigned char LongAl,
89 unsigned char IntAl, unsigned char ShortAl,
90 unsigned char ByteAl)
Chris Lattnere7fb3602001-08-27 16:00:15 +000091 : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
92 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
93
Chris Lattner46326d92003-04-25 02:50:45 +000094 // If this assert triggers, a pass "required" TargetData information, but the
95 // top level tool did not provide once for it. We do not want to default
96 // construct, or else we might end up using a bad endianness or pointer size!
97 //
98 assert(!TargetName.empty() &&
99 "ERROR: Tool did not specify a target data to use!");
100
Chris Lattner85131c82002-10-14 22:41:13 +0000101 LittleEndian = isLittleEndian;
Chris Lattnerc56406c2002-10-29 21:48:17 +0000102 SubWordDataSize = SubWordSize;
Vikram S. Advef66723f2002-05-19 15:28:02 +0000103 IntegerRegSize = IntRegSize;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000104 PointerSize = PtrSize;
105 PointerAlignment = PtrAl;
106 DoubleAlignment = DoubleAl;
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000107 assert(DoubleAlignment == PtrAl &&
108 "Double alignment and pointer alignment agree for now!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000109 FloatAlignment = FloatAl;
110 LongAlignment = LongAl;
111 IntAlignment = IntAl;
112 ShortAlignment = ShortAl;
113 ByteAlignment = ByteAl;
114}
115
Chris Lattner53a0c382003-04-24 19:09:05 +0000116TargetData::TargetData(const std::string &ToolName, const Module *M)
117 : AID(AnnotationManager::getID("TargetData::" + ToolName)) {
118 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
119
120 LittleEndian = M->isLittleEndian();
121 SubWordDataSize = 1;
122 IntegerRegSize = 8;
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000123 PointerSize = M->has32BitPointers() ? 4 : 8;
Chris Lattner53a0c382003-04-24 19:09:05 +0000124 PointerAlignment = PointerSize;
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000125 DoubleAlignment = PointerSize;
Chris Lattner53a0c382003-04-24 19:09:05 +0000126 FloatAlignment = 4;
127 LongAlignment = 8;
128 IntAlignment = 4;
129 ShortAlignment = 2;
130 ByteAlignment = 1;
131}
132
Chris Lattnere7fb3602001-08-27 16:00:15 +0000133TargetData::~TargetData() {
134 AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory
135}
136
137static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +0000138 uint64_t &Size, unsigned char &Alignment) {
Chris Lattnerf59ce922001-12-13 00:46:11 +0000139 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000140 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;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000159 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
Vikram S. Advef66723f2002-05-19 15:28:02 +0000177uint64_t TargetData::getTypeSize(const Type *Ty) const {
178 uint64_t Size;
179 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000180 getTypeInfo(Ty, this, Size, Align);
181 return Size;
182}
183
184unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000185 uint64_t Size;
186 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000187 getTypeInfo(Ty, this, Size, Align);
188 return Align;
189}
190
Vikram S. Advef66723f2002-05-19 15:28:02 +0000191uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
Chris Lattner697954c2002-01-20 22:54:45 +0000192 const std::vector<Value*> &Idx) const {
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000193 const Type *Ty = ptrTy;
194 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Advef66723f2002-05-19 15:28:02 +0000195 uint64_t Result = 0;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000196
Chris Lattner3cac88a2002-09-11 01:21:33 +0000197 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
198 if (Idx[CurIDX]->getType() == Type::LongTy) {
Vikram S. Adveca710e92002-08-13 18:17:56 +0000199 // Update Ty to refer to current element
200 Ty = cast<SequentialType>(Ty)->getElementType();
201
Vikram S. Advef66723f2002-05-19 15:28:02 +0000202 // Get the array index and the size of each array element.
Vikram S. Adve8e22ead2002-10-13 21:47:44 +0000203 // Both must be known constants, or the index shd be 0; else this fails.
Chris Lattner3cac88a2002-09-11 01:21:33 +0000204 int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
Vikram S. Adve8e22ead2002-10-13 21:47:44 +0000205 Result += arrayIdx == 0? 0
206 : (uint64_t) (arrayIdx * (int64_t) getTypeSize(Ty));
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000207
Vikram S. Advef66723f2002-05-19 15:28:02 +0000208 } else if (const StructType *STy = dyn_cast<const StructType>(Ty)) {
Chris Lattnere7fb3602001-08-27 16:00:15 +0000209 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000210 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000211
212 // Get structure layout information...
213 const StructLayout *Layout = getStructLayout(STy);
214
215 // Add in the offset, as calculated by the structure layout info...
Vikram S. Advef66723f2002-05-19 15:28:02 +0000216 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000217 Result += Layout->MemberOffsets[FieldNo];
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000218
Chris Lattnere7fb3602001-08-27 16:00:15 +0000219 // Update Ty to refer to current element
220 Ty = STy->getElementTypes()[FieldNo];
Chris Lattnere7fb3602001-08-27 16:00:15 +0000221 } else {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000222 assert(0 && "Indexing type that is not struct or array?");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000223 return 0; // Load directly through ptr
224 }
225 }
226
227 return Result;
228}