blob: 96c6ba9bfec365afd36de5feadb3266d3b531623 [file] [log] [blame]
Chris Lattner53bbf072001-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. Adve6cefc702001-09-18 12:58:33 +000013#include "llvm/Target/TargetData.h"
Chris Lattner53bbf072001-08-27 16:00:15 +000014#include "llvm/DerivedTypes.h"
Chris Lattnerca142372002-04-28 19:55:58 +000015#include "llvm/Constants.h"
Chris Lattner53bbf072001-08-27 16:00:15 +000016
Chris Lattner09cfdcb2002-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 Lattner53bbf072001-08-27 16:00:15 +000024static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Adve8b831742002-05-19 15:28:02 +000025 uint64_t &Size, unsigned char &Alignment);
Chris Lattner53bbf072001-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. Adve8b831742002-05-19 15:28:02 +000042 unsigned TyAlign;
43 uint64_t TySize;
44 getTypeInfo(Ty, &TD, TySize, A);
45 TyAlign = A;
Chris Lattner53bbf072001-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 Lattner7f74a562002-01-20 22:54:45 +000052 StructAlignment = std::max(TyAlign, StructAlignment);
Chris Lattner53bbf072001-08-27 16:00:15 +000053
54 MemberOffsets.push_back(StructSize);
Vikram S. Adve8b831742002-05-19 15:28:02 +000055 StructSize += TySize; // Consume space for this data item
Chris Lattner53bbf072001-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 Lattner4eb6d9f2001-09-07 16:40:04 +000069Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
70 void *D) {
Chris Lattner53bbf072001-08-27 16:00:15 +000071 const TargetData &TD = *(const TargetData*)D;
72 assert(AID == TD.AID && "Target data annotation ID mismatch!");
Vikram S. Adve8b831742002-05-19 15:28:02 +000073 const Type *Ty = cast<const Type>((const Value *)T);
Chris Lattner181cc322002-05-06 16:15:30 +000074 assert(isa<StructType>(Ty) &&
Chris Lattner53bbf072001-08-27 16:00:15 +000075 "Can only create StructLayout annotation on structs!");
Vikram S. Adve8b831742002-05-19 15:28:02 +000076 return new StructLayout((const StructType *)Ty, TD);
Chris Lattner53bbf072001-08-27 16:00:15 +000077}
78
79//===----------------------------------------------------------------------===//
80// TargetData Class Implementation
81//===----------------------------------------------------------------------===//
82
Vikram S. Adve8b831742002-05-19 15:28:02 +000083TargetData::TargetData(const std::string &TargetName,
Chris Lattnerb8489562002-10-29 21:48:17 +000084 bool isLittleEndian, unsigned char SubWordSize,
Chris Lattner5156bba2002-10-14 22:41:13 +000085 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 Lattner53bbf072001-08-27 16:00:15 +000090 : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
91 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
92
Chris Lattner5156bba2002-10-14 22:41:13 +000093 LittleEndian = isLittleEndian;
Chris Lattnerb8489562002-10-29 21:48:17 +000094 SubWordDataSize = SubWordSize;
Vikram S. Adve8b831742002-05-19 15:28:02 +000095 IntegerRegSize = IntRegSize;
Chris Lattner53bbf072001-08-27 16:00:15 +000096 PointerSize = PtrSize;
97 PointerAlignment = PtrAl;
98 DoubleAlignment = DoubleAl;
99 FloatAlignment = FloatAl;
100 LongAlignment = LongAl;
101 IntAlignment = IntAl;
102 ShortAlignment = ShortAl;
103 ByteAlignment = ByteAl;
104}
105
106TargetData::~TargetData() {
107 AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory
108}
109
110static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Adve8b831742002-05-19 15:28:02 +0000111 uint64_t &Size, unsigned char &Alignment) {
Chris Lattner6650d182001-12-13 00:46:11 +0000112 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
Chris Lattner53bbf072001-08-27 16:00:15 +0000113 switch (Ty->getPrimitiveID()) {
114 case Type::VoidTyID:
115 case Type::BoolTyID:
116 case Type::UByteTyID:
117 case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return;
118 case Type::UShortTyID:
119 case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return;
120 case Type::UIntTyID:
121 case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return;
122 case Type::ULongTyID:
123 case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return;
124 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return;
125 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
126 case Type::LabelTyID:
127 case Type::PointerTyID:
128 Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
129 return;
130 case Type::ArrayTyID: {
131 const ArrayType *ATy = (const ArrayType *)Ty;
Chris Lattner53bbf072001-08-27 16:00:15 +0000132 getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
133 Size *= ATy->getNumElements();
134 return;
135 }
136 case Type::StructTyID: {
137 // Get the layout annotation... which is lazily created on demand.
138 const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty);
139 Size = Layout->StructSize; Alignment = Layout->StructAlignment;
140 return;
141 }
142
143 case Type::TypeTyID:
144 default:
145 assert(0 && "Bad type for getTypeInfo!!!");
146 return;
147 }
148}
149
Vikram S. Adve8b831742002-05-19 15:28:02 +0000150uint64_t TargetData::getTypeSize(const Type *Ty) const {
151 uint64_t Size;
152 unsigned char Align;
Chris Lattner53bbf072001-08-27 16:00:15 +0000153 getTypeInfo(Ty, this, Size, Align);
154 return Size;
155}
156
157unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
Vikram S. Adve8b831742002-05-19 15:28:02 +0000158 uint64_t Size;
159 unsigned char Align;
Chris Lattner53bbf072001-08-27 16:00:15 +0000160 getTypeInfo(Ty, this, Size, Align);
161 return Align;
162}
163
Vikram S. Adve8b831742002-05-19 15:28:02 +0000164uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
Chris Lattner7f74a562002-01-20 22:54:45 +0000165 const std::vector<Value*> &Idx) const {
Vikram S. Adve71895b22002-08-04 20:52:39 +0000166 const Type *Ty = ptrTy;
167 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Adve8b831742002-05-19 15:28:02 +0000168 uint64_t Result = 0;
Chris Lattner53bbf072001-08-27 16:00:15 +0000169
Chris Lattner136dab72002-09-11 01:21:33 +0000170 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
171 if (Idx[CurIDX]->getType() == Type::LongTy) {
Vikram S. Advea3efa262002-08-13 18:17:56 +0000172 // Update Ty to refer to current element
173 Ty = cast<SequentialType>(Ty)->getElementType();
174
Vikram S. Adve8b831742002-05-19 15:28:02 +0000175 // Get the array index and the size of each array element.
Vikram S. Advea202c0d2002-10-13 21:47:44 +0000176 // Both must be known constants, or the index shd be 0; else this fails.
Chris Lattner136dab72002-09-11 01:21:33 +0000177 int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
Vikram S. Advea202c0d2002-10-13 21:47:44 +0000178 Result += arrayIdx == 0? 0
179 : (uint64_t) (arrayIdx * (int64_t) getTypeSize(Ty));
Vikram S. Adve71895b22002-08-04 20:52:39 +0000180
Vikram S. Adve8b831742002-05-19 15:28:02 +0000181 } else if (const StructType *STy = dyn_cast<const StructType>(Ty)) {
Chris Lattner53bbf072001-08-27 16:00:15 +0000182 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
Chris Lattner3462ae32001-12-03 22:26:30 +0000183 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
Chris Lattner53bbf072001-08-27 16:00:15 +0000184
185 // Get structure layout information...
186 const StructLayout *Layout = getStructLayout(STy);
187
188 // Add in the offset, as calculated by the structure layout info...
Vikram S. Adve8b831742002-05-19 15:28:02 +0000189 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
Chris Lattner53bbf072001-08-27 16:00:15 +0000190 Result += Layout->MemberOffsets[FieldNo];
Vikram S. Adve71895b22002-08-04 20:52:39 +0000191
Chris Lattner53bbf072001-08-27 16:00:15 +0000192 // Update Ty to refer to current element
193 Ty = STy->getElementTypes()[FieldNo];
Chris Lattner53bbf072001-08-27 16:00:15 +0000194 } else {
Vikram S. Adve8b831742002-05-19 15:28:02 +0000195 assert(0 && "Indexing type that is not struct or array?");
Chris Lattner53bbf072001-08-27 16:00:15 +0000196 return 0; // Load directly through ptr
197 }
198 }
199
200 return Result;
201}