blob: 3803dbb245cc0d74fbe2200551aed6c3ed361c7b [file] [log] [blame]
Anders Carlsson79474332009-07-18 20:20:21 +00001//=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "RecordLayoutBuilder.h"
11
12#include "clang/AST/Attr.h"
13#include "clang/AST/Decl.h"
Anders Carlsson6d9f6f32009-07-19 00:18:47 +000014#include "clang/AST/DeclCXX.h"
Anders Carlsson4f516282009-07-18 20:50:59 +000015#include "clang/AST/DeclObjC.h"
Anders Carlsson79474332009-07-18 20:20:21 +000016#include "clang/AST/Expr.h"
Anders Carlsson79474332009-07-18 20:20:21 +000017#include "clang/Basic/TargetInfo.h"
Daniel Dunbaraa423af2010-04-08 02:59:49 +000018#include "llvm/Support/Format.h"
19#include "llvm/ADT/SmallSet.h"
20#include "llvm/Support/MathExtras.h"
Anders Carlsson79474332009-07-18 20:20:21 +000021
22using namespace clang;
23
Anders Carlsson5efc56e2010-04-16 15:07:51 +000024ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Context)
25 : Context(Context), Size(0), Alignment(8), Packed(false),
26 UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false),
Anders Carlsson1d1e4cf2010-05-26 05:25:15 +000027 NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0),
28 PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0),
Anders Carlsson15837f82010-05-08 23:06:26 +000029 SizeOfLargestEmptySubobject(0) { }
Mike Stump3dc7eb92009-07-30 00:22:38 +000030
Mike Stumpd8fe7b22009-08-05 22:37:18 +000031/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
32/// no other data.
Anders Carlsson81430692009-09-22 03:02:06 +000033bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
Mike Stumpd8fe7b22009-08-05 22:37:18 +000034 // FIXME: Audit the corners
35 if (!RD->isDynamicClass())
36 return false;
Anders Carlsson5efc56e2010-04-16 15:07:51 +000037 const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
38 if (BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0))
Mike Stumpd8fe7b22009-08-05 22:37:18 +000039 return true;
40 return false;
41}
42
Anders Carlsson15837f82010-05-08 23:06:26 +000043void
44ASTRecordLayoutBuilder::ComputeEmptySubobjectSizes(const CXXRecordDecl *RD) {
45 // Check the bases.
46 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
47 E = RD->bases_end(); I != E; ++I) {
48 const CXXRecordDecl *BaseDecl =
49 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
50
51 uint64_t EmptySize = 0;
52 const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
53 if (BaseDecl->isEmpty()) {
54 // If the class decl is empty, get its size.
55 EmptySize = Layout.getSize();
56 } else {
57 // Otherwise, we get the largest empty subobject for the decl.
58 EmptySize = Layout.getSizeOfLargestEmptySubobject();
59 }
60
61 SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject,
62 EmptySize);
63 }
64
65 // Check the fields.
66 for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
67 I != E; ++I) {
68 const FieldDecl *FD = *I;
69
70 const RecordType *RT =
71 Context.getBaseElementType(FD->getType())->getAs<RecordType>();
72
73 // We only care about record types.
74 if (!RT)
75 continue;
76
77 uint64_t EmptySize = 0;
78 const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl());
79 const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);
80 if (MemberDecl->isEmpty()) {
81 // If the class decl is empty, get its size.
82 EmptySize = Layout.getSize();
83 } else {
84 // Otherwise, we get the largest empty subobject for the decl.
85 EmptySize = Layout.getSizeOfLargestEmptySubobject();
86 }
87
88 SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject,
89 EmptySize);
90 }
91}
92
Anders Carlsson81430692009-09-22 03:02:06 +000093void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
Daniel Dunbaraa423af2010-04-08 02:59:49 +000094 const ASTRecordLayout::PrimaryBaseInfo &BaseInfo =
Anders Carlsson5efc56e2010-04-16 15:07:51 +000095 Context.getASTRecordLayout(RD).getPrimaryBaseInfo();
Daniel Dunbaraa423af2010-04-08 02:59:49 +000096
Anders Carlsson81430692009-09-22 03:02:06 +000097 // If the record has a primary base class that is virtual, add it to the set
98 // of primary bases.
Anders Carlssona30c0d32009-11-27 22:14:40 +000099 if (BaseInfo.isVirtual())
100 IndirectPrimaryBases.insert(BaseInfo.getBase());
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000101
Anders Carlsson81430692009-09-22 03:02:06 +0000102 // Now traverse all bases and find primary bases for them.
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000103 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000104 e = RD->bases_end(); i != e; ++i) {
Sebastian Redl1054fae2009-10-25 17:03:50 +0000105 assert(!i->getType()->isDependentType() &&
106 "Cannot layout class with dependent bases.");
Mike Stump11289f42009-09-09 15:08:12 +0000107 const CXXRecordDecl *Base =
Mike Stump78696a72009-08-11 04:03:59 +0000108 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000109
Mike Stump78696a72009-08-11 04:03:59 +0000110 // Only bases with virtual bases participate in computing the
111 // indirect primary virtual base classes.
Mike Stumpc2f591b2009-08-13 22:53:07 +0000112 if (Base->getNumVBases())
Anders Carlsson81430692009-09-22 03:02:06 +0000113 IdentifyPrimaryBases(Base);
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000114 }
115}
116
Anders Carlsson81430692009-09-22 03:02:06 +0000117void
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000118ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
Anders Carlssonf2fa75b2010-03-11 03:39:12 +0000119 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000120 E = RD->bases_end(); I != E; ++I) {
Anders Carlssonf2fa75b2010-03-11 03:39:12 +0000121 assert(!I->getType()->isDependentType() &&
Sebastian Redl1054fae2009-10-25 17:03:50 +0000122 "Cannot layout class with dependent bases.");
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000123
Mike Stump11289f42009-09-09 15:08:12 +0000124 const CXXRecordDecl *Base =
Anders Carlssonf2fa75b2010-03-11 03:39:12 +0000125 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000126
Anders Carlssonf2fa75b2010-03-11 03:39:12 +0000127 // Check if this is a nearly empty virtual base.
128 if (I->isVirtual() && IsNearlyEmpty(Base)) {
129 // If it's not an indirect primary base, then we've found our primary
130 // base.
Anders Carlsson81430692009-09-22 03:02:06 +0000131 if (!IndirectPrimaryBases.count(Base)) {
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000132 PrimaryBase = Base;
133 PrimaryBaseIsVirtual = true;
Mike Stump6f3793b2009-08-12 21:50:08 +0000134 return;
135 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000136
Anders Carlssonf2fa75b2010-03-11 03:39:12 +0000137 // Is this the first nearly empty virtual base?
138 if (!FirstNearlyEmptyVBase)
139 FirstNearlyEmptyVBase = Base;
Mike Stump6f3793b2009-08-12 21:50:08 +0000140 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000141
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000142 SelectPrimaryVBase(Base);
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000143 if (PrimaryBase)
Zhongxing Xuec345b72010-02-15 04:28:35 +0000144 return;
Mike Stump6f3793b2009-08-12 21:50:08 +0000145 }
146}
147
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000148/// DeterminePrimaryBase - Determine the primary base of the given class.
149void ASTRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
150 // If the class isn't dynamic, it won't have a primary base.
151 if (!RD->isDynamicClass())
152 return;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000153
Anders Carlsson81430692009-09-22 03:02:06 +0000154 // Compute all the primary virtual bases for all of our direct and
Mike Stump590a7c72009-08-13 23:26:06 +0000155 // indirect bases, and record all their primary virtual base classes.
Mike Stump590a7c72009-08-13 23:26:06 +0000156 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000157 e = RD->bases_end(); i != e; ++i) {
Sebastian Redl1054fae2009-10-25 17:03:50 +0000158 assert(!i->getType()->isDependentType() &&
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000159 "Cannot lay out class with dependent bases.");
Mike Stump11289f42009-09-09 15:08:12 +0000160 const CXXRecordDecl *Base =
Mike Stump590a7c72009-08-13 23:26:06 +0000161 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
Anders Carlsson81430692009-09-22 03:02:06 +0000162 IdentifyPrimaryBases(Base);
Mike Stump590a7c72009-08-13 23:26:06 +0000163 }
164
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000165 // If the record has a dynamic base class, attempt to choose a primary base
166 // class. It is the first (in direct base class order) non-virtual dynamic
Anders Carlsson81430692009-09-22 03:02:06 +0000167 // base class, if one exists.
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000168 for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000169 e = RD->bases_end(); i != e; ++i) {
Anders Carlsson03ff3792009-11-27 22:05:05 +0000170 // Ignore virtual bases.
171 if (i->isVirtual())
172 continue;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000173
Anders Carlsson03ff3792009-11-27 22:05:05 +0000174 const CXXRecordDecl *Base =
175 cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
176
177 if (Base->isDynamicClass()) {
178 // We found it.
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000179 PrimaryBase = Base;
180 PrimaryBaseIsVirtual = false;
Anders Carlsson03ff3792009-11-27 22:05:05 +0000181 return;
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000182 }
183 }
184
185 // Otherwise, it is the first nearly empty virtual base that is not an
Mike Stump78696a72009-08-11 04:03:59 +0000186 // indirect primary virtual base class, if one exists.
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000187 if (RD->getNumVBases() != 0) {
188 SelectPrimaryVBase(RD);
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000189 if (PrimaryBase)
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000190 return;
191 }
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000192
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000193 // Otherwise, it is the first nearly empty virtual base that is not an
194 // indirect primary virtual base class, if one exists.
195 if (FirstNearlyEmptyVBase) {
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000196 PrimaryBase = FirstNearlyEmptyVBase;
197 PrimaryBaseIsVirtual = true;
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000198 return;
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000199 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000200
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000201 // Otherwise there is no primary base class.
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000202 assert(!PrimaryBase && "Should not get here with a primary base!");
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000203
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000204 // Allocate the virtual table pointer at offset zero.
205 assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000206
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000207 // Update the size.
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000208 Size += Context.Target.getPointerWidth(0);
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000209 DataSize = Size;
210
211 // Update the alignment.
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000212 UpdateAlignment(Context.Target.getPointerAlign(0));
Mike Stumpd8fe7b22009-08-05 22:37:18 +0000213}
214
Anders Carlsson09ffa322010-03-10 22:21:28 +0000215void
216ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000217 // First, determine the primary base class.
218 DeterminePrimaryBase(RD);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000219
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000220 // If we have a primary base class, lay it out.
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000221 if (PrimaryBase) {
222 if (PrimaryBaseIsVirtual) {
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000223 // We have a virtual primary base, insert it as an indirect primary base.
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000224 IndirectPrimaryBases.insert(PrimaryBase);
Anders Carlssonfe900962010-03-11 05:42:17 +0000225
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000226 assert(!VisitedVirtualBases.count(PrimaryBase) &&
227 "vbase already visited!");
228 VisitedVirtualBases.insert(PrimaryBase);
Anders Carlsson291279e2010-04-10 18:42:27 +0000229
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000230 LayoutVirtualBase(PrimaryBase);
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000231 } else
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000232 LayoutNonVirtualBase(PrimaryBase);
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000233 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000234
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000235 // Now lay out the non-virtual bases.
236 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000237 E = RD->bases_end(); I != E; ++I) {
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000238
239 // Ignore virtual bases.
240 if (I->isVirtual())
241 continue;
242
243 const CXXRecordDecl *Base =
244 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
245
246 // Skip the primary base.
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000247 if (Base == PrimaryBase && PrimaryBaseIsVirtual)
Anders Carlsson8630b5b2010-03-11 00:15:35 +0000248 continue;
249
250 // Lay out the base.
251 LayoutNonVirtualBase(Base);
Anders Carlsson09ffa322010-03-10 22:21:28 +0000252 }
253}
254
255void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
Anders Carlsson0d0b5882010-03-10 22:26:24 +0000256 // Layout the base.
257 uint64_t Offset = LayoutBase(RD);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000258
Anders Carlsson0d0b5882010-03-10 22:26:24 +0000259 // Add its base class offset.
Anders Carlsson6a848892010-03-11 04:10:39 +0000260 if (!Bases.insert(std::make_pair(RD, Offset)).second)
261 assert(false && "Added same base offset more than once!");
Anders Carlsson09ffa322010-03-10 22:21:28 +0000262}
Mike Stump2b84dd32009-11-05 04:02:15 +0000263
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000264void
Anders Carlssonea7b1822010-04-15 16:12:58 +0000265ASTRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD,
266 uint64_t Offset,
267 const CXXRecordDecl *MostDerivedClass) {
268 // We already have the offset for the primary base of the most derived class.
269 if (RD != MostDerivedClass) {
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000270 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssonea7b1822010-04-15 16:12:58 +0000271 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
272
273 // If this is a primary virtual base and we haven't seen it before, add it.
274 if (PrimaryBase && Layout.getPrimaryBaseWasVirtual() &&
275 !VBases.count(PrimaryBase))
276 VBases.insert(std::make_pair(PrimaryBase, Offset));
277 }
278
279 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
280 E = RD->bases_end(); I != E; ++I) {
281 assert(!I->getType()->isDependentType() &&
282 "Cannot layout class with dependent bases.");
283
284 const CXXRecordDecl *BaseDecl =
285 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
286
287 if (!BaseDecl->getNumVBases()) {
288 // This base isn't interesting since it doesn't have any virtual bases.
289 continue;
290 }
291
292 // Compute the offset of this base.
293 uint64_t BaseOffset;
294
295 if (I->isVirtual()) {
296 // If we don't know this vbase yet, don't visit it. It will be visited
297 // later.
298 if (!VBases.count(BaseDecl)) {
299 continue;
300 }
301
302 // Check if we've already visited this base.
303 if (!VisitedVirtualBases.insert(BaseDecl))
304 continue;
305
306 // We want the vbase offset from the class we're currently laying out.
307 BaseOffset = VBases[BaseDecl];
308 } else if (RD == MostDerivedClass) {
309 // We want the base offset from the class we're currently laying out.
310 assert(Bases.count(BaseDecl) && "Did not find base!");
311 BaseOffset = Bases[BaseDecl];
312 } else {
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000313 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssonea7b1822010-04-15 16:12:58 +0000314 BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
315 }
316
317 AddPrimaryVirtualBaseOffsets(BaseDecl, BaseOffset, MostDerivedClass);
318 }
319}
320
321void
Anders Carlssonde710c92010-03-11 04:33:54 +0000322ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
Anders Carlssonea7b1822010-04-15 16:12:58 +0000323 const CXXRecordDecl *MostDerivedClass) {
Anders Carlssonde710c92010-03-11 04:33:54 +0000324 const CXXRecordDecl *PrimaryBase;
Anders Carlsson291279e2010-04-10 18:42:27 +0000325 bool PrimaryBaseIsVirtual;
Anders Carlssonfe900962010-03-11 05:42:17 +0000326
Anders Carlsson291279e2010-04-10 18:42:27 +0000327 if (MostDerivedClass == RD) {
Anders Carlssond20e7cd2010-05-26 05:20:58 +0000328 PrimaryBase = this->PrimaryBase;
329 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
Anders Carlsson291279e2010-04-10 18:42:27 +0000330 } else {
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000331 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssonde710c92010-03-11 04:33:54 +0000332 PrimaryBase = Layout.getPrimaryBase();
Anders Carlsson291279e2010-04-10 18:42:27 +0000333 PrimaryBaseIsVirtual = Layout.getPrimaryBaseWasVirtual();
334 }
335
Anders Carlssonf7b7a1e2010-03-11 04:24:02 +0000336 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
337 E = RD->bases_end(); I != E; ++I) {
338 assert(!I->getType()->isDependentType() &&
Sebastian Redl1054fae2009-10-25 17:03:50 +0000339 "Cannot layout class with dependent bases.");
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000340
Mike Stump11289f42009-09-09 15:08:12 +0000341 const CXXRecordDecl *Base =
Anders Carlssonf7b7a1e2010-03-11 04:24:02 +0000342 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
343
344 if (I->isVirtual()) {
Anders Carlsson291279e2010-04-10 18:42:27 +0000345 if (PrimaryBase != Base || !PrimaryBaseIsVirtual) {
346 bool IndirectPrimaryBase = IndirectPrimaryBases.count(Base);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000347
Anders Carlsson291279e2010-04-10 18:42:27 +0000348 // Only lay out the virtual base if it's not an indirect primary base.
349 if (!IndirectPrimaryBase) {
350 // Only visit virtual bases once.
351 if (!VisitedVirtualBases.insert(Base))
352 continue;
353
Anders Carlssonfe900962010-03-11 05:42:17 +0000354 LayoutVirtualBase(Base);
Anders Carlsson6a848892010-03-11 04:10:39 +0000355 }
Mike Stump2b84dd32009-11-05 04:02:15 +0000356 }
Mike Stumpc2f591b2009-08-13 22:53:07 +0000357 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000358
Anders Carlssonf7b7a1e2010-03-11 04:24:02 +0000359 if (!Base->getNumVBases()) {
360 // This base isn't interesting since it doesn't have any virtual bases.
361 continue;
Mike Stump996576f32009-08-16 19:04:13 +0000362 }
Anders Carlssonf7b7a1e2010-03-11 04:24:02 +0000363
Anders Carlssonea7b1822010-04-15 16:12:58 +0000364 LayoutVirtualBases(Base, MostDerivedClass);
Mike Stump6b2556f2009-08-06 13:41:24 +0000365 }
366}
367
Anders Carlsson09ffa322010-03-10 22:21:28 +0000368void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
Anders Carlsson0d0b5882010-03-10 22:26:24 +0000369 // Layout the base.
370 uint64_t Offset = LayoutBase(RD);
371
372 // Add its base class offset.
Anders Carlsson6a848892010-03-11 04:10:39 +0000373 if (!VBases.insert(std::make_pair(RD, Offset)).second)
374 assert(false && "Added same vbase offset more than once!");
Anders Carlsson09ffa322010-03-10 22:21:28 +0000375}
376
377uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000378 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlsson09ffa322010-03-10 22:21:28 +0000379
380 // If we have an empty base class, try to place it at offset 0.
Anders Carlssond626cb72010-05-10 15:26:14 +0000381 if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0, /*CheckVBases=*/false)) {
Anders Carlsson09ffa322010-03-10 22:21:28 +0000382 // We were able to place the class at offset 0.
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000383 UpdateEmptyClassOffsets(RD, 0, /*UpdateVBases=*/false);
Anders Carlsson09ffa322010-03-10 22:21:28 +0000384
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000385 Size = std::max(Size, Layout.getSize());
Anders Carlsson09ffa322010-03-10 22:21:28 +0000386
387 return 0;
388 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000389
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000390 unsigned BaseAlign = Layout.getNonVirtualAlign();
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000391
Anders Carlsson09ffa322010-03-10 22:21:28 +0000392 // Round up the current record size to the base's alignment boundary.
393 uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000394
Anders Carlsson09ffa322010-03-10 22:21:28 +0000395 // Try to place the base.
396 while (true) {
Anders Carlssond626cb72010-05-10 15:26:14 +0000397 if (canPlaceRecordAtOffset(RD, Offset, /*CheckVBases=*/false))
Anders Carlsson09ffa322010-03-10 22:21:28 +0000398 break;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000399
Anders Carlsson09ffa322010-03-10 22:21:28 +0000400 Offset += BaseAlign;
401 }
402
403 if (!RD->isEmpty()) {
404 // Update the data size.
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000405 DataSize = Offset + Layout.getNonVirtualSize();
Anders Carlsson09ffa322010-03-10 22:21:28 +0000406
407 Size = std::max(Size, DataSize);
408 } else
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000409 Size = std::max(Size, Offset + Layout.getSize());
Anders Carlsson09ffa322010-03-10 22:21:28 +0000410
411 // Remember max struct/class alignment.
412 UpdateAlignment(BaseAlign);
413
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000414 UpdateEmptyClassOffsets(RD, Offset, /*UpdateVBases=*/false);
Anders Carlsson09ffa322010-03-10 22:21:28 +0000415 return Offset;
416}
417
Anders Carlssond626cb72010-05-10 15:26:14 +0000418bool
419ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
420 uint64_t Offset,
421 bool CheckVBases) const {
Anders Carlssonf24b18f2009-09-24 03:22:10 +0000422 // Look for an empty class with the same type at the same offset.
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000423 for (EmptyClassOffsetsTy::const_iterator I =
424 EmptyClassOffsets.lower_bound(Offset),
425 E = EmptyClassOffsets.upper_bound(Offset); I != E; ++I) {
426
Anders Carlssonf24b18f2009-09-24 03:22:10 +0000427 if (I->second == RD)
428 return false;
429 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000430
Anders Carlsson82828a32010-05-09 05:03:38 +0000431 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000432
433 // Check bases.
434 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000435 E = RD->bases_end(); I != E; ++I) {
Sebastian Redl1054fae2009-10-25 17:03:50 +0000436 assert(!I->getType()->isDependentType() &&
437 "Cannot layout class with dependent bases.");
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000438 if (I->isVirtual())
439 continue;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000440
Anders Carlsson82828a32010-05-09 05:03:38 +0000441 const CXXRecordDecl *BaseDecl =
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000442 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
443
Anders Carlsson82828a32010-05-09 05:03:38 +0000444 uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000445
Anders Carlssond626cb72010-05-10 15:26:14 +0000446 if (!canPlaceRecordAtOffset(BaseDecl, Offset + BaseOffset,
447 /*CheckVBases=*/false))
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000448 return false;
449 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000450
Anders Carlssond7d358a2009-09-25 15:39:00 +0000451 // Check fields.
452 unsigned FieldNo = 0;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000453 for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
Anders Carlssond7d358a2009-09-25 15:39:00 +0000454 I != E; ++I, ++FieldNo) {
455 const FieldDecl *FD = *I;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000456
Anders Carlsson82828a32010-05-09 05:03:38 +0000457 uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000458
Anders Carlssond7d358a2009-09-25 15:39:00 +0000459 if (!canPlaceFieldAtOffset(FD, Offset + FieldOffset))
460 return false;
461 }
462
Anders Carlssond626cb72010-05-10 15:26:14 +0000463 if (CheckVBases) {
464 // FIXME: virtual bases.
465 }
466
Anders Carlsson6522b052009-09-24 03:13:30 +0000467 return true;
468}
469
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000470bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
Anders Carlsson6f95c702009-09-25 00:02:51 +0000471 uint64_t Offset) const {
Anders Carlsson4bf82142009-09-25 01:23:32 +0000472 QualType T = FD->getType();
473 if (const RecordType *RT = T->getAs<RecordType>()) {
Anders Carlsson6f95c702009-09-25 00:02:51 +0000474 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
Anders Carlssond626cb72010-05-10 15:26:14 +0000475 return canPlaceRecordAtOffset(RD, Offset, /*CheckVBases=*/true);
Anders Carlsson6f95c702009-09-25 00:02:51 +0000476 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000477
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000478 if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
479 QualType ElemTy = Context.getBaseElementType(AT);
Anders Carlsson4bf82142009-09-25 01:23:32 +0000480 const RecordType *RT = ElemTy->getAs<RecordType>();
481 if (!RT)
482 return true;
483 const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
484 if (!RD)
485 return true;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000486
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000487 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlsson4bf82142009-09-25 01:23:32 +0000488
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000489 uint64_t NumElements = Context.getConstantArrayElementCount(AT);
Mike Stump2b84dd32009-11-05 04:02:15 +0000490 uint64_t ElementOffset = Offset;
Anders Carlsson4bf82142009-09-25 01:23:32 +0000491 for (uint64_t I = 0; I != NumElements; ++I) {
Anders Carlssond626cb72010-05-10 15:26:14 +0000492 if (!canPlaceRecordAtOffset(RD, ElementOffset, /*CheckVBases=*/true))
Anders Carlsson4bf82142009-09-25 01:23:32 +0000493 return false;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000494
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000495 ElementOffset += Layout.getSize();
Anders Carlsson4bf82142009-09-25 01:23:32 +0000496 }
497 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000498
Anders Carlsson6f95c702009-09-25 00:02:51 +0000499 return true;
500}
501
Anders Carlsson6522b052009-09-24 03:13:30 +0000502void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000503 uint64_t Offset,
504 bool UpdateVBases) {
Anders Carlssonf24b18f2009-09-24 03:22:10 +0000505 if (RD->isEmpty())
506 EmptyClassOffsets.insert(std::make_pair(Offset, RD));
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000507
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000508 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000509
510 // Update bases.
511 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000512 E = RD->bases_end(); I != E; ++I) {
Sebastian Redl1054fae2009-10-25 17:03:50 +0000513 assert(!I->getType()->isDependentType() &&
514 "Cannot layout class with dependent bases.");
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000515 if (I->isVirtual())
516 continue;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000517
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000518 const CXXRecordDecl *Base =
519 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000520
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000521 uint64_t BaseClassOffset = Layout.getBaseClassOffset(Base);
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000522 UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset,
523 /*UpdateVBases=*/false);
Anders Carlssonbb66bc82009-09-24 05:21:31 +0000524 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000525
Anders Carlssond7d358a2009-09-25 15:39:00 +0000526 // Update fields.
527 unsigned FieldNo = 0;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000528 for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
Anders Carlssond7d358a2009-09-25 15:39:00 +0000529 I != E; ++I, ++FieldNo) {
530 const FieldDecl *FD = *I;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000531
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000532 uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
Anders Carlssond7d358a2009-09-25 15:39:00 +0000533 UpdateEmptyClassOffsets(FD, Offset + FieldOffset);
534 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000535
Anders Carlsson57732052010-05-23 18:14:24 +0000536 const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
537
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000538 if (UpdateVBases) {
539 // FIXME: Update virtual bases.
Anders Carlsson57732052010-05-23 18:14:24 +0000540 } else if (PrimaryBase && Layout.getPrimaryBaseWasVirtual()) {
541 // We always want to update the offsets of a primary virtual base.
542 assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
543 "primary base class offset must always be 0!");
544 UpdateEmptyClassOffsets(PrimaryBase, Offset, /*UpdateVBases=*/false);
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000545 }
Anders Carlsson6522b052009-09-24 03:13:30 +0000546}
547
Anders Carlssone1883102009-09-25 01:54:38 +0000548void
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000549ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
Anders Carlssone1883102009-09-25 01:54:38 +0000550 uint64_t Offset) {
551 QualType T = FD->getType();
552
553 if (const RecordType *RT = T->getAs<RecordType>()) {
554 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000555 UpdateEmptyClassOffsets(RD, Offset, /*UpdateVBases=*/true);
Anders Carlssone1883102009-09-25 01:54:38 +0000556 return;
557 }
558 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000559
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000560 if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
561 QualType ElemTy = Context.getBaseElementType(AT);
Anders Carlssone1883102009-09-25 01:54:38 +0000562 const RecordType *RT = ElemTy->getAs<RecordType>();
563 if (!RT)
564 return;
565 const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
566 if (!RD)
567 return;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000568
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000569 const ASTRecordLayout &Info = Context.getASTRecordLayout(RD);
Anders Carlssone1883102009-09-25 01:54:38 +0000570
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000571 uint64_t NumElements = Context.getConstantArrayElementCount(AT);
Mike Stump2b84dd32009-11-05 04:02:15 +0000572 uint64_t ElementOffset = Offset;
Anders Carlssone1883102009-09-25 01:54:38 +0000573
574 for (uint64_t I = 0; I != NumElements; ++I) {
Anders Carlsson5f1a1702010-05-10 15:28:59 +0000575 UpdateEmptyClassOffsets(RD, ElementOffset, /*UpdateVBases=*/true);
Anders Carlssone1883102009-09-25 01:54:38 +0000576 ElementOffset += Info.getSize();
577 }
578 }
579}
580
Anders Carlsson79474332009-07-18 20:20:21 +0000581void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
582 IsUnion = D->isUnion();
Anders Carlsson68e0b682009-08-08 18:23:56 +0000583
Anders Carlsson28a5fa22009-08-08 19:38:24 +0000584 Packed = D->hasAttr<PackedAttr>();
585
586 // The #pragma pack attribute specifies the maximum field alignment.
Anders Carlsson68e0b682009-08-08 18:23:56 +0000587 if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
Anders Carlsson28a5fa22009-08-08 19:38:24 +0000588 MaxFieldAlignment = PPA->getAlignment();
Mike Stump11289f42009-09-09 15:08:12 +0000589
Anders Carlsson79474332009-07-18 20:20:21 +0000590 if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
Alexis Hunt96d5c762009-11-21 08:43:09 +0000591 UpdateAlignment(AA->getMaxAlignment());
Anders Carlsson6d9f6f32009-07-19 00:18:47 +0000592
Mike Stump22ea1f82009-08-16 01:46:26 +0000593 // If this is a C++ class, lay out the vtable and the non-virtual bases.
Mike Stump6b2556f2009-08-06 13:41:24 +0000594 const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
Anders Carlsson15837f82010-05-08 23:06:26 +0000595 if (RD) {
596 ComputeEmptySubobjectSizes(RD);
Mike Stump3dc7eb92009-07-30 00:22:38 +0000597 LayoutNonVirtualBases(RD);
Anders Carlsson15837f82010-05-08 23:06:26 +0000598 }
Anders Carlsson6d9f6f32009-07-19 00:18:47 +0000599
Anders Carlsson118ce162009-07-18 21:48:39 +0000600 LayoutFields(D);
Mike Stump11289f42009-09-09 15:08:12 +0000601
Anders Carlssonfc8cfa82009-07-28 19:24:15 +0000602 NonVirtualSize = Size;
603 NonVirtualAlignment = Alignment;
Mike Stump3dc7eb92009-07-30 00:22:38 +0000604
Anders Carlssonea7b1822010-04-15 16:12:58 +0000605 // If this is a C++ class, lay out its virtual bases and add its primary
606 // virtual base offsets.
607 if (RD) {
608 LayoutVirtualBases(RD, RD);
609
610 VisitedVirtualBases.clear();
611 AddPrimaryVirtualBaseOffsets(RD, 0, RD);
612 }
Mike Stump6b2556f2009-08-06 13:41:24 +0000613
Anders Carlsson79474332009-07-18 20:20:21 +0000614 // Finally, round the size of the total struct up to the alignment of the
615 // struct itself.
616 FinishLayout();
Anders Carlsson5b441d72010-04-10 21:24:48 +0000617
618#ifndef NDEBUG
619 if (RD) {
620 // Check that we have base offsets for all bases.
621 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
622 E = RD->bases_end(); I != E; ++I) {
623 if (I->isVirtual())
624 continue;
625
626 const CXXRecordDecl *BaseDecl =
627 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
628
629 assert(Bases.count(BaseDecl) && "Did not find base offset!");
630 }
631
632 // And all virtual bases.
633 for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
634 E = RD->vbases_end(); I != E; ++I) {
635 const CXXRecordDecl *BaseDecl =
636 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
637
638 assert(VBases.count(BaseDecl) && "Did not find base offset!");
639 }
640 }
641#endif
Anders Carlsson79474332009-07-18 20:20:21 +0000642}
643
Anders Carlsson6ed3a9a2010-05-26 05:04:25 +0000644void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
Anders Carlsson4f516282009-07-18 20:50:59 +0000645 if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000646 const ASTRecordLayout &SL = Context.getASTObjCInterfaceLayout(SD);
Anders Carlsson4f516282009-07-18 20:50:59 +0000647
648 UpdateAlignment(SL.getAlignment());
Mike Stump11289f42009-09-09 15:08:12 +0000649
Anders Carlsson4f516282009-07-18 20:50:59 +0000650 // We start laying out ivars not at the end of the superclass
651 // structure, but at the next byte following the last field.
Anders Carlsson27b50132009-07-18 21:26:44 +0000652 Size = llvm::RoundUpToAlignment(SL.getDataSize(), 8);
Anders Carlsson47680d82009-09-26 01:34:51 +0000653 DataSize = Size;
Anders Carlsson4f516282009-07-18 20:50:59 +0000654 }
Mike Stump11289f42009-09-09 15:08:12 +0000655
Anders Carlsson28a5fa22009-08-08 19:38:24 +0000656 Packed = D->hasAttr<PackedAttr>();
Mike Stump11289f42009-09-09 15:08:12 +0000657
Anders Carlsson28a5fa22009-08-08 19:38:24 +0000658 // The #pragma pack attribute specifies the maximum field alignment.
659 if (const PragmaPackAttr *PPA = D->getAttr<PragmaPackAttr>())
660 MaxFieldAlignment = PPA->getAlignment();
Mike Stump11289f42009-09-09 15:08:12 +0000661
Anders Carlsson4f516282009-07-18 20:50:59 +0000662 if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
Alexis Hunt96d5c762009-11-21 08:43:09 +0000663 UpdateAlignment(AA->getMaxAlignment());
Anders Carlsson4f516282009-07-18 20:50:59 +0000664 // Layout each ivar sequentially.
665 llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000666 Context.ShallowCollectObjCIvars(D, Ivars);
Anders Carlsson4f516282009-07-18 20:50:59 +0000667 for (unsigned i = 0, e = Ivars.size(); i != e; ++i)
668 LayoutField(Ivars[i]);
Mike Stump11289f42009-09-09 15:08:12 +0000669
Anders Carlsson4f516282009-07-18 20:50:59 +0000670 // Finally, round the size of the total struct up to the alignment of the
671 // struct itself.
672 FinishLayout();
673}
674
Anders Carlsson118ce162009-07-18 21:48:39 +0000675void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
676 // Layout each field, for now, just sequentially, respecting alignment. In
677 // the future, this will need to be tweakable by targets.
Mike Stump11289f42009-09-09 15:08:12 +0000678 for (RecordDecl::field_iterator Field = D->field_begin(),
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000679 FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
Anders Carlsson118ce162009-07-18 21:48:39 +0000680 LayoutField(*Field);
681}
682
Anders Carlsson57235162010-04-16 15:57:11 +0000683void ASTRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
684 uint64_t TypeSize) {
685 assert(Context.getLangOptions().CPlusPlus &&
686 "Can only have wide bit-fields in C++!");
687
688 // Itanium C++ ABI 2.4:
689 // If sizeof(T)*8 < n, let T' be the largest integral POD type with
690 // sizeof(T')*8 <= n.
691
692 QualType IntegralPODTypes[] = {
693 Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy,
694 Context.UnsignedLongTy, Context.UnsignedLongLongTy
695 };
696
Anders Carlsson57235162010-04-16 15:57:11 +0000697 QualType Type;
698 for (unsigned I = 0, E = llvm::array_lengthof(IntegralPODTypes);
699 I != E; ++I) {
700 uint64_t Size = Context.getTypeSize(IntegralPODTypes[I]);
Anders Carlsson57235162010-04-16 15:57:11 +0000701
702 if (Size > FieldSize)
703 break;
704
705 Type = IntegralPODTypes[I];
706 }
707 assert(!Type.isNull() && "Did not find a type!");
Anders Carlsson57235162010-04-16 15:57:11 +0000708
709 unsigned TypeAlign = Context.getTypeAlign(Type);
710
711 // We're not going to use any of the unfilled bits in the last byte.
712 UnfilledBitsInLastByte = 0;
713
Anders Carlssonaad5fa82010-04-17 20:21:41 +0000714 uint64_t FieldOffset;
715
Anders Carlsson57235162010-04-16 15:57:11 +0000716 if (IsUnion) {
717 DataSize = std::max(DataSize, FieldSize);
Anders Carlssonaad5fa82010-04-17 20:21:41 +0000718 FieldOffset = 0;
Anders Carlsson57235162010-04-16 15:57:11 +0000719 } else {
Anders Carlssonaad5fa82010-04-17 20:21:41 +0000720 // The bitfield is allocated starting at the next offset aligned appropriately
721 // for T', with length n bits.
722 FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign);
723
Anders Carlsson57235162010-04-16 15:57:11 +0000724 uint64_t NewSizeInBits = FieldOffset + FieldSize;
725
726 DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
727 UnfilledBitsInLastByte = DataSize - NewSizeInBits;
728 }
729
730 // Place this field at the current location.
731 FieldOffsets.push_back(FieldOffset);
732
733 // Update the size.
734 Size = std::max(Size, DataSize);
735
736 // Remember max struct/class alignment.
737 UpdateAlignment(TypeAlign);
738}
739
Anders Carlsson07209442009-11-22 17:37:31 +0000740void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
741 bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
Anders Carlssonba958402009-11-22 19:13:51 +0000742 uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte);
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000743 uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000744
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000745 std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType());
Anders Carlsson07209442009-11-22 17:37:31 +0000746 uint64_t TypeSize = FieldInfo.first;
747 unsigned FieldAlign = FieldInfo.second;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000748
Anders Carlsson57235162010-04-16 15:57:11 +0000749 if (FieldSize > TypeSize) {
750 LayoutWideBitField(FieldSize, TypeSize);
751 return;
752 }
753
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000754 if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
Anders Carlsson07209442009-11-22 17:37:31 +0000755 FieldAlign = 1;
756 if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
757 FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
758
759 // The maximum field alignment overrides the aligned attribute.
760 if (MaxFieldAlignment)
761 FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000762
Daniel Dunbar3d9289c2010-04-15 06:18:39 +0000763 // Check if we need to add padding to give the field the correct alignment.
Anders Carlsson07209442009-11-22 17:37:31 +0000764 if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
765 FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000766
Daniel Dunbar3d9289c2010-04-15 06:18:39 +0000767 // Padding members don't affect overall alignment.
Anders Carlsson07209442009-11-22 17:37:31 +0000768 if (!D->getIdentifier())
769 FieldAlign = 1;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000770
Anders Carlsson07209442009-11-22 17:37:31 +0000771 // Place this field at the current location.
772 FieldOffsets.push_back(FieldOffset);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000773
Anders Carlssonba958402009-11-22 19:13:51 +0000774 // Update DataSize to include the last byte containing (part of) the bitfield.
775 if (IsUnion) {
776 // FIXME: I think FieldSize should be TypeSize here.
777 DataSize = std::max(DataSize, FieldSize);
778 } else {
779 uint64_t NewSizeInBits = FieldOffset + FieldSize;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000780
Anders Carlssonba958402009-11-22 19:13:51 +0000781 DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
782 UnfilledBitsInLastByte = DataSize - NewSizeInBits;
783 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000784
Anders Carlssonba958402009-11-22 19:13:51 +0000785 // Update the size.
786 Size = std::max(Size, DataSize);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000787
Anders Carlsson07209442009-11-22 17:37:31 +0000788 // Remember max struct/class alignment.
789 UpdateAlignment(FieldAlign);
790}
791
Anders Carlsson79474332009-07-18 20:20:21 +0000792void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
Anders Carlsson07209442009-11-22 17:37:31 +0000793 if (D->isBitField()) {
794 LayoutBitField(D);
795 return;
796 }
797
Anders Carlssonba958402009-11-22 19:13:51 +0000798 // Reset the unfilled bits.
799 UnfilledBitsInLastByte = 0;
800
Anders Carlsson07209442009-11-22 17:37:31 +0000801 bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
Anders Carlsson47680d82009-09-26 01:34:51 +0000802 uint64_t FieldOffset = IsUnion ? 0 : DataSize;
Anders Carlsson79474332009-07-18 20:20:21 +0000803 uint64_t FieldSize;
804 unsigned FieldAlign;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000805
Anders Carlsson07209442009-11-22 17:37:31 +0000806 if (D->getType()->isIncompleteArrayType()) {
807 // This is a flexible array member; we can't directly
808 // query getTypeInfo about these, so we figure it out here.
809 // Flexible array members don't have any size, but they
810 // have to be aligned appropriately for their element type.
811 FieldSize = 0;
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000812 const ArrayType* ATy = Context.getAsArrayType(D->getType());
813 FieldAlign = Context.getTypeAlign(ATy->getElementType());
Anders Carlsson07209442009-11-22 17:37:31 +0000814 } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
815 unsigned AS = RT->getPointeeType().getAddressSpace();
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000816 FieldSize = Context.Target.getPointerWidth(AS);
817 FieldAlign = Context.Target.getPointerAlign(AS);
Anders Carlsson79474332009-07-18 20:20:21 +0000818 } else {
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000819 std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType());
Anders Carlsson07209442009-11-22 17:37:31 +0000820 FieldSize = FieldInfo.first;
821 FieldAlign = FieldInfo.second;
Anders Carlsson79474332009-07-18 20:20:21 +0000822 }
Mike Stump11289f42009-09-09 15:08:12 +0000823
Anders Carlsson07209442009-11-22 17:37:31 +0000824 if (FieldPacked)
825 FieldAlign = 8;
826 if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
827 FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
828
829 // The maximum field alignment overrides the aligned attribute.
830 if (MaxFieldAlignment)
831 FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
832
833 // Round up the current record size to the field's alignment boundary.
834 FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000835
Anders Carlsson07209442009-11-22 17:37:31 +0000836 if (!IsUnion) {
837 while (true) {
838 // Check if we can place the field at this offset.
839 if (canPlaceFieldAtOffset(D, FieldOffset))
840 break;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000841
Anders Carlsson07209442009-11-22 17:37:31 +0000842 // We couldn't place the field at the offset. Try again at a new offset.
843 FieldOffset += FieldAlign;
844 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000845
Anders Carlsson07209442009-11-22 17:37:31 +0000846 UpdateEmptyClassOffsets(D, FieldOffset);
847 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000848
Anders Carlsson79474332009-07-18 20:20:21 +0000849 // Place this field at the current location.
850 FieldOffsets.push_back(FieldOffset);
Mike Stump11289f42009-09-09 15:08:12 +0000851
Anders Carlsson79474332009-07-18 20:20:21 +0000852 // Reserve space for this field.
853 if (IsUnion)
854 Size = std::max(Size, FieldSize);
855 else
856 Size = FieldOffset + FieldSize;
Mike Stump11289f42009-09-09 15:08:12 +0000857
Anders Carlsson47680d82009-09-26 01:34:51 +0000858 // Update the data size.
859 DataSize = Size;
Mike Stump11289f42009-09-09 15:08:12 +0000860
Anders Carlsson79474332009-07-18 20:20:21 +0000861 // Remember max struct/class alignment.
862 UpdateAlignment(FieldAlign);
863}
864
865void ASTRecordLayoutBuilder::FinishLayout() {
866 // In C++, records cannot be of size 0.
Anders Carlsson5efc56e2010-04-16 15:07:51 +0000867 if (Context.getLangOptions().CPlusPlus && Size == 0)
Anders Carlsson79474332009-07-18 20:20:21 +0000868 Size = 8;
869 // Finally, round the size of the record up to the alignment of the
870 // record itself.
Anders Carlsson07209442009-11-22 17:37:31 +0000871 Size = llvm::RoundUpToAlignment(Size, Alignment);
Anders Carlsson79474332009-07-18 20:20:21 +0000872}
873
874void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
875 if (NewAlignment <= Alignment)
876 return;
Mike Stump11289f42009-09-09 15:08:12 +0000877
Anders Carlsson79474332009-07-18 20:20:21 +0000878 assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2"));
Mike Stump11289f42009-09-09 15:08:12 +0000879
Anders Carlsson79474332009-07-18 20:20:21 +0000880 Alignment = NewAlignment;
881}
Mike Stump11289f42009-09-09 15:08:12 +0000882
Anders Carlsson5ebf8b42009-12-07 04:35:11 +0000883const ASTRecordLayout *
884ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
885 const RecordDecl *D) {
886 ASTRecordLayoutBuilder Builder(Ctx);
887
888 Builder.Layout(D);
889
890 if (!isa<CXXRecordDecl>(D))
Ted Kremenekc3015a92010-03-08 20:56:29 +0000891 return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment,
892 Builder.Size,
893 Builder.FieldOffsets.data(),
894 Builder.FieldOffsets.size());
Anders Carlsson5ebf8b42009-12-07 04:35:11 +0000895
896 // FIXME: This is not always correct. See the part about bitfields at
897 // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
898 // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
899 bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
900
901 // FIXME: This should be done in FinalizeLayout.
902 uint64_t DataSize =
903 IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
904 uint64_t NonVirtualSize =
905 IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
906
Ted Kremenekc3015a92010-03-08 20:56:29 +0000907 return new (Ctx) ASTRecordLayout(Ctx, Builder.Size, Builder.Alignment,
908 DataSize, Builder.FieldOffsets.data(),
909 Builder.FieldOffsets.size(),
910 NonVirtualSize,
911 Builder.NonVirtualAlignment,
Anders Carlsson2357bfd2010-05-08 22:35:05 +0000912 Builder.SizeOfLargestEmptySubobject,
Ted Kremenekc3015a92010-03-08 20:56:29 +0000913 Builder.PrimaryBase,
Anders Carlsson1d1e4cf2010-05-26 05:25:15 +0000914 Builder.PrimaryBaseIsVirtual,
Anders Carlsson6a848892010-03-11 04:10:39 +0000915 Builder.Bases, Builder.VBases);
Anders Carlsson5ebf8b42009-12-07 04:35:11 +0000916}
917
Anders Carlsson5ebf8b42009-12-07 04:35:11 +0000918const CXXMethodDecl *
919ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
920 assert(RD->isDynamicClass() && "Class does not have any virtual methods!");
921
Daniel Dunbarccabe482010-04-19 20:44:53 +0000922 // If a class isn't polymorphic it doesn't have a key function.
Anders Carlsson5ebf8b42009-12-07 04:35:11 +0000923 if (!RD->isPolymorphic())
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000924 return 0;
Eli Friedmanf2c79b62009-12-08 03:56:49 +0000925
926 // A class inside an anonymous namespace doesn't have a key function. (Or
927 // at least, there's no point to assigning a key function to such a class;
928 // this doesn't affect the ABI.)
929 if (RD->isInAnonymousNamespace())
930 return 0;
931
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000932 for (CXXRecordDecl::method_iterator I = RD->method_begin(),
933 E = RD->method_end(); I != E; ++I) {
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000934 const CXXMethodDecl *MD = *I;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000935
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000936 if (!MD->isVirtual())
937 continue;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000938
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000939 if (MD->isPure())
940 continue;
Eli Friedmanf2c79b62009-12-08 03:56:49 +0000941
Anders Carlssonf98849e2009-12-02 17:15:43 +0000942 // Ignore implicit member functions, they are always marked as inline, but
943 // they don't have a body until they're defined.
944 if (MD->isImplicit())
945 continue;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000946
Douglas Gregora318efd2010-01-05 19:06:31 +0000947 if (MD->isInlineSpecified())
948 continue;
Eli Friedman71a26d82009-12-06 20:50:05 +0000949
950 if (MD->hasInlineBody())
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000951 continue;
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000952
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000953 // We found it.
954 return MD;
955 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +0000956
Anders Carlssonb1d3f7c2009-11-30 23:41:22 +0000957 return 0;
958}
959
Anders Carlssondf291d82010-05-26 04:56:53 +0000960/// getASTRecordLayout - Get or compute information about the layout of the
961/// specified record (struct/union/class), which indicates its size and field
962/// position information.
963const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
964 D = D->getDefinition();
965 assert(D && "Cannot get layout of forward declarations!");
966
967 // Look up this layout, if already laid out, return what we have.
968 // Note that we can't save a reference to the entry because this function
969 // is recursive.
970 const ASTRecordLayout *Entry = ASTRecordLayouts[D];
971 if (Entry) return *Entry;
972
Anders Carlssond2954862010-05-26 05:10:47 +0000973 const ASTRecordLayout *NewEntry;
974
975 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
976 ASTRecordLayoutBuilder Builder(*this);
977 Builder.Layout(RD);
978
979 // FIXME: This is not always correct. See the part about bitfields at
980 // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
981 // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
982 bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
983
984 // FIXME: This should be done in FinalizeLayout.
985 uint64_t DataSize =
986 IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
987 uint64_t NonVirtualSize =
988 IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
989
990 NewEntry =
991 new (*this) ASTRecordLayout(*this, Builder.Size, Builder.Alignment,
992 DataSize, Builder.FieldOffsets.data(),
993 Builder.FieldOffsets.size(),
994 NonVirtualSize,
995 Builder.NonVirtualAlignment,
996 Builder.SizeOfLargestEmptySubobject,
997 Builder.PrimaryBase,
Anders Carlsson1d1e4cf2010-05-26 05:25:15 +0000998 Builder.PrimaryBaseIsVirtual,
Anders Carlssond2954862010-05-26 05:10:47 +0000999 Builder.Bases, Builder.VBases);
1000 } else {
1001 ASTRecordLayoutBuilder Builder(*this);
1002 Builder.Layout(D);
1003
1004 NewEntry =
1005 new (*this) ASTRecordLayout(*this, Builder.Size, Builder.Alignment,
1006 Builder.Size,
1007 Builder.FieldOffsets.data(),
1008 Builder.FieldOffsets.size());
1009 }
1010
Anders Carlssondf291d82010-05-26 04:56:53 +00001011 ASTRecordLayouts[D] = NewEntry;
1012
1013 if (getLangOptions().DumpRecordLayouts) {
1014 llvm::errs() << "\n*** Dumping AST Record Layout\n";
1015 DumpRecordLayout(D, llvm::errs());
1016 }
1017
1018 return *NewEntry;
1019}
1020
1021const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
1022 RD = cast<CXXRecordDecl>(RD->getDefinition());
1023 assert(RD && "Cannot get key function for forward declarations!");
1024
1025 const CXXMethodDecl *&Entry = KeyFunctions[RD];
1026 if (!Entry)
1027 Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD);
1028 else
1029 assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) &&
1030 "Key function changed!");
1031
1032 return Entry;
1033}
1034
1035/// getInterfaceLayoutImpl - Get or compute information about the
1036/// layout of the given interface.
1037///
1038/// \param Impl - If given, also include the layout of the interface's
1039/// implementation. This may differ by including synthesized ivars.
1040const ASTRecordLayout &
1041ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
1042 const ObjCImplementationDecl *Impl) {
1043 assert(!D->isForwardDecl() && "Invalid interface decl!");
1044
1045 // Look up this layout, if already laid out, return what we have.
1046 ObjCContainerDecl *Key =
1047 Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D;
1048 if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
1049 return *Entry;
1050
1051 // Add in synthesized ivar count if laying out an implementation.
1052 if (Impl) {
1053 unsigned SynthCount = CountNonClassIvars(D);
1054 // If there aren't any sythesized ivars then reuse the interface
1055 // entry. Note we can't cache this because we simply free all
1056 // entries later; however we shouldn't look up implementations
1057 // frequently.
1058 if (SynthCount == 0)
1059 return getObjCLayout(D, 0);
1060 }
1061
Anders Carlsson6ed3a9a2010-05-26 05:04:25 +00001062 ASTRecordLayoutBuilder Builder(*this);
1063 Builder.Layout(D);
1064
Anders Carlssondf291d82010-05-26 04:56:53 +00001065 const ASTRecordLayout *NewEntry =
Anders Carlsson6ed3a9a2010-05-26 05:04:25 +00001066 new (*this) ASTRecordLayout(*this, Builder.Size, Builder.Alignment,
1067 Builder.DataSize,
1068 Builder.FieldOffsets.data(),
1069 Builder.FieldOffsets.size());
1070
Anders Carlssondf291d82010-05-26 04:56:53 +00001071 ObjCLayouts[Key] = NewEntry;
1072
1073 return *NewEntry;
1074}
1075
Daniel Dunbaraa423af2010-04-08 02:59:49 +00001076static void PrintOffset(llvm::raw_ostream &OS,
1077 uint64_t Offset, unsigned IndentLevel) {
1078 OS << llvm::format("%4d | ", Offset);
1079 OS.indent(IndentLevel * 2);
1080}
1081
1082static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
1083 const CXXRecordDecl *RD, ASTContext &C,
1084 uint64_t Offset,
1085 unsigned IndentLevel,
1086 const char* Description,
1087 bool IncludeVirtualBases) {
1088 const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
1089
1090 PrintOffset(OS, Offset, IndentLevel);
Dan Gohman145f3f12010-04-19 16:39:44 +00001091 OS << C.getTypeDeclType(const_cast<CXXRecordDecl *>(RD)).getAsString();
Daniel Dunbaraa423af2010-04-08 02:59:49 +00001092 if (Description)
1093 OS << ' ' << Description;
1094 if (RD->isEmpty())
1095 OS << " (empty)";
1096 OS << '\n';
1097
1098 IndentLevel++;
1099
1100 const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase();
1101
1102 // Vtable pointer.
1103 if (RD->isDynamicClass() && !PrimaryBase) {
1104 PrintOffset(OS, Offset, IndentLevel);
Benjamin Kramerb11416d2010-04-17 09:33:03 +00001105 OS << '(' << RD << " vtable pointer)\n";
Daniel Dunbaraa423af2010-04-08 02:59:49 +00001106 }
1107 // Dump (non-virtual) bases
1108 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
1109 E = RD->bases_end(); I != E; ++I) {
1110 assert(!I->getType()->isDependentType() &&
1111 "Cannot layout class with dependent bases.");
1112 if (I->isVirtual())
1113 continue;
1114
1115 const CXXRecordDecl *Base =
1116 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
1117
1118 uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8;
1119
1120 DumpCXXRecordLayout(OS, Base, C, BaseOffset, IndentLevel,
1121 Base == PrimaryBase ? "(primary base)" : "(base)",
1122 /*IncludeVirtualBases=*/false);
1123 }
1124
1125 // Dump fields.
1126 uint64_t FieldNo = 0;
1127 for (CXXRecordDecl::field_iterator I = RD->field_begin(),
1128 E = RD->field_end(); I != E; ++I, ++FieldNo) {
1129 const FieldDecl *Field = *I;
1130 uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8;
1131
1132 if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
1133 if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
1134 DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
1135 Field->getNameAsCString(),
1136 /*IncludeVirtualBases=*/true);
1137 continue;
1138 }
1139 }
1140
1141 PrintOffset(OS, FieldOffset, IndentLevel);
Benjamin Kramerb11416d2010-04-17 09:33:03 +00001142 OS << Field->getType().getAsString() << ' ' << Field << '\n';
Daniel Dunbaraa423af2010-04-08 02:59:49 +00001143 }
1144
1145 if (!IncludeVirtualBases)
1146 return;
1147
1148 // Dump virtual bases.
1149 for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
1150 E = RD->vbases_end(); I != E; ++I) {
1151 assert(I->isVirtual() && "Found non-virtual class!");
1152 const CXXRecordDecl *VBase =
1153 cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
1154
1155 uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8;
1156 DumpCXXRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel,
1157 VBase == PrimaryBase ?
1158 "(primary virtual base)" : "(virtual base)",
1159 /*IncludeVirtualBases=*/false);
1160 }
Daniel Dunbaraa423af2010-04-08 02:59:49 +00001161
1162 OS << " sizeof=" << Info.getSize() / 8;
1163 OS << ", dsize=" << Info.getDataSize() / 8;
1164 OS << ", align=" << Info.getAlignment() / 8 << '\n';
1165 OS << " nvsize=" << Info.getNonVirtualSize() / 8;
1166 OS << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n';
1167 OS << '\n';
1168}
Daniel Dunbarccabe482010-04-19 20:44:53 +00001169
1170void ASTContext::DumpRecordLayout(const RecordDecl *RD,
1171 llvm::raw_ostream &OS) {
1172 const ASTRecordLayout &Info = getASTRecordLayout(RD);
1173
1174 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
1175 return DumpCXXRecordLayout(OS, CXXRD, *this, 0, 0, 0,
1176 /*IncludeVirtualBases=*/true);
1177
1178 OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n";
1179 OS << "Record: ";
1180 RD->dump();
1181 OS << "\nLayout: ";
1182 OS << "<ASTRecordLayout\n";
1183 OS << " Size:" << Info.getSize() << "\n";
1184 OS << " DataSize:" << Info.getDataSize() << "\n";
1185 OS << " Alignment:" << Info.getAlignment() << "\n";
1186 OS << " FieldOffsets: [";
1187 for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
1188 if (i) OS << ", ";
1189 OS << Info.getFieldOffset(i);
1190 }
1191 OS << "]>\n";
1192}