blob: 805b7549373182007b2ec5280eb7d476429baf3b [file] [log] [blame]
Chris Lattnere7fb3602001-08-27 16:00:15 +00001//===-- TargetData.cpp - Data size & alignment routines --------------------==//
Misha Brukmanf976c852005-04-21 22:55:34 +00002//
John Criswellb576c942003-10-20 19:43:21 +00003// 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.
Misha Brukmanf976c852005-04-21 22:55:34 +00007//
John Criswellb576c942003-10-20 19:43:21 +00008//===----------------------------------------------------------------------===//
Chris Lattnere7fb3602001-08-27 16:00:15 +00009//
10// This file defines target properties related to datatype size/offset/alignment
Chris Lattner0e7ac162004-02-26 08:02:17 +000011// information.
Chris Lattnere7fb3602001-08-27 16:00:15 +000012//
13// This structure should be created once, filled in if the defaults are not
14// correct and then passed around by const&. None of the members functions
15// require modification to the object.
16//
17//===----------------------------------------------------------------------===//
18
Vikram S. Adve0799fc42001-09-18 12:58:33 +000019#include "llvm/Target/TargetData.h"
Chris Lattner53a0c382003-04-24 19:09:05 +000020#include "llvm/Module.h"
Chris Lattnere7fb3602001-08-27 16:00:15 +000021#include "llvm/DerivedTypes.h"
Chris Lattner31bcdb82002-04-28 19:55:58 +000022#include "llvm/Constants.h"
Chris Lattner28977af2004-04-05 01:30:19 +000023#include "llvm/Support/GetElementPtrTypeIterator.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000024#include "llvm/Support/MathExtras.h"
Chris Lattnerec6478b2007-02-10 19:43:18 +000025#include "llvm/Support/ManagedStatic.h"
Owen Anderson8f60c562006-05-12 05:49:47 +000026#include "llvm/ADT/StringExtras.h"
Chris Lattnere7ea48c2005-03-13 19:04:41 +000027#include <algorithm>
Owen Anderson8f60c562006-05-12 05:49:47 +000028#include <cstdlib>
Owen Anderson2577c222006-05-12 07:01:44 +000029#include <sstream>
Chris Lattnerf0453282003-12-22 05:01:15 +000030using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000031
Misha Brukman5560c9d2003-08-18 14:43:39 +000032// Handle the Pass registration stuff necessary to use TargetData's.
Chris Lattneraa31ad02002-09-25 23:46:55 +000033namespace {
34 // Register the default SparcV9 implementation...
35 RegisterPass<TargetData> X("targetdata", "Target Data Layout");
36}
37
Chris Lattner58092e32007-01-20 22:35:55 +000038static inline void getTypeInfoABI(const Type *Ty, const TargetData *TD,
39 uint64_t &Size, unsigned char &Alignment);
40
41static inline void getTypeInfoPref(const Type *Ty, const TargetData *TD,
42 uint64_t &Size, unsigned char &Alignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000043
44//===----------------------------------------------------------------------===//
Chris Lattner0e7ac162004-02-26 08:02:17 +000045// Support for StructLayout
Chris Lattnere7fb3602001-08-27 16:00:15 +000046//===----------------------------------------------------------------------===//
47
Chris Lattner0e7ac162004-02-26 08:02:17 +000048StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
Chris Lattnere7fb3602001-08-27 16:00:15 +000049 StructAlignment = 0;
50 StructSize = 0;
Chris Lattner9182e3f2007-02-10 20:15:41 +000051 NumElements = ST->getNumElements();
Chris Lattnere7fb3602001-08-27 16:00:15 +000052
53 // Loop over each of the elements, placing them in memory...
Chris Lattner9182e3f2007-02-10 20:15:41 +000054 for (unsigned i = 0, e = NumElements; i != e; ++i) {
55 const Type *Ty = ST->getElementType(i);
Chris Lattnere7fb3602001-08-27 16:00:15 +000056 unsigned char A;
Vikram S. Advef66723f2002-05-19 15:28:02 +000057 unsigned TyAlign;
58 uint64_t TySize;
Chris Lattner58092e32007-01-20 22:35:55 +000059 getTypeInfoABI(Ty, &TD, TySize, A);
Andrew Lenharth38ecbf12006-12-08 18:06:16 +000060 TyAlign = ST->isPacked() ? 1 : A;
Chris Lattnere7fb3602001-08-27 16:00:15 +000061
Misha Brukman5560c9d2003-08-18 14:43:39 +000062 // Add padding if necessary to make the data element aligned properly...
Chris Lattnere7fb3602001-08-27 16:00:15 +000063 if (StructSize % TyAlign != 0)
64 StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding...
65
66 // Keep track of maximum alignment constraint
Chris Lattner697954c2002-01-20 22:54:45 +000067 StructAlignment = std::max(TyAlign, StructAlignment);
Chris Lattnere7fb3602001-08-27 16:00:15 +000068
Chris Lattner9182e3f2007-02-10 20:15:41 +000069 MemberOffsets[i] = StructSize;
Vikram S. Advef66723f2002-05-19 15:28:02 +000070 StructSize += TySize; // Consume space for this data item
Chris Lattnere7fb3602001-08-27 16:00:15 +000071 }
72
Chris Lattner4e840d42003-05-21 18:08:44 +000073 // Empty structures have alignment of 1 byte.
74 if (StructAlignment == 0) StructAlignment = 1;
75
Chris Lattnere7fb3602001-08-27 16:00:15 +000076 // Add padding to the end of the struct so that it could be put in an array
77 // and all array elements would be aligned correctly.
78 if (StructSize % StructAlignment != 0)
79 StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
Chris Lattnere7fb3602001-08-27 16:00:15 +000080}
81
Chris Lattnere7ea48c2005-03-13 19:04:41 +000082
83/// getElementContainingOffset - Given a valid offset into the structure,
84/// return the structure index that contains it.
85unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
Chris Lattner9182e3f2007-02-10 20:15:41 +000086 const uint64_t *SI =
87 std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset);
88 assert(SI != &MemberOffsets[0] && "Offset not in structure type!");
Chris Lattnere7ea48c2005-03-13 19:04:41 +000089 --SI;
90 assert(*SI <= Offset && "upper_bound didn't work");
Chris Lattner9182e3f2007-02-10 20:15:41 +000091 assert((SI == &MemberOffsets[0] || *(SI-1) < Offset) &&
92 (SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) &&
Chris Lattnere7ea48c2005-03-13 19:04:41 +000093 "Upper bound didn't work!");
Chris Lattner9182e3f2007-02-10 20:15:41 +000094 return SI-&MemberOffsets[0];
Chris Lattnere7ea48c2005-03-13 19:04:41 +000095}
96
Chris Lattnere7fb3602001-08-27 16:00:15 +000097//===----------------------------------------------------------------------===//
98// TargetData Class Implementation
99//===----------------------------------------------------------------------===//
100
Chris Lattneracbc07a2006-06-16 18:11:26 +0000101void TargetData::init(const std::string &TargetDescription) {
Owen Anderson8f60c562006-05-12 05:49:47 +0000102 std::string temp = TargetDescription;
103
104 LittleEndian = false;
Chris Lattner58092e32007-01-20 22:35:55 +0000105 PointerMemSize = 8;
106 PointerABIAlignment = 8;
Owen Anderson1027a532007-01-20 23:07:13 +0000107 DoubleABIAlignment = 0;
Chris Lattner58092e32007-01-20 22:35:55 +0000108 FloatABIAlignment = 4;
Owen Anderson1027a532007-01-20 23:07:13 +0000109 LongABIAlignment = 0;
Chris Lattner58092e32007-01-20 22:35:55 +0000110 IntABIAlignment = 4;
111 ShortABIAlignment = 2;
112 ByteABIAlignment = 1;
113 BoolABIAlignment = 1;
114 BoolPrefAlignment = BoolABIAlignment;
115 BytePrefAlignment = ByteABIAlignment;
116 ShortPrefAlignment = ShortABIAlignment;
117 IntPrefAlignment = IntABIAlignment;
Owen Anderson1027a532007-01-20 23:07:13 +0000118 LongPrefAlignment = 8;
Chris Lattner58092e32007-01-20 22:35:55 +0000119 FloatPrefAlignment = FloatABIAlignment;
Owen Anderson1027a532007-01-20 23:07:13 +0000120 DoublePrefAlignment = 8;
Chris Lattner58092e32007-01-20 22:35:55 +0000121 PointerPrefAlignment = PointerABIAlignment;
122 AggMinPrefAlignment = 0;
Owen Anderson8f60c562006-05-12 05:49:47 +0000123
Owen Andersond988b322006-05-20 00:24:56 +0000124 while (!temp.empty()) {
Owen Anderson8f60c562006-05-12 05:49:47 +0000125 std::string token = getToken(temp, "-");
126
Owen Anderson84cc6db2006-05-17 21:56:02 +0000127 char signal = getToken(token, ":")[0];
128
129 switch(signal) {
Owen Anderson8f60c562006-05-12 05:49:47 +0000130 case 'E':
Owen Anderson571a13f2006-05-12 06:06:55 +0000131 LittleEndian = false;
132 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000133 case 'e':
Owen Anderson571a13f2006-05-12 06:06:55 +0000134 LittleEndian = true;
135 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000136 case 'p':
Chris Lattner58092e32007-01-20 22:35:55 +0000137 PointerMemSize = atoi(getToken(token,":").c_str()) / 8;
138 PointerABIAlignment = atoi(getToken(token,":").c_str()) / 8;
139 PointerPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
140 if (PointerPrefAlignment == 0)
141 PointerPrefAlignment = PointerABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000142 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000143 case 'd':
Chris Lattner58092e32007-01-20 22:35:55 +0000144 DoubleABIAlignment = atoi(getToken(token,":").c_str()) / 8;
145 DoublePrefAlignment = atoi(getToken(token,":").c_str()) / 8;
146 if (DoublePrefAlignment == 0)
147 DoublePrefAlignment = DoubleABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000148 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000149 case 'f':
Chris Lattner58092e32007-01-20 22:35:55 +0000150 FloatABIAlignment = atoi(getToken(token, ":").c_str()) / 8;
151 FloatPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
152 if (FloatPrefAlignment == 0)
153 FloatPrefAlignment = FloatABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000154 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000155 case 'l':
Chris Lattner58092e32007-01-20 22:35:55 +0000156 LongABIAlignment = atoi(getToken(token, ":").c_str()) / 8;
157 LongPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
158 if (LongPrefAlignment == 0)
159 LongPrefAlignment = LongABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000160 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000161 case 'i':
Chris Lattner58092e32007-01-20 22:35:55 +0000162 IntABIAlignment = atoi(getToken(token, ":").c_str()) / 8;
163 IntPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
164 if (IntPrefAlignment == 0)
165 IntPrefAlignment = IntABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000166 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000167 case 's':
Chris Lattner58092e32007-01-20 22:35:55 +0000168 ShortABIAlignment = atoi(getToken(token, ":").c_str()) / 8;
169 ShortPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
170 if (ShortPrefAlignment == 0)
171 ShortPrefAlignment = ShortABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000172 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000173 case 'b':
Chris Lattner58092e32007-01-20 22:35:55 +0000174 ByteABIAlignment = atoi(getToken(token, ":").c_str()) / 8;
175 BytePrefAlignment = atoi(getToken(token,":").c_str()) / 8;
176 if (BytePrefAlignment == 0)
177 BytePrefAlignment = ByteABIAlignment;
Owen Anderson571a13f2006-05-12 06:06:55 +0000178 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000179 case 'B':
Chris Lattner58092e32007-01-20 22:35:55 +0000180 BoolABIAlignment = atoi(getToken(token, ":").c_str()) / 8;
181 BoolPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
182 if (BoolPrefAlignment == 0)
183 BoolPrefAlignment = BoolABIAlignment;
184 break;
185 case 'A':
186 AggMinPrefAlignment = atoi(getToken(token,":").c_str()) / 8;
Owen Anderson571a13f2006-05-12 06:06:55 +0000187 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000188 default:
Owen Anderson571a13f2006-05-12 06:06:55 +0000189 break;
Owen Anderson8f60c562006-05-12 05:49:47 +0000190 }
191 }
Owen Anderson1027a532007-01-20 23:07:13 +0000192
Reid Spencer26f23852007-01-26 08:11:39 +0000193 // Unless explicitly specified, the alignments for longs and doubles is
194 // capped by pointer size.
Owen Anderson1027a532007-01-20 23:07:13 +0000195 if (LongABIAlignment == 0)
196 LongABIAlignment = LongPrefAlignment = PointerMemSize;
197 if (DoubleABIAlignment == 0)
198 DoubleABIAlignment = DoublePrefAlignment = PointerMemSize;
Owen Anderson8f60c562006-05-12 05:49:47 +0000199}
200
Chris Lattner1790d442006-06-16 18:22:52 +0000201TargetData::TargetData(const Module *M) {
Reid Spencer26f23852007-01-26 08:11:39 +0000202 init(M->getDataLayout());
Chris Lattner53a0c382003-04-24 19:09:05 +0000203}
204
Chris Lattnerec6478b2007-02-10 19:43:18 +0000205/// LayoutInfo - The lazy cache of structure layout information maintained by
Chris Lattner9182e3f2007-02-10 20:15:41 +0000206/// TargetData. Note that the struct types must have been free'd before
207/// llvm_shutdown is called (and thus this is deallocated) because all the
208/// targets with cached elements should have been destroyed.
Chris Lattner8dff24f2006-01-14 00:07:34 +0000209///
Chris Lattnerec6478b2007-02-10 19:43:18 +0000210typedef std::pair<const TargetData*,const StructType*> LayoutKey;
Chris Lattnera12bd032007-02-10 20:18:06 +0000211typedef std::map<LayoutKey, StructLayout*> LayoutInfoTy;
212static ManagedStatic<LayoutInfoTy> LayoutInfo;
Chris Lattner0e7ac162004-02-26 08:02:17 +0000213
214
Chris Lattnere7fb3602001-08-27 16:00:15 +0000215TargetData::~TargetData() {
Chris Lattnerec6478b2007-02-10 19:43:18 +0000216 if (LayoutInfo.isConstructed()) {
Chris Lattner0e7ac162004-02-26 08:02:17 +0000217 // Remove any layouts for this TD.
Chris Lattnera12bd032007-02-10 20:18:06 +0000218 LayoutInfoTy &TheMap = *LayoutInfo;
219 LayoutInfoTy::iterator
Chris Lattnerec6478b2007-02-10 19:43:18 +0000220 I = TheMap.lower_bound(LayoutKey(this, (const StructType*)0));
221
Chris Lattnera12bd032007-02-10 20:18:06 +0000222 for (LayoutInfoTy::iterator E = TheMap.end();
Chris Lattner9182e3f2007-02-10 20:15:41 +0000223 I != E && I->first.first == this; ) {
224 I->second->~StructLayout();
225 free(I->second);
Chris Lattnerec6478b2007-02-10 19:43:18 +0000226 TheMap.erase(I++);
Chris Lattner9182e3f2007-02-10 20:15:41 +0000227 }
Chris Lattner0e7ac162004-02-26 08:02:17 +0000228 }
229}
230
Chris Lattner9182e3f2007-02-10 20:15:41 +0000231const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
Chris Lattnera12bd032007-02-10 20:18:06 +0000232 LayoutInfoTy &TheMap = *LayoutInfo;
Chris Lattner9182e3f2007-02-10 20:15:41 +0000233
Chris Lattnera12bd032007-02-10 20:18:06 +0000234 LayoutInfoTy::iterator I = TheMap.lower_bound(LayoutKey(this, Ty));
Chris Lattner9182e3f2007-02-10 20:15:41 +0000235 if (I != TheMap.end() && I->first.first == this && I->first.second == Ty)
236 return I->second;
237
238 // Otherwise, create the struct layout. Because it is variable length, we
239 // malloc it, then use placement new.
240 unsigned NumElts = Ty->getNumElements();
241 StructLayout *L =
242 (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1)*sizeof(uint64_t));
243 new (L) StructLayout(Ty, *this);
244
245 TheMap.insert(I, std::make_pair(LayoutKey(this, Ty), L));
246 return L;
247}
248
249/// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
250/// objects. If a TargetData object is alive when types are being refined and
251/// removed, this method must be called whenever a StructType is removed to
252/// avoid a dangling pointer in this cache.
253void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
254 if (!LayoutInfo.isConstructed()) return; // No cache.
255
Chris Lattnera12bd032007-02-10 20:18:06 +0000256 LayoutInfoTy::iterator I = LayoutInfo->find(LayoutKey(this, Ty));
Chris Lattner9182e3f2007-02-10 20:15:41 +0000257 if (I != LayoutInfo->end()) {
258 I->second->~StructLayout();
259 free(I->second);
260 LayoutInfo->erase(I);
261 }
262}
263
264
Owen Anderson2577c222006-05-12 07:01:44 +0000265std::string TargetData::getStringRepresentation() const {
266 std::stringstream repr;
267
268 if (LittleEndian)
269 repr << "e";
270 else
271 repr << "E";
272
Chris Lattner58092e32007-01-20 22:35:55 +0000273 repr << "-p:" << (PointerMemSize * 8) << ":" << (PointerABIAlignment * 8);
274 repr << "-d:" << (DoubleABIAlignment * 8) << ":"
275 << (DoublePrefAlignment * 8);
276 repr << "-f:" << (FloatABIAlignment * 8) << ":"
277 << (FloatPrefAlignment * 8);
278 repr << "-l:" << (LongABIAlignment * 8) << ":"
279 << (LongPrefAlignment * 8);
280 repr << "-i:" << (IntABIAlignment * 8) << ":"
281 << (IntPrefAlignment * 8);
282 repr << "-s:" << (ShortABIAlignment * 8) << ":"
283 << (ShortPrefAlignment * 8);
284 repr << "-b:" << (ByteABIAlignment * 8) << ":"
285 << (BytePrefAlignment * 8);
286 repr << "-B:" << (BoolABIAlignment * 8) << ":"
287 << (BoolPrefAlignment * 8);
288 repr << "-A:" << (AggMinPrefAlignment * 8);
Owen Anderson2577c222006-05-12 07:01:44 +0000289
290 return repr.str();
291}
292
Chris Lattner8dff24f2006-01-14 00:07:34 +0000293
Chris Lattner58092e32007-01-20 22:35:55 +0000294static inline void getTypeInfoABI(const Type *Ty, const TargetData *TD,
295 uint64_t &Size, unsigned char &Alignment) {
Chris Lattnerf59ce922001-12-13 00:46:11 +0000296 assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
Chris Lattnerf70c22b2004-06-17 18:19:28 +0000297 switch (Ty->getTypeID()) {
Reid Spencera54b7cb2007-01-12 07:05:14 +0000298 case Type::IntegerTyID: {
299 unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth();
300 if (BitWidth <= 8) {
Chris Lattner58092e32007-01-20 22:35:55 +0000301 Size = 1; Alignment = TD->getByteABIAlignment();
Reid Spencera54b7cb2007-01-12 07:05:14 +0000302 } else if (BitWidth <= 16) {
Chris Lattner58092e32007-01-20 22:35:55 +0000303 Size = 2; Alignment = TD->getShortABIAlignment();
Reid Spencera54b7cb2007-01-12 07:05:14 +0000304 } else if (BitWidth <= 32) {
Chris Lattner58092e32007-01-20 22:35:55 +0000305 Size = 4; Alignment = TD->getIntABIAlignment();
Reid Spencera54b7cb2007-01-12 07:05:14 +0000306 } else if (BitWidth <= 64) {
Chris Lattner58092e32007-01-20 22:35:55 +0000307 Size = 8; Alignment = TD->getLongABIAlignment();
Reid Spencerd2a988c2007-02-05 23:51:43 +0000308 } else {
309 Size = ((BitWidth + 7) / 8) & ~1;
310 Alignment = TD->getLongABIAlignment();
311 }
Reid Spencera54b7cb2007-01-12 07:05:14 +0000312 return;
313 }
Chris Lattner58092e32007-01-20 22:35:55 +0000314 case Type::VoidTyID: Size = 1; Alignment = TD->getByteABIAlignment(); return;
315 case Type::FloatTyID: Size = 4; Alignment = TD->getFloatABIAlignment(); return;
316 case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleABIAlignment(); return;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000317 case Type::LabelTyID:
318 case Type::PointerTyID:
Chris Lattner58092e32007-01-20 22:35:55 +0000319 Size = TD->getPointerSize(); Alignment = TD->getPointerABIAlignment();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000320 return;
321 case Type::ArrayTyID: {
Chris Lattner59b00672004-07-01 17:32:59 +0000322 const ArrayType *ATy = cast<ArrayType>(Ty);
Chris Lattner58092e32007-01-20 22:35:55 +0000323 getTypeInfoABI(ATy->getElementType(), TD, Size, Alignment);
Brian Gaekee0e35892004-07-02 07:01:31 +0000324 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
Chris Lattner59b00672004-07-01 17:32:59 +0000325 Size = AlignedSize*ATy->getNumElements();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000326 return;
327 }
Chris Lattner527efc62004-12-01 17:14:28 +0000328 case Type::PackedTyID: {
329 const PackedType *PTy = cast<PackedType>(Ty);
Chris Lattner58092e32007-01-20 22:35:55 +0000330 getTypeInfoABI(PTy->getElementType(), TD, Size, Alignment);
Chris Lattner527efc62004-12-01 17:14:28 +0000331 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
332 Size = AlignedSize*PTy->getNumElements();
Evan Chenge668bda2006-03-31 22:33:42 +0000333 // FIXME: The alignments of specific packed types are target dependent.
334 // For now, just set it to be equal to Size.
Chris Lattner0aab36f2006-04-03 23:14:49 +0000335 Alignment = Size;
Chris Lattner527efc62004-12-01 17:14:28 +0000336 return;
337 }
Chris Lattnere7fb3602001-08-27 16:00:15 +0000338 case Type::StructTyID: {
339 // Get the layout annotation... which is lazily created on demand.
Chris Lattner59b00672004-07-01 17:32:59 +0000340 const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
Chris Lattnerb0c39a32007-02-10 19:59:22 +0000341 Size = Layout->getSizeInBytes(); Alignment = Layout->getAlignment();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000342 return;
343 }
Misha Brukmanf976c852005-04-21 22:55:34 +0000344
Chris Lattnere7fb3602001-08-27 16:00:15 +0000345 default:
346 assert(0 && "Bad type for getTypeInfo!!!");
347 return;
348 }
349}
350
Chris Lattner58092e32007-01-20 22:35:55 +0000351static inline void getTypeInfoPref(const Type *Ty, const TargetData *TD,
352 uint64_t &Size, unsigned char &Alignment) {
353 assert(Ty->isSized() && "Cannot getTypeInfoPref() on a type that is unsized!");
354 switch (Ty->getTypeID()) {
355 case Type::IntegerTyID: {
356 unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth();
357 if (BitWidth <= 8) {
358 Size = 1; Alignment = TD->getBytePrefAlignment();
359 } else if (BitWidth <= 16) {
360 Size = 2; Alignment = TD->getShortPrefAlignment();
361 } else if (BitWidth <= 32) {
362 Size = 4; Alignment = TD->getIntPrefAlignment();
363 } else if (BitWidth <= 64) {
364 Size = 8; Alignment = TD->getLongPrefAlignment();
365 } else
366 assert(0 && "Integer types > 64 bits not supported.");
367 return;
368 }
369 case Type::VoidTyID:
370 Size = 1; Alignment = TD->getBytePrefAlignment();
371 return;
372 case Type::FloatTyID:
373 Size = 4; Alignment = TD->getFloatPrefAlignment();
374 return;
375 case Type::DoubleTyID:
376 Size = 8; Alignment = TD->getDoublePrefAlignment();
377 return;
378 case Type::LabelTyID:
379 case Type::PointerTyID:
380 Size = TD->getPointerSize(); Alignment = TD->getPointerPrefAlignment();
381 return;
382 case Type::ArrayTyID: {
383 const ArrayType *ATy = cast<ArrayType>(Ty);
384 getTypeInfoPref(ATy->getElementType(), TD, Size, Alignment);
385 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
386 Size = AlignedSize*ATy->getNumElements();
387 return;
388 }
389 case Type::PackedTyID: {
390 const PackedType *PTy = cast<PackedType>(Ty);
391 getTypeInfoPref(PTy->getElementType(), TD, Size, Alignment);
392 unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
393 Size = AlignedSize*PTy->getNumElements();
394 // FIXME: The alignments of specific packed types are target dependent.
395 // For now, just set it to be equal to Size.
396 Alignment = Size;
397 return;
398 }
399 case Type::StructTyID: {
400 // Get the layout annotation... which is lazily created on demand;
401 // enforce minimum aggregate alignment.
402 const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
Chris Lattnerb0c39a32007-02-10 19:59:22 +0000403 Size = Layout->getSizeInBytes();
404 Alignment = std::max(Layout->getAlignment(),
405 (const unsigned int)TD->getAggMinPrefAlignment());
Chris Lattner58092e32007-01-20 22:35:55 +0000406 return;
407 }
408
409 default:
410 assert(0 && "Bad type for getTypeInfoPref!!!");
411 return;
412 }
413}
414
415
Vikram S. Advef66723f2002-05-19 15:28:02 +0000416uint64_t TargetData::getTypeSize(const Type *Ty) const {
417 uint64_t Size;
418 unsigned char Align;
Chris Lattner58092e32007-01-20 22:35:55 +0000419 getTypeInfoABI(Ty, this, Size, Align);
Chris Lattnere7fb3602001-08-27 16:00:15 +0000420 return Size;
421}
422
Reid Spencer7c292432007-01-20 23:32:04 +0000423uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const {
424 if (Ty->isInteger())
425 return cast<IntegerType>(Ty)->getBitWidth();
426
427 uint64_t Size;
428 unsigned char Align;
429 getTypeInfoABI(Ty, this, Size, Align);
430 return Size * 8;
431}
432
Chris Lattner58092e32007-01-20 22:35:55 +0000433unsigned char TargetData::getTypeAlignmentABI(const Type *Ty) const {
Vikram S. Advef66723f2002-05-19 15:28:02 +0000434 uint64_t Size;
435 unsigned char Align;
Chris Lattner58092e32007-01-20 22:35:55 +0000436 getTypeInfoABI(Ty, this, Size, Align);
437 return Align;
438}
439
440unsigned char TargetData::getTypeAlignmentPref(const Type *Ty) const {
441 uint64_t Size;
442 unsigned char Align;
443 getTypeInfoPref(Ty, this, Size, Align);
Chris Lattnere7fb3602001-08-27 16:00:15 +0000444 return Align;
445}
446
Evan Chengde268f72007-01-24 07:03:39 +0000447unsigned char TargetData::getPreferredTypeAlignmentShift(const Type *Ty) const {
Evan Cheng778900a2007-01-22 23:08:19 +0000448 unsigned Align = getTypeAlignmentPref(Ty);
Chris Lattnerd2b0bb42004-08-17 19:13:00 +0000449 assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
Chris Lattner0561b3f2005-08-02 19:26:06 +0000450 return Log2_32(Align);
Chris Lattnerd2b0bb42004-08-17 19:13:00 +0000451}
452
Chris Lattnerf0453282003-12-22 05:01:15 +0000453/// getIntPtrType - Return an unsigned integer type that is the same size or
454/// greater to the host pointer size.
455const Type *TargetData::getIntPtrType() const {
456 switch (getPointerSize()) {
457 default: assert(0 && "Unknown pointer size!");
Reid Spencer47857812006-12-31 05:55:36 +0000458 case 2: return Type::Int16Ty;
459 case 4: return Type::Int32Ty;
460 case 8: return Type::Int64Ty;
Chris Lattnerf0453282003-12-22 05:01:15 +0000461 }
462}
463
464
Chris Lattnerddce8d22007-02-10 19:33:15 +0000465uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,
466 unsigned NumIndices) const {
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000467 const Type *Ty = ptrTy;
468 assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
Vikram S. Advef66723f2002-05-19 15:28:02 +0000469 uint64_t Result = 0;
Chris Lattnere7fb3602001-08-27 16:00:15 +0000470
Chris Lattnerddce8d22007-02-10 19:33:15 +0000471 generic_gep_type_iterator<Value* const*>
472 TI = gep_type_begin(ptrTy, Indices, Indices+NumIndices);
473 for (unsigned CurIDX = 0; CurIDX != NumIndices; ++CurIDX, ++TI) {
Chris Lattner28977af2004-04-05 01:30:19 +0000474 if (const StructType *STy = dyn_cast<StructType>(*TI)) {
Chris Lattnerddce8d22007-02-10 19:33:15 +0000475 assert(Indices[CurIDX]->getType() == Type::Int32Ty &&"Illegal struct idx");
476 unsigned FieldNo = cast<ConstantInt>(Indices[CurIDX])->getZExtValue();
Chris Lattnere7fb3602001-08-27 16:00:15 +0000477
478 // Get structure layout information...
479 const StructLayout *Layout = getStructLayout(STy);
480
481 // Add in the offset, as calculated by the structure layout info...
Chris Lattnerb1919e22007-02-10 19:55:17 +0000482 Result += Layout->getElementOffset(FieldNo);
Vikram S. Adveed0030e2002-08-04 20:52:39 +0000483
Chris Lattnere7fb3602001-08-27 16:00:15 +0000484 // Update Ty to refer to current element
Chris Lattnerd21cd802004-02-09 04:37:31 +0000485 Ty = STy->getElementType(FieldNo);
Chris Lattner28977af2004-04-05 01:30:19 +0000486 } else {
487 // Update Ty to refer to current element
488 Ty = cast<SequentialType>(Ty)->getElementType();
489
490 // Get the array index and the size of each array element.
Chris Lattnerddce8d22007-02-10 19:33:15 +0000491 int64_t arrayIdx = cast<ConstantInt>(Indices[CurIDX])->getSExtValue();
Chris Lattner28977af2004-04-05 01:30:19 +0000492 Result += arrayIdx * (int64_t)getTypeSize(Ty);
Chris Lattnere7fb3602001-08-27 16:00:15 +0000493 }
494 }
495
496 return Result;
497}
Brian Gaeked0fde302003-11-11 22:41:34 +0000498
Devang Patelf9c197e2006-10-24 20:32:14 +0000499/// getPreferredAlignmentLog - Return the preferred alignment of the
500/// specified global, returned in log form. This includes an explicitly
501/// requested alignment (if the global has one).
502unsigned TargetData::getPreferredAlignmentLog(const GlobalVariable *GV) const {
503 const Type *ElemType = GV->getType()->getElementType();
Evan Chengde268f72007-01-24 07:03:39 +0000504 unsigned Alignment = getPreferredTypeAlignmentShift(ElemType);
Devang Patelf9c197e2006-10-24 20:32:14 +0000505 if (GV->getAlignment() > (1U << Alignment))
506 Alignment = Log2_32(GV->getAlignment());
507
508 if (GV->hasInitializer()) {
Devang Patelf9c197e2006-10-24 20:32:14 +0000509 if (Alignment < 4) {
510 // If the global is not external, see if it is large. If so, give it a
511 // larger alignment.
512 if (getTypeSize(ElemType) > 128)
513 Alignment = 4; // 16-byte alignment.
514 }
515 }
516 return Alignment;
517}
518