blob: 91c9d01198cae207992d4f021297f44226426fe8 [file] [log] [blame]
Chris Lattnere7fb3602001-08-27 16:00:15 +00001//===-- TargetData.cpp - Data size & alignment routines --------------------==//
John Criswellb576c942003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattnere7fb3602001-08-27 16:00:15 +00009//
10// This file defines target properties related to datatype size/offset/alignment
11// information. It uses lazy annotations to cache information about how
12// structure types are laid out and used.
13//
14// This structure should be created once, filled in if the defaults are not
15// correct and then passed around by const&. None of the members functions
16// require modification to the object.
17//
18//===----------------------------------------------------------------------===//
19
Vikram S. Adve0799fc42001-09-18 12:58:33 +000020#include "llvm/Target/TargetData.h"
Chris Lattner53a0c382003-04-24 19:09:05 +000021#include "llvm/Module.h"
Chris Lattnere7fb3602001-08-27 16:00:15 +000022#include "llvm/DerivedTypes.h"
Chris Lattner31bcdb82002-04-28 19:55:58 +000023#include "llvm/Constants.h"
Chris Lattnerf0453282003-12-22 05:01:15 +000024using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000025
Misha Brukman5560c9d2003-08-18 14:43:39 +000026// Handle the Pass registration stuff necessary to use TargetData's.
Chris Lattneraa31ad02002-09-25 23:46:55 +000027namespace {
28 // Register the default SparcV9 implementation...
29 RegisterPass<TargetData> X("targetdata", "Target Data Layout");
30}
31
Chris Lattnere7fb3602001-08-27 16:00:15 +000032static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
Vikram S. Advef66723f2002-05-19 15:28:02 +000033 uint64_t &Size, unsigned char &Alignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000034
35//===----------------------------------------------------------------------===//
36// Support for StructLayout Annotation
37//===----------------------------------------------------------------------===//
38
39StructLayout::StructLayout(const StructType *ST, const TargetData &TD)
40 : Annotation(TD.getStructLayoutAID()) {
41 StructAlignment = 0;
42 StructSize = 0;
43
44 // Loop over each of the elements, placing them in memory...
45 for (StructType::ElementTypes::const_iterator
46 TI = ST->getElementTypes().begin(),
47 TE = ST->getElementTypes().end(); TI != TE; ++TI) {
48 const Type *Ty = *TI;
49 unsigned char A;
Vikram S. Advef66723f2002-05-19 15:28:02 +000050 unsigned TyAlign;
51 uint64_t TySize;
52 getTypeInfo(Ty, &TD, TySize, A);
53 TyAlign = A;
Chris Lattnere7fb3602001-08-27 16:00:15 +000054
Misha Brukman5560c9d2003-08-18 14:43:39 +000055 // Add padding if necessary to make the data element aligned properly...
Chris Lattnere7fb3602001-08-27 16:00:15 +000056 if (StructSize % TyAlign != 0)
57 StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding...
58
59 // Keep track of maximum alignment constraint
Chris Lattner697954c2002-01-20 22:54:45 +000060 StructAlignment = std::max(TyAlign, StructAlignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000061
62 MemberOffsets.push_back(StructSize);
Vikram S. Advef66723f2002-05-19 15:28:02 +000063 StructSize += TySize; // Consume space for this data item
Chris Lattnere7fb3602001-08-27 16:00:15 +000064 }
65
Chris Lattner4e840d42003-05-21 18:08:44 +000066 // Empty structures have alignment of 1 byte.
67 if (StructAlignment == 0) StructAlignment = 1;
68
Chris Lattnere7fb3602001-08-27 16:00:15 +000069 // Add padding to the end of the struct so that it could be put in an array
70 // and all array elements would be aligned correctly.
71 if (StructSize % StructAlignment != 0)
72 StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
Chris Lattnere7fb3602001-08-27 16:00:15 +000073}
74
Chris Lattner97b73112001-09-07 16:40:04 +000075Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T,
76 void *D) {
Chris Lattnere7fb3602001-08-27 16:00:15 +000077 const TargetData &TD = *(const TargetData*)D;
78 assert(AID == TD.AID && "Target data annotation ID mismatch!");
Chris Lattner949a3622003-07-23 15:30:06 +000079 const Type *Ty = cast<Type>((const Value *)T);
Chris Lattner9b625032002-05-06 16:15:30 +000080 assert(isa<StructType>(Ty) &&
Chris Lattnere7fb3602001-08-27 16:00:15 +000081 "Can only create StructLayout annotation on structs!");
Chris Lattner949a3622003-07-23 15:30:06 +000082 return new StructLayout(cast<StructType>(Ty), TD);
Chris Lattnere7fb3602001-08-27 16:00:15 +000083}
84
85//===----------------------------------------------------------------------===//
86// TargetData Class Implementation
87//===----------------------------------------------------------------------===//
88
Vikram S. Advef66723f2002-05-19 15:28:02 +000089TargetData::TargetData(const std::string &TargetName,
Chris Lattner10daaa12003-04-26 20:11:09 +000090 bool isLittleEndian, unsigned char PtrSize,
Chris Lattner85131c82002-10-14 22:41:13 +000091 unsigned char PtrAl, unsigned char DoubleAl,
92 unsigned char FloatAl, unsigned char LongAl,
93 unsigned char IntAl, unsigned char ShortAl,
94 unsigned char ByteAl)
Chris Lattnere7fb3602001-08-27 16:00:15 +000095 : AID(AnnotationManager::getID("TargetData::" + TargetName)) {
96 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
97
Chris Lattner46326d92003-04-25 02:50:45 +000098 // If this assert triggers, a pass "required" TargetData information, but the
99 // top level tool did not provide once for it. We do not want to default
100 // construct, or else we might end up using a bad endianness or pointer size!
101 //
102 assert(!TargetName.empty() &&
103 "ERROR: Tool did not specify a target data to use!");
104
Chris Lattner85131c82002-10-14 22:41:13 +0000105 LittleEndian = isLittleEndian;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000106 PointerSize = PtrSize;
107 PointerAlignment = PtrAl;
108 DoubleAlignment = DoubleAl;
Chris Lattnerdd7253c2003-04-25 06:06:43 +0000109 assert(DoubleAlignment == PtrAl &&
110 "Double alignment and pointer alignment agree for now!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000111 FloatAlignment = FloatAl;
112 LongAlignment = LongAl;
113 IntAlignment = IntAl;
114 ShortAlignment = ShortAl;
115 ByteAlignment = ByteAl;
116}
117
Chris Lattner53a0c382003-04-24 19:09:05 +0000118TargetData::TargetData(const std::string &ToolName, const Module *M)
119 : AID(AnnotationManager::getID("TargetData::" + ToolName)) {
120 AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this);
121
Chris Lattner030574f2003-08-24 13:49:22 +0000122 LittleEndian = M->getEndianness() != Module::BigEndian;
123 PointerSize = M->getPointerSize() != Module::Pointer64 ? 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
Chris Lattnerf0453282003-12-22 05:01:15 +0000191/// getIntPtrType - Return an unsigned integer type that is the same size or
192/// greater to the host pointer size.
193const Type *TargetData::getIntPtrType() const {
194 switch (getPointerSize()) {
195 default: assert(0 && "Unknown pointer size!");
196 case 2: return Type::UShortTy;
197 case 4: return Type::UIntTy;
198 case 8: return Type::ULongTy;
199 }
200}
201
202
Vikram S. Advef66723f2002-05-19 15:28:02 +0000203uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
Chris Lattner697954c2002-01-20 22:54:45 +0000204 const std::vector<Value*> &Idx) const {
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000205 const Type *Ty = ptrTy;
206 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Advef66723f2002-05-19 15:28:02 +0000207 uint64_t Result = 0;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000208
Chris Lattner3cac88a2002-09-11 01:21:33 +0000209 for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
210 if (Idx[CurIDX]->getType() == Type::LongTy) {
Vikram S. Adveca710e92002-08-13 18:17:56 +0000211 // Update Ty to refer to current element
212 Ty = cast<SequentialType>(Ty)->getElementType();
213
Vikram S. Advef66723f2002-05-19 15:28:02 +0000214 // Get the array index and the size of each array element.
Chris Lattner3cac88a2002-09-11 01:21:33 +0000215 int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
Chris Lattner94a51182003-06-04 02:35:35 +0000216 Result += arrayIdx * (int64_t)getTypeSize(Ty);
Chris Lattner4954f042003-06-02 05:21:06 +0000217 } else {
218 const StructType *STy = cast<StructType>(Ty);
Chris Lattnere7fb3602001-08-27 16:00:15 +0000219 assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000220 unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000221
222 // Get structure layout information...
223 const StructLayout *Layout = getStructLayout(STy);
224
225 // Add in the offset, as calculated by the structure layout info...
Vikram S. Advef66723f2002-05-19 15:28:02 +0000226 assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
Chris Lattnere7fb3602001-08-27 16:00:15 +0000227 Result += Layout->MemberOffsets[FieldNo];
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000228
Chris Lattnere7fb3602001-08-27 16:00:15 +0000229 // Update Ty to refer to current element
230 Ty = STy->getElementTypes()[FieldNo];
Chris Lattnere7fb3602001-08-27 16:00:15 +0000231 }
232 }
233
234 return Result;
235}
Brian Gaeked0fde302003-11-11 22:41:34 +0000236