24 #include "llvm/IR/DataLayout.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Type.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/MathExtras.h"
29 #include "llvm/Support/raw_ostream.h"
30 using namespace clang;
31 using namespace CodeGen;
74 struct CGRecordLowering {
80 enum InfoKind { VFPtr, VBPtr, Field,
Base, VBase, Scissor }
Kind;
88 : Offset(Offset), Kind(Kind), Data(Data), FD(FD) {}
91 : Offset(Offset), Kind(Kind), Data(Data), RD(RD) {}
100 return MemberInfo(Offset, MemberInfo::Field, Data);
108 bool isDiscreteBitFieldABI() {
110 D->isMsStruct(Context);
117 bool isOverlappingVBaseABI() {
122 llvm::Type *getIntNType(uint64_t NumBits) {
123 return llvm::Type::getIntNTy(Types.getLLVMContext(),
124 (
unsigned)llvm::RoundUpToAlignment(NumBits, 8));
127 llvm::Type *getByteArrayType(
CharUnits NumBytes) {
128 assert(!NumBytes.
isZero() &&
"Empty byte arrays aren't allowed.");
129 llvm::Type *
Type = llvm::Type::getInt8Ty(Types.getLLVMContext());
131 (llvm::Type *)llvm::ArrayType::get(Type, NumBytes.getQuantity());
135 llvm::Type *getStorageType(
const FieldDecl *FD) {
136 llvm::Type *Type = Types.ConvertTypeForMem(FD->
getType());
138 if (isDiscreteBitFieldABI())
return Type;
144 return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType();
146 CharUnits bitsToCharUnits(uint64_t BitOffset) {
152 CharUnits getAlignment(llvm::Type *Type) {
156 return Types.isZeroInitializable(FD->
getType());
159 return Types.isZeroInitializable(RD);
161 void appendPaddingBytes(
CharUnits Size) {
163 FieldTypes.push_back(getByteArrayType(Size));
165 uint64_t getFieldBitOffset(
const FieldDecl *FD) {
170 llvm::Type *StorageType);
172 void lower(
bool NonVirtualBaseType);
174 void accumulateFields();
177 void accumulateBases();
178 void accumulateVPtrs();
179 void accumulateVBases();
183 void calculateZeroInit();
186 void clipTailPadding();
188 void determinePacked(
bool NVBaseType);
190 void insertPadding();
192 void fillOutputFields();
199 const llvm::DataLayout &DataLayout;
201 std::vector<MemberInfo> Members;
204 llvm::DenseMap<const FieldDecl *, unsigned> Fields;
205 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
206 llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
207 llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
208 bool IsZeroInitializable : 1;
209 bool IsZeroInitializableAsBase : 1;
212 CGRecordLowering(
const CGRecordLowering &) =
delete;
213 void operator =(
const CGRecordLowering &) =
delete;
218 : Types(Types),
Context(Types.getContext()), D(D),
220 Layout(Types.getContext().getASTRecordLayout(D)),
221 DataLayout(Types.getDataLayout()), IsZeroInitializable(
true),
222 IsZeroInitializableAsBase(
true), Packed(Packed) {}
224 void CGRecordLowering::setBitFieldInfo(
238 if (DataLayout.isBigEndian())
242 void CGRecordLowering::lower(
bool NVBaseType) {
263 CharUnits Size = NVBaseType ? Layout.getNonVirtualSize() : Layout.getSize();
272 return appendPaddingBytes(Size);
276 std::stable_sort(Members.begin(), Members.end());
277 Members.push_back(StorageInfo(Size, getIntNType(8)));
279 determinePacked(NVBaseType);
286 void CGRecordLowering::lowerUnion() {
288 llvm::Type *StorageType =
nullptr;
289 bool SeenNamedMember =
false;
295 for (
const auto *Field : D->fields()) {
296 if (Field->isBitField()) {
298 if (Field->getBitWidthValue(
Context) == 0)
300 llvm::Type *FieldType = getStorageType(Field);
301 if (LayoutSize < getSize(FieldType))
302 FieldType = getByteArrayType(LayoutSize);
305 Fields[Field->getCanonicalDecl()] = 0;
306 llvm::Type *FieldType = getStorageType(Field);
313 if (!SeenNamedMember) {
314 SeenNamedMember = Field->getIdentifier();
315 if (!SeenNamedMember)
316 if (
const auto *FieldRD =
317 dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
318 SeenNamedMember = FieldRD->findFirstNamedDataMember();
319 if (SeenNamedMember && !isZeroInitializable(Field)) {
320 IsZeroInitializable = IsZeroInitializableAsBase =
false;
321 StorageType = FieldType;
326 if (!IsZeroInitializable)
330 getAlignment(FieldType) > getAlignment(StorageType) ||
331 (getAlignment(FieldType) == getAlignment(StorageType) &&
332 getSize(FieldType) > getSize(StorageType)))
333 StorageType = FieldType;
337 return appendPaddingBytes(LayoutSize);
340 if (LayoutSize < getSize(StorageType))
341 StorageType = getByteArrayType(LayoutSize);
342 FieldTypes.push_back(StorageType);
343 appendPaddingBytes(LayoutSize - getSize(StorageType));
345 if (LayoutSize % getAlignment(StorageType))
349 void CGRecordLowering::accumulateFields() {
351 FieldEnd = D->field_end();
353 if (Field->isBitField()) {
356 for (++Field; Field != FieldEnd && Field->isBitField(); ++Field);
357 accumulateBitFields(Start, Field);
359 Members.push_back(MemberInfo(
360 bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
361 getStorageType(*Field), *Field));
378 uint64_t StartBitOffset, Tail = 0;
379 if (isDiscreteBitFieldABI()) {
380 for (; Field != FieldEnd; ++Field) {
381 uint64_t BitOffset = getFieldBitOffset(*Field);
383 if (Field->getBitWidthValue(
Context) == 0) {
387 llvm::Type *Type = Types.ConvertTypeForMem(Field->getType());
390 if (Run == FieldEnd || BitOffset >= Tail) {
392 StartBitOffset = BitOffset;
393 Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(Type);
397 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
401 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
402 MemberInfo::Field,
nullptr, *Field));
408 if (Run == FieldEnd) {
410 if (Field == FieldEnd)
413 if (Field->getBitWidthValue(
Context) != 0) {
415 StartBitOffset = getFieldBitOffset(*Field);
416 Tail = StartBitOffset + Field->getBitWidthValue(
Context);
422 if (Field != FieldEnd && Field->getBitWidthValue(
Context) != 0 &&
423 Tail == getFieldBitOffset(*Field)) {
424 Tail += Field->getBitWidthValue(
Context);
429 llvm::Type *Type = getIntNType(Tail - StartBitOffset);
433 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
434 for (; Run != Field; ++Run)
435 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
436 MemberInfo::Field,
nullptr, *Run));
441 void CGRecordLowering::accumulateBases() {
443 if (Layout.isPrimaryBaseVirtual()) {
446 getStorageType(BaseDecl), BaseDecl));
449 for (
const auto &
Base : RD->bases()) {
450 if (
Base.isVirtual())
458 Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
463 void CGRecordLowering::accumulateVPtrs() {
464 if (Layout.hasOwnVFPtr())
466 llvm::FunctionType::get(getIntNType(32),
true)->
467 getPointerTo()->getPointerTo()));
468 if (Layout.hasOwnVBPtr())
469 Members.push_back(MemberInfo(Layout.getVBPtrOffset(), MemberInfo::VBPtr,
470 llvm::Type::getInt32PtrTy(Types.getLLVMContext())));
473 void CGRecordLowering::accumulateVBases() {
474 CharUnits ScissorOffset = Layout.getNonVirtualSize();
479 if (isOverlappingVBaseABI())
480 for (
const auto &
Base : RD->vbases()) {
488 ScissorOffset = std::min(ScissorOffset,
489 Layout.getVBaseClassOffset(BaseDecl));
491 Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor,
nullptr,
493 for (
const auto &
Base : RD->vbases()) {
500 if (isOverlappingVBaseABI() &&
502 !hasOwnStorage(RD, BaseDecl)) {
503 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
nullptr,
508 if (Layout.getVBaseOffsetsMap().find(BaseDecl)->second.hasVtorDisp())
511 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
512 getStorageType(BaseDecl), BaseDecl));
522 if (!hasOwnStorage(
Base.getType()->getAsCXXRecordDecl(), Query))
527 void CGRecordLowering::calculateZeroInit() {
528 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
529 MemberEnd = Members.end();
530 IsZeroInitializableAsBase && Member != MemberEnd; ++Member) {
531 if (Member->Kind == MemberInfo::Field) {
532 if (!Member->FD || isZeroInitializable(Member->FD))
534 IsZeroInitializable = IsZeroInitializableAsBase =
false;
536 Member->Kind == MemberInfo::VBase) {
537 if (isZeroInitializable(Member->RD))
539 IsZeroInitializable =
false;
541 IsZeroInitializableAsBase =
false;
546 void CGRecordLowering::clipTailPadding() {
547 std::vector<MemberInfo>::iterator Prior = Members.begin();
549 for (std::vector<MemberInfo>::iterator Member = Prior + 1,
550 MemberEnd = Members.end();
551 Member != MemberEnd; ++Member) {
553 if (!Member->Data && Member->Kind != MemberInfo::Scissor)
555 if (Member->Offset < Tail) {
556 assert(Prior->Kind == MemberInfo::Field && !Prior->FD &&
557 "Only storage fields have tail padding!");
558 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::RoundUpToAlignment(
559 cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));
563 Tail = Prior->Offset + getSize(Prior->Data);
567 void CGRecordLowering::determinePacked(
bool NVBaseType) {
574 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
575 MemberEnd = Members.end();
576 Member != MemberEnd; ++Member) {
581 if (Member->Offset % getAlignment(Member->Data))
583 if (Member->Offset < NVSize)
584 NVAlignment = std::max(NVAlignment, getAlignment(Member->Data));
585 Alignment = std::max(Alignment, getAlignment(Member->Data));
589 if (Members.back().Offset % Alignment)
594 if (NVSize % NVAlignment)
598 Members.back().Data = getIntNType(
Context.
toBits(Alignment));
601 void CGRecordLowering::insertPadding() {
602 std::vector<std::pair<CharUnits, CharUnits> > Padding;
604 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
605 MemberEnd = Members.end();
606 Member != MemberEnd; ++Member) {
610 assert(Offset >= Size);
613 getAlignment(Member->Data)))
614 Padding.push_back(std::make_pair(Size, Offset - Size));
615 Size = Offset + getSize(Member->Data);
620 for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator
621 Pad = Padding.begin(), PadEnd = Padding.end();
622 Pad != PadEnd; ++Pad)
623 Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second)));
624 std::stable_sort(Members.begin(), Members.end());
627 void CGRecordLowering::fillOutputFields() {
628 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
629 MemberEnd = Members.end();
630 Member != MemberEnd; ++Member) {
632 FieldTypes.push_back(Member->Data);
633 if (Member->Kind == MemberInfo::Field) {
635 Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1;
638 setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back());
640 NonVirtualBases[Member->RD] = FieldTypes.size() - 1;
641 else if (Member->Kind == MemberInfo::VBase)
642 VirtualBases[Member->RD] = FieldTypes.size() - 1;
648 uint64_t Offset, uint64_t Size,
649 uint64_t StorageSize,
661 if (Size > TypeSizeInBits) {
671 Size = TypeSizeInBits;
679 Offset = StorageSize - (Offset +
Size);
682 return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
686 llvm::StructType *Ty) {
687 CGRecordLowering
Builder(*
this, D,
false);
689 Builder.lower(
false);
692 llvm::StructType *BaseTy =
nullptr;
693 if (isa<CXXRecordDecl>(D) && !D->
isUnion() && !D->
hasAttr<FinalAttr>()) {
695 if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
696 CGRecordLowering BaseBuilder(*
this, D, Builder.Packed);
697 BaseBuilder.lower(
true);
699 getLLVMContext(), BaseBuilder.FieldTypes,
"", BaseBuilder.Packed);
703 assert(Builder.Packed == BaseBuilder.Packed &&
704 "Non-virtual and complete types must agree on packedness");
711 Ty->setBody(Builder.FieldTypes, Builder.Packed);
715 Builder.IsZeroInitializableAsBase);
717 RL->NonVirtualBases.swap(Builder.NonVirtualBases);
718 RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
721 RL->FieldInfo.swap(Builder.Fields);
724 RL->BitFields.swap(Builder.BitFields);
727 if (
getContext().getLangOpts().DumpRecordLayouts) {
728 llvm::outs() <<
"\n*** Dumping IRgen Record Layout\n";
729 llvm::outs() <<
"Record: ";
730 D->
dump(llvm::outs());
731 llvm::outs() <<
"\nLayout: ";
732 RL->
print(llvm::outs());
740 assert(TypeSizeInBits ==
getDataLayout().getTypeAllocSizeInBits(Ty) &&
741 "Type size mismatch!");
746 uint64_t AlignedNonVirtualTypeSizeInBits =
749 assert(AlignedNonVirtualTypeSizeInBits ==
751 "Type size mismatch!");
755 llvm::StructType *ST =
757 const llvm::StructLayout *SL =
getDataLayout().getStructLayout(ST);
761 for (
unsigned i = 0, e = AST_RL.
getFieldCount(); i != e; ++i, ++it) {
768 assert(AST_RL.
getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
769 "Invalid field offset!");
782 llvm::Type *ElementTy = ST->getTypeAtIndex(RL->
getLLVMFieldNo(FD));
793 assert(static_cast<unsigned>(Info.
Offset + Info.
Size) ==
795 "Big endian union bitfield does not end at the back");
797 assert(Info.
Offset == 0 &&
798 "Little endian union bitfield with a non-zero offset");
800 "Union not large enough for bitfield storage");
804 "Storage size does not match the element type size");
806 assert(Info.
Size > 0 &&
"Empty bitfield!");
808 "Bitfield outside of its allocated storage");
816 OS <<
"<CGRecordLayout\n";
817 OS <<
" LLVMType:" << *CompleteObjectType <<
"\n";
818 if (BaseSubobjectType)
819 OS <<
" NonVirtualBaseLLVMType:" << *BaseSubobjectType <<
"\n";
820 OS <<
" IsZeroInitializable:" << IsZeroInitializable <<
"\n";
821 OS <<
" BitFields:[\n";
824 std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
825 for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
826 it = BitFields.begin(), ie = BitFields.end();
833 BFIs.push_back(std::make_pair(Index, &it->second));
835 llvm::array_pod_sort(BFIs.begin(), BFIs.end());
836 for (
unsigned i = 0, e = BFIs.size(); i != e; ++i) {
838 BFIs[i].second->print(OS);
850 OS <<
"<CGBitFieldInfo"
851 <<
" Offset:" << Offset
Defines the clang::ASTContext interface.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool isBitField() const
Determines whether this field is a bitfield.
void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix)
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTContext & getContext() const
bool isPrimaryBaseVirtual() const
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
field_iterator field_begin() const
const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const
Return the BitFieldInfo that corresponds to the field FD.
llvm::Type * ConvertTypeForMem(QualType T)
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
bool isNearlyEmpty(const CXXRecordDecl *RD) const
unsigned Size
The total size of the bit-field, in bits.
const TargetInfo & getTargetInfo() const
CharUnits StorageOffset
The offset of the bitfield storage from the start of the struct.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
uint64_t getFieldOffset(unsigned FieldNo) const
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types, const FieldDecl *FD, uint64_t Offset, uint64_t Size, uint64_t StorageSize, CharUnits StorageOffset)
Given a bit-field decl, build an appropriate helper object for accessing that field (which is expecte...
bool isSignedIntegerOrEnumerationType() const
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
DeclarationName getDeclName() const
void print(raw_ostream &OS) const
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getBitWidthValue(const ASTContext &Ctx) const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
const llvm::DataLayout & getDataLayout() const
llvm::LLVMContext & getLLVMContext()
bool operator<(DeclarationName LHS, DeclarationName RHS)
void print(raw_ostream &OS) const
bool isZero() const
isZero - Test whether the quantity equals zero.
unsigned IsSigned
Whether the bit-field is signed.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
CharUnits getNonVirtualSize() const
unsigned getFieldIndex() const
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Represents a C++ struct/union/class.
BoundNodesTreeBuilder *const Builder
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
CGRecordLayout * ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty)
Compute a new LLVM record layout object for the given record.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
CharUnits RoundUpToAlignment(const CharUnits &Align) const
bool isZeroInitializable(QualType T)
Structure with information about how a bitfield should be accessed.