20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/MathExtras.h"
24 using namespace clang;
39 struct BaseSubobjectInfo {
51 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
54 const BaseSubobjectInfo *Derived;
60 struct ExternalLayout {
61 ExternalLayout() :
Size(0), Align(0) {}
70 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
73 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
76 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
80 uint64_t getExternalFieldOffset(
const FieldDecl *FD) {
81 assert(FieldOffsets.count(FD) &&
82 "Field does not have an external offset");
83 return FieldOffsets[FD];
87 auto Known = BaseOffsets.find(RD);
88 if (Known == BaseOffsets.end())
90 BaseOffset = Known->second;
95 auto Known = VirtualBaseOffsets.find(RD);
96 if (Known == VirtualBaseOffsets.end())
98 BaseOffset = Known->second;
105 class EmptySubobjectMap {
113 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
114 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
115 EmptyClassOffsetsMapTy EmptyClassOffsets;
123 void ComputeEmptySubobjectSizes();
127 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
132 bool PlacingOverlappingField);
134 bool PlacingOverlappingField);
139 return Offset <= MaxEmptyClassOffset;
145 assert(FieldOffset % CharWidth == 0 &&
146 "Field offset not at char boundary!");
155 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
161 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
172 ComputeEmptySubobjectSizes();
179 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
187 void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
226 if (EmptySize > SizeOfLargestEmptySubobject)
227 SizeOfLargestEmptySubobject = EmptySize;
232 EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
238 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(
Offset);
239 if (I == EmptyClassOffsets.end())
242 const ClassVectorTy &Classes = I->second;
243 if (llvm::find(Classes, RD) == Classes.end())
250 void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
258 ClassVectorTy &Classes = EmptyClassOffsets[
Offset];
259 if (llvm::is_contained(Classes, RD))
262 Classes.push_back(RD);
265 if (
Offset > MaxEmptyClassOffset)
266 MaxEmptyClassOffset =
Offset;
270 EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
274 if (!AnyEmptySubobjectsBeyondOffset(
Offset))
277 if (!CanPlaceSubobjectAtOffset(Info->Class,
Offset))
282 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
288 if (!CanPlaceBaseSubobjectAtOffset(
Base, BaseOffset))
292 if (Info->PrimaryVirtualBaseInfo) {
293 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
295 if (Info == PrimaryVirtualBaseInfo->Derived) {
296 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo,
Offset))
302 unsigned FieldNo = 0;
304 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
309 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
316 void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
318 bool PlacingEmptyBase) {
319 if (!PlacingEmptyBase &&
Offset >= SizeOfLargestEmptySubobject) {
328 AddSubobjectAtOffset(Info->Class,
Offset);
332 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
337 UpdateEmptyBaseSubobjects(
Base, BaseOffset, PlacingEmptyBase);
340 if (Info->PrimaryVirtualBaseInfo) {
341 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
343 if (Info == PrimaryVirtualBaseInfo->Derived)
344 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo,
Offset,
349 unsigned FieldNo = 0;
351 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
356 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
360 bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
364 if (SizeOfLargestEmptySubobject.isZero())
367 if (!CanPlaceBaseSubobjectAtOffset(Info,
Offset))
372 UpdateEmptyBaseSubobjects(Info,
Offset, Info->Class->isEmpty());
377 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
382 if (!AnyEmptySubobjectsBeyondOffset(
Offset))
385 if (!CanPlaceSubobjectAtOffset(RD,
Offset))
392 if (
Base.isVirtual())
398 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
408 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
414 unsigned FieldNo = 0;
416 I != E; ++I, ++FieldNo) {
422 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
430 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
434 if (!AnyEmptySubobjectsBeyondOffset(
Offset))
439 return CanPlaceFieldSubobjectAtOffset(RD, RD,
Offset);
453 for (uint64_t I = 0; I != NumElements; ++I) {
456 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
459 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
462 ElementOffset += Layout.
getSize();
470 EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
472 if (!CanPlaceFieldSubobjectAtOffset(FD,
Offset))
477 UpdateEmptyFieldSubobjects(FD,
Offset, FD->
hasAttr<NoUniqueAddressAttr>());
481 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
483 bool PlacingOverlappingField) {
494 if (!PlacingOverlappingField &&
Offset >= SizeOfLargestEmptySubobject)
497 AddSubobjectAtOffset(RD,
Offset);
503 if (
Base.isVirtual())
509 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
510 PlacingOverlappingField);
519 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
520 PlacingOverlappingField);
525 unsigned FieldNo = 0;
527 I != E; ++I, ++FieldNo) {
533 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
537 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
541 UpdateEmptyFieldSubobjects(RD, RD,
Offset, PlacingOverlappingField);
558 for (uint64_t I = 0; I != NumElements; ++I) {
564 if (!PlacingOverlappingField &&
565 ElementOffset >= SizeOfLargestEmptySubobject)
568 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
569 PlacingOverlappingField);
570 ElementOffset += Layout.
getSize();
577 class ItaniumRecordLayoutBuilder {
584 EmptySubobjectMap *EmptySubobjects;
605 unsigned UseExternalLayout : 1;
609 unsigned InferAlignment : 1;
614 unsigned IsUnion : 1;
616 unsigned IsMac68kAlign : 1;
618 unsigned IsNaturalAlign : 1;
620 unsigned IsMsStruct : 1;
626 unsigned char UnfilledBitsInLastUnit;
630 unsigned char LastBitfieldStorageUnitSize;
653 bool PrimaryBaseIsVirtual;
666 bool HandledFirstNonOverlappingEmptyField;
668 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
671 BaseOffsetsMapTy Bases;
689 ExternalLayout External;
691 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
692 EmptySubobjectMap *EmptySubobjects)
693 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
698 IsMac68kAlign(
false),
699 IsNaturalAlign(!Context.
getTargetInfo().getTriple().isOSAIX()),
700 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
701 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(
CharUnits::
Zero()),
706 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
707 HandledFirstNonOverlappingEmptyField(
false),
708 FirstNearlyEmptyVBase(nullptr) {}
715 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
716 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
725 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
727 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
728 BaseSubobjectInfoMapTy;
736 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
744 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
746 BaseSubobjectInfo *Derived);
753 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
760 void LayoutNonVirtualBase(
const BaseSubobjectInfo *
Base);
762 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
770 void LayoutVirtualBase(
const BaseSubobjectInfo *
Base);
777 void InitializeLayout(
const Decl *D);
786 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
788 void UpdateAlignment(
CharUnits NewAlignment) {
789 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
797 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
798 uint64_t ComputedOffset);
800 void CheckFieldPadding(uint64_t
Offset, uint64_t UnpaddedOffset,
801 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
810 uint64_t getSizeInBits()
const {
return Size; }
813 void setSize(uint64_t NewSize) {
Size = NewSize; }
815 CharUnits getAligment()
const {
return Alignment; }
821 uint64_t getDataSizeInBits()
const {
return DataSize; }
823 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
824 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
826 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
827 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
831 void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
832 for (
const auto &I : RD->
bases()) {
833 assert(!I.getType()->isDependentType() &&
834 "Cannot layout class with dependent bases.");
842 if (!IndirectPrimaryBases.count(
Base)) {
844 PrimaryBaseIsVirtual =
true;
849 if (!FirstNearlyEmptyVBase)
850 FirstNearlyEmptyVBase =
Base;
853 SelectPrimaryVBase(
Base);
860 void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
872 for (
const auto &I : RD->
bases()) {
879 if (
Base->isDynamicClass()) {
882 PrimaryBaseIsVirtual =
false;
892 SelectPrimaryVBase(RD);
898 if (FirstNearlyEmptyVBase) {
899 PrimaryBase = FirstNearlyEmptyVBase;
900 PrimaryBaseIsVirtual =
true;
904 assert(!PrimaryBase &&
"Should not get here with a primary base!");
907 BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
908 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
909 BaseSubobjectInfo *Info;
915 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
920 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
923 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
927 Info->IsVirtual = IsVirtual;
928 Info->Derived =
nullptr;
929 Info->PrimaryVirtualBaseInfo =
nullptr;
932 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
940 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
945 if (PrimaryVirtualBaseInfo) {
946 if (PrimaryVirtualBaseInfo->Derived) {
950 PrimaryVirtualBase =
nullptr;
953 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
954 PrimaryVirtualBaseInfo->Derived = Info;
961 for (
const auto &I : RD->
bases()) {
962 bool IsVirtual = I.isVirtual();
964 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
966 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
969 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
973 assert(PrimaryVirtualBaseInfo &&
974 "Did not create a primary virtual base!");
977 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
978 PrimaryVirtualBaseInfo->Derived = Info;
984 void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
986 for (
const auto &I : RD->
bases()) {
987 bool IsVirtual = I.isVirtual();
989 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
992 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
998 "Did not add virtual base!");
1001 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
1002 "Non-virtual base already exists!");
1003 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1008 void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1013 if (!MaxFieldAlignment.
isZero()) {
1014 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
1015 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
1019 setSize(getSize().alignTo(BaseAlign));
1022 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1025 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1028 DeterminePrimaryBase(RD);
1031 ComputeBaseSubobjectInfo(RD);
1035 if (PrimaryBaseIsVirtual) {
1038 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1039 PrimaryBaseInfo->Derived =
nullptr;
1042 IndirectPrimaryBases.insert(PrimaryBase);
1044 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1045 "vbase already visited!");
1046 VisitedVirtualBases.insert(PrimaryBase);
1048 LayoutVirtualBase(PrimaryBaseInfo);
1050 BaseSubobjectInfo *PrimaryBaseInfo =
1051 NonVirtualBaseInfo.lookup(PrimaryBase);
1052 assert(PrimaryBaseInfo &&
1053 "Did not find base info for non-virtual primary base!");
1055 LayoutNonVirtualBase(PrimaryBaseInfo);
1061 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1066 EnsureVTablePointerAlignment(PtrAlign);
1069 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1070 HandledFirstNonOverlappingEmptyField =
true;
1072 setSize(getSize() + PtrWidth);
1073 setDataSize(getSize());
1077 for (
const auto &I : RD->
bases()) {
1083 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1088 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1092 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1093 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1095 LayoutNonVirtualBase(BaseInfo);
1099 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1100 const BaseSubobjectInfo *
Base) {
1105 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1106 Bases.insert(std::make_pair(
Base->Class,
Offset));
1111 void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1114 if (!Info->Class->getNumVBases())
1118 if (Info->PrimaryVirtualBaseInfo) {
1119 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1120 "Primary virtual base is not virtual!");
1121 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1123 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1124 "primary vbase offset already exists!");
1125 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1129 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo,
Offset);
1135 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
1136 if (
Base->IsVirtual)
1140 AddPrimaryVirtualBaseOffsets(
Base, BaseOffset);
1144 void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1147 bool PrimaryBaseIsVirtual;
1149 if (MostDerivedClass == RD) {
1150 PrimaryBase = this->PrimaryBase;
1151 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1159 assert(!
Base.getType()->isDependentType() &&
1160 "Cannot layout class with dependent bases.");
1164 if (
Base.isVirtual()) {
1165 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1166 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1169 if (!IndirectPrimaryBase) {
1171 if (!VisitedVirtualBases.insert(BaseDecl).second)
1175 assert(BaseInfo &&
"Did not find virtual base info!");
1176 LayoutVirtualBase(BaseInfo);
1186 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1190 void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1191 const BaseSubobjectInfo *
Base) {
1192 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1198 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1199 VBases.insert(std::make_pair(
Base->Class,
1206 ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *
Base) {
1207 assert(!IsUnion &&
"Unions cannot have base classes.");
1213 bool HasExternalLayout =
false;
1214 if (UseExternalLayout) {
1215 if (
Base->IsVirtual)
1216 HasExternalLayout = External.getExternalVBaseOffset(
Base->Class,
Offset);
1218 HasExternalLayout = External.getExternalNVBaseOffset(
Base->Class,
Offset);
1221 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](
CharUnits UnpackedAlign) {
1224 return (Packed && ((Context.
getLangOpts().getClangABICompat() <=
1235 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1237 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1239 const bool DefaultsToAIXPowerAlignment =
1241 if (DefaultsToAIXPowerAlignment) {
1246 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1249 HandledFirstNonOverlappingEmptyField =
true;
1250 }
else if (!IsNaturalAlign) {
1251 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1252 PreferredBaseAlign = BaseAlign;
1256 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1258 : UnpackedPreferredBaseAlign;
1260 if (
Base->Class->isEmpty() &&
1264 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1271 if (!MaxFieldAlignment.
isZero()) {
1272 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
1273 PreferredBaseAlign =
std::min(PreferredBaseAlign, MaxFieldAlignment);
1274 UnpackedAlignTo =
std::min(UnpackedAlignTo, MaxFieldAlignment);
1278 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1279 if (!HasExternalLayout) {
1281 Offset = getDataSize().alignTo(AlignTo);
1284 while (!EmptySubobjects->CanPlaceBaseAtOffset(
Base,
Offset))
1287 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(
Base,
Offset);
1289 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1291 if (InferAlignment &&
Offset < getDataSize().alignTo(AlignTo)) {
1295 InferAlignment =
false;
1299 if (!
Base->Class->isEmpty()) {
1303 setSize(
std::max(getSize(), getDataSize()));
1308 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1313 void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1314 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1319 Packed = D->
hasAttr<PackedAttr>();
1322 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1330 if (D->
hasAttr<AlignMac68kAttr>()) {
1332 !D->
hasAttr<AlignNaturalAttr>() &&
1333 "Having both mac68k and natural alignment on a decl is not allowed.");
1334 IsMac68kAlign =
true;
1339 if (D->
hasAttr<AlignNaturalAttr>())
1340 IsNaturalAlign =
true;
1342 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1349 HandledFirstNonOverlappingEmptyField =
1353 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1355 UseExternalLayout = Source->layoutRecordType(
1356 RD, External.Size, External.Align, External.FieldOffsets,
1357 External.BaseOffsets, External.VirtualBaseOffsets);
1360 if (UseExternalLayout) {
1361 if (External.Align > 0) {
1366 InferAlignment =
true;
1372 void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1373 InitializeLayout(D);
1381 void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1382 InitializeLayout(RD);
1385 LayoutNonVirtualBases(RD);
1391 NonVirtualAlignment = Alignment;
1392 PreferredNVAlignment = PreferredAlignment;
1395 LayoutVirtualBases(RD, RD);
1404 if (
Base.isVirtual())
1409 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1416 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1430 setSize(getDataSize());
1433 InitializeLayout(D);
1437 LayoutField(IVD,
false);
1444 void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1453 InsertExtraPadding && (Next !=
End || !HasFlexibleArrayMember));
1462 return llvm::alignTo(Size, CharAlignment);
1465 void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1466 uint64_t StorageUnitSize,
1470 "Can only have wide bit-fields in C++!");
1482 for (
const QualType &QT : IntegralPODTypes) {
1485 if (Size > FieldSize)
1490 assert(!
Type.isNull() &&
"Did not find a type!");
1495 UnfilledBitsInLastUnit = 0;
1496 LastBitfieldStorageUnitSize = 0;
1498 uint64_t FieldOffset;
1499 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1504 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1509 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1511 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1515 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1519 FieldOffsets.push_back(FieldOffset);
1521 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1522 Context.
toBits(TypeAlign), FieldPacked, D);
1525 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1528 UpdateAlignment(TypeAlign);
1531 void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1532 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1535 uint64_t StorageUnitSize = FieldInfo.
Width;
1536 unsigned FieldAlign = FieldInfo.
Align;
1598 FieldAlign = StorageUnitSize;
1603 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1604 UnfilledBitsInLastUnit < FieldSize) {
1606 if (!LastBitfieldStorageUnitSize && !FieldSize)
1609 UnfilledBitsInLastUnit = 0;
1610 LastBitfieldStorageUnitSize = 0;
1616 if (FieldSize > StorageUnitSize) {
1617 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
1622 uint64_t FieldOffset =
1623 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1628 if (FieldSize == 0 &&
1631 if (!IsUnion && FieldOffset == 0 &&
1637 unsigned ZeroLengthBitfieldBoundary =
1639 FieldAlign =
std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1648 unsigned UnpackedFieldAlign = FieldAlign;
1651 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1656 if (ExplicitFieldAlign) {
1657 FieldAlign =
std::max(FieldAlign, ExplicitFieldAlign);
1658 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1663 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1664 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1665 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1667 FieldAlign = UnpackedFieldAlign;
1669 FieldAlign =
std::min(FieldAlign, MaxFieldAlignmentInBits);
1674 if (IsMsStruct && IsUnion) {
1675 FieldAlign = UnpackedFieldAlign = 1;
1681 uint64_t UnpaddedFieldOffset = FieldOffset;
1682 uint64_t UnpackedFieldOffset = FieldOffset;
1692 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1693 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1694 UnpackedFieldOffset =
1695 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1696 UnfilledBitsInLastUnit = 0;
1701 bool AllowPadding = MaxFieldAlignment.
isZero();
1704 if (FieldSize == 0 ||
1706 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1707 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1708 }
else if (ExplicitFieldAlign &&
1709 (MaxFieldAlignmentInBits == 0 ||
1710 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1714 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1718 if (FieldSize == 0 ||
1720 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1722 UnpackedFieldOffset =
1723 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1724 else if (ExplicitFieldAlign &&
1725 (MaxFieldAlignmentInBits == 0 ||
1726 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1728 UnpackedFieldOffset =
1729 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1734 if (UseExternalLayout)
1735 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1738 FieldOffsets.push_back(FieldOffset);
1747 FieldAlign = UnpackedFieldAlign = 1;
1750 if (!UseExternalLayout)
1751 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1752 UnpackedFieldAlign, FieldPacked, D);
1760 uint64_t RoundedFieldSize;
1762 RoundedFieldSize = (FieldSize ? StorageUnitSize
1770 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1774 }
else if (IsMsStruct && FieldSize) {
1777 if (!UnfilledBitsInLastUnit) {
1778 setDataSize(FieldOffset + StorageUnitSize);
1779 UnfilledBitsInLastUnit = StorageUnitSize;
1781 UnfilledBitsInLastUnit -= FieldSize;
1782 LastBitfieldStorageUnitSize = StorageUnitSize;
1788 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1790 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1791 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1796 LastBitfieldStorageUnitSize = 0;
1800 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1803 UnadjustedAlignment =
1809 void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1810 bool InsertExtraPadding) {
1812 bool PotentiallyOverlapping = D->
hasAttr<NoUniqueAddressAttr>() && FieldClass;
1813 bool IsOverlappingEmptyField =
1814 PotentiallyOverlapping && FieldClass->isEmpty();
1817 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1819 const bool DefaultsToAIXPowerAlignment =
1821 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1822 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1824 "The first non-overlapping empty field should have been handled.");
1826 if (!IsOverlappingEmptyField) {
1827 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1834 HandledFirstNonOverlappingEmptyField = !IsUnion;
1843 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1845 UnfilledBitsInLastUnit = 0;
1846 LastBitfieldStorageUnitSize = 0;
1848 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1850 bool AlignIsRequired =
false;
1858 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1860 FieldAlign = TI.Align;
1863 EffectiveFieldSize = FieldSize =
1865 AlignIsRequired = TI.AlignIsRequired;
1877 setDeclInfo(
false );
1881 if (PotentiallyOverlapping) {
1883 EffectiveFieldSize =
1897 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1900 "Non PowerOf2 size in MSVC mode");
1922 if (TypeSize > FieldAlign &&
1924 FieldAlign = TypeSize;
1939 if (DefaultsToAIXPowerAlignment && !AlignIsRequired &&
1940 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1941 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
1942 if (BTy->getKind() == BuiltinType::Double ||
1943 BTy->getKind() == BuiltinType::LongDouble) {
1945 "No need to upgrade the alignment value.");
1952 performBuiltinTypeAlignmentUpgrade(CTy->getElementType()->castAs<
BuiltinType>());
1954 performBuiltinTypeAlignmentUpgrade(BTy);
1957 assert(RD &&
"Expected non-null RecordDecl.");
1966 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
1967 CharUnits UnpackedFieldOffset = FieldOffset;
1975 FieldAlign =
std::max(FieldAlign, MaxAlignmentInChars);
1976 PreferredAlign =
std::max(PreferredAlign, MaxAlignmentInChars);
1977 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, MaxAlignmentInChars);
1980 if (!MaxFieldAlignment.
isZero()) {
1981 FieldAlign =
std::min(FieldAlign, MaxFieldAlignment);
1982 PreferredAlign =
std::min(PreferredAlign, MaxFieldAlignment);
1983 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignment);
1987 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
1989 FieldOffset = FieldOffset.
alignTo(AlignTo);
1990 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
1992 if (UseExternalLayout) {
1994 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
1996 if (!IsUnion && EmptySubobjects) {
1998 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2000 assert(Allowed &&
"Externally-placed field cannot be placed here");
2003 if (!IsUnion && EmptySubobjects) {
2005 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2010 FieldOffset = getDataSize().
alignTo(AlignTo);
2012 FieldOffset += AlignTo;
2018 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2020 if (!UseExternalLayout)
2021 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
2022 Context.
toBits(UnpackedFieldOffset),
2023 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
2025 if (InsertExtraPadding) {
2027 CharUnits ExtraSizeForAsan = ASanAlignment;
2028 if (FieldSize % ASanAlignment)
2031 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2035 if (!IsOverlappingEmptyField) {
2036 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2038 setDataSize(
std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2040 setDataSize(FieldOffset + EffectiveFieldSize);
2042 PaddedFieldSize =
std::max(PaddedFieldSize, FieldOffset + FieldSize);
2043 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
2046 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2050 UnadjustedAlignment =
std::max(UnadjustedAlignment, FieldAlign);
2051 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2054 void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
2056 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2070 setSize(
std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2074 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2075 uint64_t UnpackedSizeInBits =
2076 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2078 uint64_t RoundedSize = llvm::alignTo(
2082 : PreferredAlignment));
2084 if (UseExternalLayout) {
2088 if (InferAlignment && External.Size < RoundedSize) {
2091 InferAlignment =
false;
2093 setSize(External.Size);
2098 setSize(RoundedSize);
2101 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
2103 if (getSizeInBits() > UnpaddedSize) {
2104 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2106 if (PadSize % CharBitNum == 0) {
2107 PadSize = PadSize / CharBitNum;
2113 << (InBits ? 1 : 0);
2119 if (Packed && UnpackedAlignment <= Alignment &&
2120 UnpackedSizeInBits == getSizeInBits() && !HasPackedField)
2126 void ItaniumRecordLayoutBuilder::UpdateAlignment(
2131 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2134 if (NewAlignment > Alignment) {
2135 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2136 "Alignment not a power of 2");
2137 Alignment = NewAlignment;
2140 if (UnpackedNewAlignment > UnpackedAlignment) {
2141 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2142 "Alignment not a power of 2");
2143 UnpackedAlignment = UnpackedNewAlignment;
2146 if (PreferredNewAlignment > PreferredAlignment) {
2147 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2148 "Alignment not a power of 2");
2149 PreferredAlignment = PreferredNewAlignment;
2154 ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2155 uint64_t ComputedOffset) {
2156 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
2158 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2163 InferAlignment =
false;
2167 return ExternalFieldOffset;
2180 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2184 void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2185 uint64_t
Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2186 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
2189 if (isa<ObjCIvarDecl>(D))
2200 if (!IsUnion &&
Offset > UnpaddedOffset) {
2201 unsigned PadSize =
Offset - UnpaddedOffset;
2203 if (PadSize % CharBitNum == 0) {
2204 PadSize = PadSize / CharBitNum;
2219 << (InBits ? 1 : 0);
2221 if (isPacked &&
Offset != UnpackedOffset) {
2222 HasPackedField =
true;
2246 bool allowInlineFunctions =
2250 if (!MD->isVirtual())
2258 if (MD->isImplicit())
2261 if (MD->isInlineSpecified() || MD->isConstexpr())
2264 if (MD->hasInlineBody())
2268 if (!MD->isUserProvided())
2272 if (!allowInlineFunctions) {
2284 if (!MD->hasAttr<CUDADeviceAttr>())
2288 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2296 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>())
2350 llvm_unreachable(
"bad tail-padding use kind");
2448 struct MicrosoftRecordLayoutBuilder {
2449 struct ElementInfo {
2453 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2454 MicrosoftRecordLayoutBuilder(
const ASTContext &Context) : Context(Context) {}
2456 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2457 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2478 void layoutBitField(
const FieldDecl *FD);
2481 void layoutZeroWidthBitField(
const FieldDecl *FD);
2490 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2492 void placeFieldAtOffset(
CharUnits FieldOffset) {
2493 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2496 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2497 FieldOffsets.push_back(FieldOffset);
2500 void computeVtorDispSet(
2501 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2526 ElementInfo PointerInfo;
2534 BaseOffsetsMapTy Bases;
2540 unsigned RemainingBitsInField;
2544 bool LastFieldIsNonZeroWidthBitfield : 1;
2546 bool HasOwnVFPtr : 1;
2552 bool EndsWithZeroSizedObject : 1;
2555 bool LeadsWithZeroSizedBase : 1;
2558 bool UseExternalLayout : 1;
2562 ExternalLayout External;
2566 MicrosoftRecordLayoutBuilder::ElementInfo
2567 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2572 if (!MaxFieldAlignment.
isZero())
2573 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2579 Alignment =
std::max(Alignment, Info.Alignment);
2586 MicrosoftRecordLayoutBuilder::ElementInfo
2587 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2593 ElementInfo Info{TInfo.Width, TInfo.Align};
2605 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2611 FieldRequiredAlignment =
std::max(FieldRequiredAlignment,
2615 RequiredAlignment =
std::max(RequiredAlignment, FieldRequiredAlignment);
2618 if (!MaxFieldAlignment.
isZero())
2619 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2620 if (FD->
hasAttr<PackedAttr>())
2622 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2626 void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2629 initializeLayout(RD);
2631 DataSize =
Size =
Size.alignTo(Alignment);
2637 void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2640 initializeLayout(RD);
2641 initializeCXXLayout(RD);
2642 layoutNonVirtualBases(RD);
2646 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2647 Alignment =
std::max(Alignment, PointerInfo.Alignment);
2648 auto RoundingAlignment = Alignment;
2649 if (!MaxFieldAlignment.
isZero())
2650 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2651 if (!UseExternalLayout)
2652 Size =
Size.alignTo(RoundingAlignment);
2653 NonVirtualSize =
Size;
2656 layoutVirtualBases(RD);
2660 void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2673 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2677 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2678 unsigned PackedAlignment = MFAA->getAlignment();
2683 if (RD->
hasAttr<PackedAttr>())
2687 UseExternalLayout =
false;
2689 UseExternalLayout = Source->layoutRecordType(
2690 RD, External.Size, External.Align, External.FieldOffsets,
2691 External.BaseOffsets, External.VirtualBaseOffsets);
2695 MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2696 EndsWithZeroSizedObject =
false;
2697 LeadsWithZeroSizedBase =
false;
2698 HasOwnVFPtr =
false;
2700 PrimaryBase =
nullptr;
2701 SharedVBPtrBase =
nullptr;
2706 PointerInfo.Alignment =
2709 if (!MaxFieldAlignment.
isZero())
2710 PointerInfo.Alignment =
std::min(PointerInfo.Alignment, MaxFieldAlignment);
2714 MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2722 bool HasPolymorphicBaseClass =
false;
2729 if (
Base.isVirtual()) {
2734 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2735 SharedVBPtrBase = BaseDecl;
2743 PrimaryBase = BaseDecl;
2747 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2751 if (!HasPolymorphicBaseClass)
2755 else if (!PrimaryBase) {
2760 M->size_overridden_methods() == 0) {
2769 bool CheckLeadingLayout = !PrimaryBase;
2772 if (
Base.isVirtual())
2783 if (CheckLeadingLayout) {
2784 CheckLeadingLayout =
false;
2788 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2794 else if (SharedVBPtrBase) {
2801 if (!isa<CXXRecordDecl>(RD))
2803 if (RD->
hasAttr<EmptyBasesAttr>())
2805 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2815 void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2827 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2831 bool FoundBase =
false;
2832 if (UseExternalLayout) {
2833 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2835 assert(BaseOffset >= Size &&
"base offset already allocated");
2841 if (MDCUsesEBO && BaseDecl->
isEmpty()) {
2846 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2849 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2851 PreviousBaseLayout = &BaseLayout;
2854 void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2855 LastFieldIsNonZeroWidthBitfield =
false;
2860 void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2865 LastFieldIsNonZeroWidthBitfield =
false;
2866 ElementInfo Info = getAdjustedElementInfo(FD);
2867 Alignment =
std::max(Alignment, Info.Alignment);
2869 if (UseExternalLayout)
2875 FieldOffset =
Size.alignTo(Info.Alignment);
2876 placeFieldAtOffset(FieldOffset);
2880 void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2883 layoutZeroWidthBitField(FD);
2886 ElementInfo Info = getAdjustedElementInfo(FD);
2889 if (Width > Context.
toBits(Info.Size))
2890 Width = Context.
toBits(Info.Size);
2894 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
2895 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2896 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
2897 RemainingBitsInField -= Width;
2900 LastFieldIsNonZeroWidthBitfield =
true;
2901 CurrentBitfieldSize = Info.Size;
2902 if (UseExternalLayout) {
2903 auto FieldBitOffset = External.getExternalFieldOffset(FD);
2904 placeFieldAtBitOffset(FieldBitOffset);
2906 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
2907 Context.
toBits(Info.Size));
2909 Alignment =
std::max(Alignment, Info.Alignment);
2910 }
else if (IsUnion) {
2917 placeFieldAtOffset(FieldOffset);
2918 Size = FieldOffset + Info.Size;
2919 Alignment =
std::max(Alignment, Info.Alignment);
2920 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
2925 MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
2928 if (!LastFieldIsNonZeroWidthBitfield) {
2934 LastFieldIsNonZeroWidthBitfield =
false;
2935 ElementInfo Info = getAdjustedElementInfo(FD);
2943 placeFieldAtOffset(FieldOffset);
2945 Alignment =
std::max(Alignment, Info.Alignment);
2949 void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
2950 if (!HasVBPtr || SharedVBPtrBase)
2955 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
2957 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
2960 if (UseExternalLayout) {
2963 if (Size < FieldStart)
2970 .alignTo(
std::max(RequiredAlignment, Alignment));
2972 for (uint64_t &FieldOffset : FieldOffsets)
2974 for (BaseOffsetsMapTy::value_type &
Base : Bases)
2975 if (
Base.second >= InjectionSite)
2979 void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
2985 PointerInfo.Size.alignTo(
std::max(RequiredAlignment, Alignment));
2991 if (UseExternalLayout) {
2995 if (FieldOffsets.empty() && Bases.empty())
3004 for (uint64_t &FieldOffset : FieldOffsets)
3006 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3010 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3015 CharUnits VtorDispAlignment = VtorDispSize;
3017 if (!MaxFieldAlignment.
isZero())
3018 VtorDispAlignment =
std::min(VtorDispAlignment, MaxFieldAlignment);
3023 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3028 VtorDispAlignment =
std::max(VtorDispAlignment, RequiredAlignment);
3031 computeVtorDispSet(HasVtorDispSet, RD);
3035 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3037 bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
3046 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3047 Alignment =
std::max(VtorDispAlignment, Alignment);
3050 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3054 if (UseExternalLayout) {
3055 if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3058 BaseOffset =
Size.alignTo(Info.Alignment);
3060 assert(BaseOffset >= Size &&
"base offset already allocated");
3062 VBases.insert(std::make_pair(BaseDecl,
3065 PreviousBaseLayout = &BaseLayout;
3069 void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3073 if (!RequiredAlignment.isZero()) {
3074 Alignment =
std::max(Alignment, RequiredAlignment);
3075 auto RoundingAlignment = Alignment;
3076 if (!MaxFieldAlignment.
isZero())
3077 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
3078 RoundingAlignment =
std::max(RoundingAlignment, RequiredAlignment);
3079 Size =
Size.alignTo(RoundingAlignment);
3081 if (
Size.isZero()) {
3082 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3083 EndsWithZeroSizedObject =
true;
3084 LeadsWithZeroSizedBase =
true;
3088 if (RequiredAlignment >= MinEmptyStructSize)
3091 Size = MinEmptyStructSize;
3094 if (UseExternalLayout) {
3105 BasesWithOverriddenMethods,
3107 if (BasesWithOverriddenMethods.count(RD))
3112 if (!
Base.isVirtual() &&
3114 Base.getType()->getAsCXXRecordDecl()))
3119 void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3120 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3129 HasVtordispSet.insert(BaseDecl);
3140 if (bi.second.hasVtorDisp())
3141 HasVtordispSet.insert(bi.first);
3162 !isa<CXXDestructorDecl>(MD) && !MD->isPure())
3164 while (!Work.empty()) {
3168 if (MethodRange.begin() == MethodRange.end())
3169 BasesWithOverriddenMethods.insert(MD->
getParent());
3171 Work.insert(MethodRange.begin(), MethodRange.end());
3179 if (!HasVtordispSet.count(BaseDecl) &&
3181 HasVtordispSet.insert(BaseDecl);
3199 assert(D &&
"Cannot get layout of forward declarations!");
3200 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3207 if (Entry)
return *Entry;
3212 MicrosoftRecordLayoutBuilder Builder(*
this);
3213 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3214 Builder.cxxLayout(RD);
3216 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3217 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3218 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3219 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3221 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3222 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3223 Builder.Bases, Builder.VBases);
3227 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3228 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3229 Builder.FieldOffsets);
3232 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3233 EmptySubobjectMap EmptySubobjects(*
this, RD);
3234 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3240 bool skipTailPadding =
3245 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3247 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3249 *
this, Builder.getSize(), Builder.Alignment,
3250 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3254 NonVirtualSize, Builder.NonVirtualAlignment,
3255 Builder.PreferredNVAlignment,
3256 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3257 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3260 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3264 *
this, Builder.getSize(), Builder.Alignment,
3265 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3267 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3271 ASTRecordLayouts[D] = NewEntry;
3274 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3285 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3294 const Decl *Result =
3299 KeyFunctions[RD] =
const_cast<Decl*
>(Result);
3301 return cast_or_null<CXXMethodDecl>(Result);
3306 "not working with method declaration from class definition");
3311 const auto &Map = KeyFunctions;
3315 if (I == Map.end())
return;
3323 KeyFunctions.erase(Method->
getParent());
3333 uint64_t OffsetInBits;
3334 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3344 return OffsetInBits;
3371 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3372 IVD; IVD = IVD->getNextIvar()) {
3377 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3395 "Invalid interface decl!");
3410 if (SynthCount == 0)
3411 return getObjCLayout(D,
nullptr);
3414 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3418 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3419 Builder.UnadjustedAlignment,
3421 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3423 ObjCLayouts[Key] = NewEntry;
3430 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)
Offset.getQuantity());
3431 OS.indent(IndentLevel * 2);
3435 unsigned Begin,
unsigned Width,
3436 unsigned IndentLevel) {
3439 llvm::raw_svector_ostream BufferOS(Buffer);
3440 BufferOS <<
Offset.getQuantity() <<
':';
3444 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3448 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3449 OS.indent(IndentLevel * 2);
3454 OS.indent(IndentLevel * 2);
3460 unsigned IndentLevel,
3461 const char* Description,
3463 bool IncludeVirtualBases) {
3465 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3468 OS << C.getTypeDeclType(
const_cast<RecordDecl*
>(RD)).getAsString();
3470 OS <<
' ' << Description;
3471 if (CXXRD && CXXRD->isEmpty())
3484 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(C)) {
3486 OS <<
'(' << *RD <<
" vtable pointer)\n";
3487 }
else if (HasOwnVFPtr) {
3490 OS <<
'(' << *RD <<
" vftable pointer)\n";
3496 assert(!
Base.getType()->isDependentType() &&
3497 "Cannot layout class with dependent bases.");
3498 if (!
Base.isVirtual())
3499 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3512 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3520 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3525 uint64_t FieldNo = 0;
3527 E = RD->
field_end(); I != E; ++I, ++FieldNo) {
3529 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3531 Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3534 if (
auto RT = Field.getType()->getAs<
RecordType>()) {
3536 Field.getName().data(),
3542 if (Field.isBitField()) {
3543 uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset -
Offset);
3544 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3545 unsigned Width = Field.getBitWidthValue(C);
3550 OS << Field.getType().getAsString() <<
' ' << Field <<
'\n';
3554 if (CXXRD && IncludeVirtualBases) {
3559 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3564 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3566 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3571 "(primary virtual base)" :
"(virtual base)",
3577 if (!PrintSizeInfo)
return;
3584 if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3592 if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3593 OS <<
", preferrednvalign="
3600 bool Simple)
const {
3618 OS <<
"<ASTRecordLayout\n";
3626 OS <<
" FieldOffsets: [";
3627 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {