blob: 1207a6eed149d7ffbf144a3c8bd28147e5ac6efa [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 Lattnere7fb3602001-08-27 16:00:15 +000014#include "llvm/DerivedTypes.h"
Chris Lattner31bcdb82002-04-28 19:55:58 +000015#include "llvm/Constants.h"
Chris Lattnere7fb3602001-08-27 16:00:15 +000016
Chris Lattneraa31ad02002-09-25 23:46:55 +000017// Handle the Pass registration stuff neccesary to use TargetData's.
18namespace {
19 // Register the default SparcV9 implementation...
20 RegisterPass<TargetData> X("targetdata", "Target Data Layout");
21}
22
23
Chris Lattnere7fb3602001-08-27 16:00:15 +000024static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +000025 uint64_t &Size, unsigned char &Alignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000026
27//===----------------------------------------------------------------------===//
28// Support for StructLayout Annotation
29//===----------------------------------------------------------------------===//
30
31StructLayout::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;
Vikram S. Advef66723f2002-05-19 15:28:02 +000042 unsigned TyAlign;
43 uint64_t TySize;
44 getTypeInfo(Ty, &TD, TySize, A);
45 TyAlign = A;
Chris Lattnere7fb3602001-08-27 16:00:15 +000046
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
Chris Lattner697954c2002-01-20 22:54:45 +000052 StructAlignment = std::max(TyAlign, StructAlignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000053
54 MemberOffsets.push_back(StructSize);
Vikram S. Advef66723f2002-05-19 15:28:02 +000055 StructSize += TySize; // Consume space for this data item
Chris Lattnere7fb3602001-08-27 16:00:15 +000056 }
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
Chris Lattner97b73112001-09-07 16:40:04 +000069Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
70 void *D) {
Chris Lattnere7fb3602001-08-27 16:00:15 +000071 const TargetData &TD = *(const TargetData*)D;
72 assert(AID == TD.AID && "Target data annotation ID mismatch!");
Vikram S. Advef66723f2002-05-19 15:28:02 +000073 const Type *Ty = cast<const Type>((const Value *)T);
Chris Lattner9b625032002-05-06 16:15:30 +000074 assert(isa<StructType>(Ty) &&
Chris Lattnere7fb3602001-08-27 16:00:15 +000075 "Can only create StructLayout annotation on structs!");
Vikram S. Advef66723f2002-05-19 15:28:02 +000076 return new StructLayout((const StructType *)Ty, TD);
Chris Lattnere7fb3602001-08-27 16:00:15 +000077}
78
79//===----------------------------------------------------------------------===//
80// TargetData Class Implementation
81//===----------------------------------------------------------------------===//
82
Vikram S. Advef66723f2002-05-19 15:28:02 +000083TargetData::TargetData(const std::string &TargetName,
Chris Lattner85131c82002-10-14 22:41:13 +000084 bool isLittleEndian,
85 unsigned char IntRegSize, unsigned char PtrSize,
86 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 Lattner85131c82002-10-14 22:41:13 +000093 LittleEndian = isLittleEndian;
Vikram S. Advef66723f2002-05-19 15:28:02 +000094 IntegerRegSize = IntRegSize;
Chris Lattnere7fb3602001-08-27 16:00:15 +000095 PointerSize = PtrSize;
96 PointerAlignment = PtrAl;
97 DoubleAlignment = DoubleAl;
98 FloatAlignment = FloatAl;
99 LongAlignment = LongAl;
100 IntAlignment = IntAl;
101 ShortAlignment = ShortAl;
102 ByteAlignment = ByteAl;
103}
104
105TargetData::~TargetData() {
106 AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory
107}
108
109static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +0000110 uint64_t &Size, unsigned char &Alignment) {
Chris Lattnerf59ce922001-12-13 00:46:11 +0000111 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000112 switch (Ty->getPrimitiveID()) {
113 case Type::VoidTyID:
114 case Type::BoolTyID:
115 case Type::UByteTyID:
116 case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return;
117 case Type::UShortTyID:
118 case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return;
119 case Type::UIntTyID:
120 case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return;
121 case Type::ULongTyID:
122 case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return;
123 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return;
124 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
125 case Type::LabelTyID:
126 case Type::PointerTyID:
127 Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
128 return;
129 case Type::ArrayTyID: {
130 const ArrayType *ATy = (const ArrayType *)Ty;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000131 getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
132 Size *= ATy->getNumElements();
133 return;
134 }
135 case Type::StructTyID: {
136 // Get the layout annotation... which is lazily created on demand.
137 const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty);
138 Size = Layout->StructSize; Alignment = Layout->StructAlignment;
139 return;
140 }
141
142 case Type::TypeTyID:
143 default:
144 assert(0 && "Bad type for getTypeInfo!!!");
145 return;
146 }
147}
148
Vikram S. Advef66723f2002-05-19 15:28:02 +0000149uint64_t TargetData::getTypeSize(const Type *Ty) const {
150 uint64_t Size;
151 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000152 getTypeInfo(Ty, this, Size, Align);
153 return Size;
154}
155
156unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000157 uint64_t Size;
158 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000159 getTypeInfo(Ty, this, Size, Align);
160 return Align;
161}
162
Vikram S. Advef66723f2002-05-19 15:28:02 +0000163uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
Chris Lattner697954c2002-01-20 22:54:45 +0000164 const std::vector<Value*> &Idx) const {
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000165 const Type *Ty = ptrTy;
166 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Advef66723f2002-05-19 15:28:02 +0000167 uint64_t Result = 0;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000168
Chris Lattner3cac88a2002-09-11 01:21:33 +0000169 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
170 if (Idx[CurIDX]->getType() == Type::LongTy) {
Vikram S. Adveca710e92002-08-13 18:17:56 +0000171 // Update Ty to refer to current element
172 Ty = cast<SequentialType>(Ty)->getElementType();
173
Vikram S. Advef66723f2002-05-19 15:28:02 +0000174 // Get the array index and the size of each array element.
Vikram S. Adve8e22ead2002-10-13 21:47:44 +0000175 // Both must be known constants, or the index shd be 0; else this fails.
Chris Lattner3cac88a2002-09-11 01:21:33 +0000176 int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
Vikram S. Adve8e22ead2002-10-13 21:47:44 +0000177 Result += arrayIdx == 0? 0
178 : (uint64_t) (arrayIdx * (int64_t) getTypeSize(Ty));
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000179
Vikram S. Advef66723f2002-05-19 15:28:02 +0000180 } else if (const StructType *STy = dyn_cast<const StructType>(Ty)) {
Chris Lattnere7fb3602001-08-27 16:00:15 +0000181 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000182 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000183
184 // Get structure layout information...
185 const StructLayout *Layout = getStructLayout(STy);
186
187 // Add in the offset, as calculated by the structure layout info...
Vikram S. Advef66723f2002-05-19 15:28:02 +0000188 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000189 Result += Layout->MemberOffsets[FieldNo];
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000190
Chris Lattnere7fb3602001-08-27 16:00:15 +0000191 // Update Ty to refer to current element
192 Ty = STy->getElementTypes()[FieldNo];
193
Vikram S. Advef66723f2002-05-19 15:28:02 +0000194 } else if (isa<const ArrayType>(Ty)) {
195 assert(0 && "Loading from arrays not implemented yet!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000196 } else {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000197 assert(0 && "Indexing type that is not struct or array?");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000198 return 0; // Load directly through ptr
199 }
200 }
201
202 return Result;
203}