blob: 158f57e3accf2941e27022c9c5d7ada39d0eb432 [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 Lattner10daaa12003-04-26 20:11:09 +000085 bool isLittleEndian, unsigned char PtrSize,
Chris Lattner85131c82002-10-14 22:41:13 +000086 unsigned char PtrAl, unsigned char DoubleAl,
87 unsigned char FloatAl, unsigned char LongAl,
88 unsigned char IntAl, unsigned char ShortAl,
89 unsigned char ByteAl)
Chris Lattnere7fb3602001-08-27 16:00:15 +000090 : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
91 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
92
Chris Lattner46326d92003-04-25 02:50:45 +000093 // If this assert triggers, a pass "required" TargetData information, but the
94 // top level tool did not provide once for it. We do not want to default
95 // construct, or else we might end up using a bad endianness or pointer size!
96 //
97 assert(!TargetName.empty() &&
98 "ERROR: Tool did not specify a target data to use!");
99
Chris Lattner85131c82002-10-14 22:41:13 +0000100 LittleEndian = isLittleEndian;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000101 PointerSize = PtrSize;
102 PointerAlignment = PtrAl;
103 DoubleAlignment = DoubleAl;
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000104 assert(DoubleAlignment == PtrAl &&
105 "Double alignment and pointer alignment agree for now!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000106 FloatAlignment = FloatAl;
107 LongAlignment = LongAl;
108 IntAlignment = IntAl;
109 ShortAlignment = ShortAl;
110 ByteAlignment = ByteAl;
111}
112
Chris Lattner53a0c382003-04-24 19:09:05 +0000113TargetData::TargetData(const std::string &ToolName, const Module *M)
114 : AID(AnnotationManager::getID("TargetData::" + ToolName)) {
115 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
116
117 LittleEndian = M->isLittleEndian();
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000118 PointerSize = M->has32BitPointers() ? 4 : 8;
Chris Lattner53a0c382003-04-24 19:09:05 +0000119 PointerAlignment = PointerSize;
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000120 DoubleAlignment = PointerSize;
Chris Lattner53a0c382003-04-24 19:09:05 +0000121 FloatAlignment = 4;
122 LongAlignment = 8;
123 IntAlignment = 4;
124 ShortAlignment = 2;
125 ByteAlignment = 1;
126}
127
Chris Lattnere7fb3602001-08-27 16:00:15 +0000128TargetData::~TargetData() {
129 AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory
130}
131
132static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +0000133 uint64_t &Size, unsigned char &Alignment) {
Chris Lattnerf59ce922001-12-13 00:46:11 +0000134 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000135 switch (Ty->getPrimitiveID()) {
136 case Type::VoidTyID:
137 case Type::BoolTyID:
138 case Type::UByteTyID:
139 case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return;
140 case Type::UShortTyID:
141 case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return;
142 case Type::UIntTyID:
143 case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return;
144 case Type::ULongTyID:
145 case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return;
146 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return;
147 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
148 case Type::LabelTyID:
149 case Type::PointerTyID:
150 Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
151 return;
152 case Type::ArrayTyID: {
153 const ArrayType *ATy = (const ArrayType *)Ty;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000154 getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
155 Size *= ATy->getNumElements();
156 return;
157 }
158 case Type::StructTyID: {
159 // Get the layout annotation... which is lazily created on demand.
160 const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty);
161 Size = Layout->StructSize; Alignment = Layout->StructAlignment;
162 return;
163 }
164
165 case Type::TypeTyID:
166 default:
167 assert(0 && "Bad type for getTypeInfo!!!");
168 return;
169 }
170}
171
Vikram S. Advef66723f2002-05-19 15:28:02 +0000172uint64_t TargetData::getTypeSize(const Type *Ty) const {
173 uint64_t Size;
174 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000175 getTypeInfo(Ty, this, Size, Align);
176 return Size;
177}
178
179unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000180 uint64_t Size;
181 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000182 getTypeInfo(Ty, this, Size, Align);
183 return Align;
184}
185
Vikram S. Advef66723f2002-05-19 15:28:02 +0000186uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
Chris Lattner697954c2002-01-20 22:54:45 +0000187 const std::vector<Value*> &Idx) const {
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000188 const Type *Ty = ptrTy;
189 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Advef66723f2002-05-19 15:28:02 +0000190 uint64_t Result = 0;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000191
Chris Lattner3cac88a2002-09-11 01:21:33 +0000192 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
193 if (Idx[CurIDX]->getType() == Type::LongTy) {
Vikram S. Adveca710e92002-08-13 18:17:56 +0000194 // Update Ty to refer to current element
195 Ty = cast<SequentialType>(Ty)->getElementType();
196
Vikram S. Advef66723f2002-05-19 15:28:02 +0000197 // Get the array index and the size of each array element.
Vikram S. Adve8e22ead2002-10-13 21:47:44 +0000198 // Both must be known constants, or the index shd be 0; else this fails.
Chris Lattner3cac88a2002-09-11 01:21:33 +0000199 int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
Vikram S. Adve8e22ead2002-10-13 21:47:44 +0000200 Result += arrayIdx == 0? 0
201 : (uint64_t) (arrayIdx * (int64_t) getTypeSize(Ty));
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000202
Vikram S. Advef66723f2002-05-19 15:28:02 +0000203 } else if (const StructType *STy = dyn_cast<const StructType>(Ty)) {
Chris Lattnere7fb3602001-08-27 16:00:15 +0000204 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000205 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000206
207 // Get structure layout information...
208 const StructLayout *Layout = getStructLayout(STy);
209
210 // Add in the offset, as calculated by the structure layout info...
Vikram S. Advef66723f2002-05-19 15:28:02 +0000211 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000212 Result += Layout->MemberOffsets[FieldNo];
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000213
Chris Lattnere7fb3602001-08-27 16:00:15 +0000214 // Update Ty to refer to current element
215 Ty = STy->getElementTypes()[FieldNo];
Chris Lattnere7fb3602001-08-27 16:00:15 +0000216 } else {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000217 assert(0 && "Indexing type that is not struct or array?");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000218 return 0; // Load directly through ptr
219 }
220 }
221
222 return Result;
223}