blob: 08a6536b78a87983422399bfd5b82528862119a0 [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
17static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +000018 uint64_t &Size, unsigned char &Alignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000019
20//===----------------------------------------------------------------------===//
21// Support for StructLayout Annotation
22//===----------------------------------------------------------------------===//
23
24StructLayout::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;
Vikram S. Advef66723f2002-05-19 15:28:02 +000035 unsigned TyAlign;
36 uint64_t TySize;
37 getTypeInfo(Ty, &TD, TySize, A);
38 TyAlign = A;
Chris Lattnere7fb3602001-08-27 16:00:15 +000039
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
Chris Lattner697954c2002-01-20 22:54:45 +000045 StructAlignment = std::max(TyAlign, StructAlignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000046
47 MemberOffsets.push_back(StructSize);
Vikram S. Advef66723f2002-05-19 15:28:02 +000048 StructSize += TySize; // Consume space for this data item
Chris Lattnere7fb3602001-08-27 16:00:15 +000049 }
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
Chris Lattner97b73112001-09-07 16:40:04 +000062Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
63 void *D) {
Chris Lattnere7fb3602001-08-27 16:00:15 +000064 const TargetData &TD = *(const TargetData*)D;
65 assert(AID == TD.AID && "Target data annotation ID mismatch!");
Vikram S. Advef66723f2002-05-19 15:28:02 +000066 const Type *Ty = cast<const Type>((const Value *)T);
Chris Lattner9b625032002-05-06 16:15:30 +000067 assert(isa<StructType>(Ty) &&
Chris Lattnere7fb3602001-08-27 16:00:15 +000068 "Can only create StructLayout annotation on structs!");
Vikram S. Advef66723f2002-05-19 15:28:02 +000069 return new StructLayout((const StructType *)Ty, TD);
Chris Lattnere7fb3602001-08-27 16:00:15 +000070}
71
72//===----------------------------------------------------------------------===//
73// TargetData Class Implementation
74//===----------------------------------------------------------------------===//
75
Vikram S. Advef66723f2002-05-19 15:28:02 +000076TargetData::TargetData(const std::string &TargetName,
Chris Lattner0c0edf82002-07-25 06:17:51 +000077 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)
Chris Lattnere7fb3602001-08-27 16:00:15 +000082 : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
83 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
84
Vikram S. Advef66723f2002-05-19 15:28:02 +000085 IntegerRegSize = IntRegSize;
Chris Lattnere7fb3602001-08-27 16:00:15 +000086 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
96TargetData::~TargetData() {
97 AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory
98}
99
100static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +0000101 uint64_t &Size, unsigned char &Alignment) {
Chris Lattnerf59ce922001-12-13 00:46:11 +0000102 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000103 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;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000122 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
Vikram S. Advef66723f2002-05-19 15:28:02 +0000140uint64_t TargetData::getTypeSize(const Type *Ty) const {
141 uint64_t Size;
142 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000143 getTypeInfo(Ty, this, Size, Align);
144 return Size;
145}
146
147unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000148 uint64_t Size;
149 unsigned char Align;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000150 getTypeInfo(Ty, this, Size, Align);
151 return Align;
152}
153
Vikram S. Advef66723f2002-05-19 15:28:02 +0000154uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
Chris Lattner697954c2002-01-20 22:54:45 +0000155 const std::vector<Value*> &Idx) const {
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000156 const Type *Ty = ptrTy;
157 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Advef66723f2002-05-19 15:28:02 +0000158 uint64_t Result = 0;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000159
Vikram S. Advef66723f2002-05-19 15:28:02 +0000160 for (unsigned CurIDX = 0; CurIDX < Idx.size(); ++CurIDX) {
161 if (Idx[CurIDX]->getType() == Type::UIntTy) {
162 // Get the array index and the size of each array element.
163 // Both must be known constants, or this will fail.
164 unsigned arrayIdx = cast<ConstantUInt>(Idx[CurIDX])->getValue();
165 uint64_t elementSize = this->getTypeSize(Ty);
166 Result += arrayIdx * elementSize;
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000167
168 // Update Ty to refer to current element
169 Ty = cast<SequentialType>(Ty)->getElementType();
170
Vikram S. Advef66723f2002-05-19 15:28:02 +0000171 } else if (const StructType *STy = dyn_cast<const StructType>(Ty)) {
Chris Lattnere7fb3602001-08-27 16:00:15 +0000172 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000173 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000174
175 // Get structure layout information...
176 const StructLayout *Layout = getStructLayout(STy);
177
178 // Add in the offset, as calculated by the structure layout info...
Vikram S. Advef66723f2002-05-19 15:28:02 +0000179 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000180 Result += Layout->MemberOffsets[FieldNo];
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000181
Chris Lattnere7fb3602001-08-27 16:00:15 +0000182 // Update Ty to refer to current element
183 Ty = STy->getElementTypes()[FieldNo];
184
Vikram S. Advef66723f2002-05-19 15:28:02 +0000185 } else if (isa<const ArrayType>(Ty)) {
186 assert(0 && "Loading from arrays not implemented yet!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000187 } else {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000188 assert(0 && "Indexing type that is not struct or array?");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000189 return 0; // Load directly through ptr
190 }
191 }
192
193 return Result;
194}