23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/Type.h" 26 #include "llvm/Support/Debug.h" 27 #include "llvm/Support/MathExtras.h" 28 #include "llvm/Support/raw_ostream.h" 29 using namespace clang;
30 using namespace CodeGen;
73 struct CGRecordLowering {
79 enum InfoKind { VFPtr, VBPtr,
Field,
Base, VBase, Scissor }
Kind;
87 : Offset(Offset), Kind(Kind), Data(Data), FD(FD) {}
90 : Offset(Offset), Kind(Kind), Data(Data), RD(RD) {}
92 bool operator <(
const MemberInfo&
a)
const {
return Offset < a.Offset; }
99 return MemberInfo(Offset, MemberInfo::Field, Data);
107 bool isDiscreteBitFieldABI() {
109 D->isMsStruct(Context);
116 bool isOverlappingVBaseABI() {
122 return llvm::Type::getIntNTy(Types.getLLVMContext(),
123 (unsigned)llvm::alignTo(NumBits, 8));
127 assert(!NumBytes.
isZero() &&
"Empty byte arrays aren't allowed.");
130 (
llvm::Type *)llvm::ArrayType::get(Type, NumBytes.getQuantity());
137 if (isDiscreteBitFieldABI())
return Type;
139 (unsigned)Context.
toBits(getSize(Type))));
143 return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType();
145 CharUnits bitsToCharUnits(uint64_t BitOffset) {
155 return Types.isZeroInitializable(FD->
getType());
158 return Types.isZeroInitializable(RD);
160 void appendPaddingBytes(
CharUnits Size) {
162 FieldTypes.push_back(getByteArrayType(Size));
164 uint64_t getFieldBitOffset(
const FieldDecl *FD) {
171 void lower(
bool NonVirtualBaseType);
173 void accumulateFields();
176 void accumulateBases();
177 void accumulateVPtrs();
178 void accumulateVBases();
182 void calculateZeroInit();
185 void clipTailPadding();
187 void determinePacked(
bool NVBaseType);
189 void insertPadding();
191 void fillOutputFields();
198 const llvm::DataLayout &DataLayout;
200 std::vector<MemberInfo> Members;
203 llvm::DenseMap<const FieldDecl *, unsigned> Fields;
204 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
205 llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
206 llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
207 bool IsZeroInitializable : 1;
208 bool IsZeroInitializableAsBase : 1;
211 CGRecordLowering(
const CGRecordLowering &) =
delete;
212 void operator =(
const CGRecordLowering &) =
delete;
218 : Types(Types), Context(Types.
getContext()), D(D),
220 Layout(Types.
getContext().getASTRecordLayout(D)),
222 IsZeroInitializableAsBase(
true), Packed(Packed) {}
224 void CGRecordLowering::setBitFieldInfo(
228 Info.
Offset = (unsigned)(getFieldBitOffset(FD) - Context.
toBits(StartOffset));
230 Info.
StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
238 if (DataLayout.isBigEndian())
242 void CGRecordLowering::lower(
bool NVBaseType) {
263 CharUnits Size = NVBaseType ? Layout.getNonVirtualSize() : Layout.getSize();
272 return appendPaddingBytes(Size);
276 llvm::stable_sort(Members);
277 Members.push_back(StorageInfo(Size, getIntNType(8)));
279 determinePacked(NVBaseType);
286 void CGRecordLowering::lowerUnion() {
289 bool SeenNamedMember =
false;
295 for (
const auto *Field : D->fields()) {
296 if (
Field->isBitField()) {
297 if (
Field->isZeroLengthBitField(Context))
299 llvm::Type *FieldType = getStorageType(Field);
300 if (LayoutSize < getSize(FieldType))
301 FieldType = getByteArrayType(LayoutSize);
304 Fields[
Field->getCanonicalDecl()] = 0;
305 llvm::Type *FieldType = getStorageType(Field);
312 if (!SeenNamedMember) {
313 SeenNamedMember =
Field->getIdentifier();
314 if (!SeenNamedMember)
315 if (
const auto *FieldRD =
Field->getType()->getAsRecordDecl())
316 SeenNamedMember = FieldRD->findFirstNamedDataMember();
318 IsZeroInitializable = IsZeroInitializableAsBase =
false;
319 StorageType = FieldType;
324 if (!IsZeroInitializable)
328 getAlignment(FieldType) > getAlignment(StorageType) ||
329 (getAlignment(FieldType) == getAlignment(StorageType) &&
330 getSize(FieldType) > getSize(StorageType)))
331 StorageType = FieldType;
335 return appendPaddingBytes(LayoutSize);
338 if (LayoutSize < getSize(StorageType))
339 StorageType = getByteArrayType(LayoutSize);
340 FieldTypes.push_back(StorageType);
341 appendPaddingBytes(LayoutSize - getSize(StorageType));
343 if (LayoutSize % getAlignment(StorageType))
347 void CGRecordLowering::accumulateFields() {
349 FieldEnd = D->field_end();
350 Field != FieldEnd;) {
351 if (
Field->isBitField()) {
355 accumulateBitFields(Start, Field);
356 }
else if (!
Field->isZeroSize(Context)) {
357 Members.push_back(MemberInfo(
358 bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
359 getStorageType(*Field), *Field));
379 uint64_t StartBitOffset, Tail = 0;
380 if (isDiscreteBitFieldABI()) {
381 for (; Field != FieldEnd; ++Field) {
382 uint64_t BitOffset = getFieldBitOffset(*Field);
384 if (Field->isZeroLengthBitField(Context)) {
388 llvm::Type *Type = Types.ConvertTypeForMem(Field->getType());
391 if (Run == FieldEnd || BitOffset >= Tail) {
393 StartBitOffset = BitOffset;
394 Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(Type);
398 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
402 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
403 MemberInfo::Field,
nullptr, *Field));
412 auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord,
413 uint64_t StartBitOffset) {
414 if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
416 if (!DataLayout.isLegalInteger(OffsetInRecord))
421 Context.
toBits(getAlignment(getIntNType(OffsetInRecord))) !=
428 bool StartFieldAsSingleRun =
false;
431 if (Run == FieldEnd) {
433 if (Field == FieldEnd)
436 if (!Field->isZeroLengthBitField(Context)) {
438 StartBitOffset = getFieldBitOffset(*Field);
439 Tail = StartBitOffset + Field->getBitWidthValue(Context);
440 StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Tail - StartBitOffset,
456 if (!StartFieldAsSingleRun && Field != FieldEnd &&
457 !IsBetterAsSingleFieldRun(Tail - StartBitOffset, StartBitOffset) &&
458 (!Field->isZeroLengthBitField(Context) ||
461 Tail == getFieldBitOffset(*Field)) {
462 Tail += Field->getBitWidthValue(Context);
468 llvm::Type *Type = getIntNType(Tail - StartBitOffset);
472 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
473 for (; Run != Field; ++Run)
474 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
475 MemberInfo::Field,
nullptr, *Run));
477 StartFieldAsSingleRun =
false;
481 void CGRecordLowering::accumulateBases() {
483 if (Layout.isPrimaryBaseVirtual()) {
486 getStorageType(BaseDecl), BaseDecl));
489 for (
const auto &
Base : RD->bases()) {
490 if (
Base.isVirtual())
498 Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
499 MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
503 void CGRecordLowering::accumulateVPtrs() {
504 if (Layout.hasOwnVFPtr())
506 llvm::FunctionType::get(getIntNType(32),
true)->
507 getPointerTo()->getPointerTo()));
508 if (Layout.hasOwnVBPtr())
509 Members.push_back(MemberInfo(Layout.getVBPtrOffset(), MemberInfo::VBPtr,
510 llvm::Type::getInt32PtrTy(Types.getLLVMContext())));
513 void CGRecordLowering::accumulateVBases() {
514 CharUnits ScissorOffset = Layout.getNonVirtualSize();
519 if (isOverlappingVBaseABI())
520 for (
const auto &
Base : RD->vbases()) {
526 if (Context.
isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl))
528 ScissorOffset =
std::min(ScissorOffset,
529 Layout.getVBaseClassOffset(BaseDecl));
531 Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor,
nullptr,
533 for (
const auto &
Base : RD->vbases()) {
540 if (isOverlappingVBaseABI() &&
542 !hasOwnStorage(RD, BaseDecl)) {
543 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
nullptr,
548 if (Layout.getVBaseOffsetsMap().find(BaseDecl)->second.hasVtorDisp())
551 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
552 getStorageType(BaseDecl), BaseDecl));
562 if (!hasOwnStorage(
Base.getType()->getAsCXXRecordDecl(), Query))
567 void CGRecordLowering::calculateZeroInit() {
568 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
569 MemberEnd = Members.end();
570 IsZeroInitializableAsBase && Member != MemberEnd; ++Member) {
571 if (Member->Kind == MemberInfo::Field) {
574 IsZeroInitializable = IsZeroInitializableAsBase =
false;
575 }
else if (Member->Kind == MemberInfo::Base ||
576 Member->Kind == MemberInfo::VBase) {
579 IsZeroInitializable =
false;
580 if (Member->Kind == MemberInfo::Base)
581 IsZeroInitializableAsBase =
false;
586 void CGRecordLowering::clipTailPadding() {
587 std::vector<MemberInfo>::iterator Prior = Members.begin();
589 for (std::vector<MemberInfo>::iterator Member = Prior + 1,
590 MemberEnd = Members.end();
591 Member != MemberEnd; ++Member) {
593 if (!Member->Data && Member->Kind != MemberInfo::Scissor)
595 if (Member->Offset < Tail) {
596 assert(Prior->Kind == MemberInfo::Field &&
597 "Only storage fields have tail padding!");
598 if (!Prior->FD || Prior->FD->isBitField())
599 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
600 cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));
602 assert(Prior->FD->hasAttr<NoUniqueAddressAttr>() &&
603 "should not have reused this field's tail padding");
604 Prior->Data = getByteArrayType(
610 Tail = Prior->Offset + getSize(Prior->Data);
614 void CGRecordLowering::determinePacked(
bool NVBaseType) {
621 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
622 MemberEnd = Members.end();
623 Member != MemberEnd; ++Member) {
628 if (Member->Offset % getAlignment(Member->Data))
630 if (Member->Offset < NVSize)
631 NVAlignment =
std::max(NVAlignment, getAlignment(Member->Data));
632 Alignment =
std::max(Alignment, getAlignment(Member->Data));
636 if (Members.back().Offset % Alignment)
641 if (NVSize % NVAlignment)
645 Members.back().Data = getIntNType(Context.
toBits(Alignment));
648 void CGRecordLowering::insertPadding() {
649 std::vector<std::pair<CharUnits, CharUnits> > Padding;
651 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
652 MemberEnd = Members.end();
653 Member != MemberEnd; ++Member) {
657 assert(Offset >= Size);
661 Padding.push_back(std::make_pair(Size, Offset - Size));
662 Size = Offset + getSize(Member->Data);
667 for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator
668 Pad = Padding.begin(), PadEnd = Padding.end();
669 Pad != PadEnd; ++Pad)
670 Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second)));
671 llvm::stable_sort(Members);
674 void CGRecordLowering::fillOutputFields() {
675 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
676 MemberEnd = Members.end();
677 Member != MemberEnd; ++Member) {
679 FieldTypes.push_back(Member->Data);
680 if (Member->Kind == MemberInfo::Field) {
682 Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1;
685 setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back());
686 }
else if (Member->Kind == MemberInfo::Base)
687 NonVirtualBases[Member->RD] = FieldTypes.size() - 1;
688 else if (Member->Kind == MemberInfo::VBase)
689 VirtualBases[Member->RD] = FieldTypes.size() - 1;
695 uint64_t Offset, uint64_t Size,
696 uint64_t StorageSize,
708 if (Size > TypeSizeInBits) {
718 Size = TypeSizeInBits;
726 Offset = StorageSize - (Offset + Size);
729 return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
733 llvm::StructType *Ty) {
734 CGRecordLowering Builder(*
this, D,
false);
736 Builder.lower(
false);
739 llvm::StructType *BaseTy =
nullptr;
740 if (isa<CXXRecordDecl>(D) && !D->
isUnion() && !D->
hasAttr<FinalAttr>()) {
742 if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
743 CGRecordLowering BaseBuilder(*
this, D, Builder.Packed);
744 BaseBuilder.lower(
true);
746 getLLVMContext(), BaseBuilder.FieldTypes,
"", BaseBuilder.Packed);
747 addRecordTypeName(D, BaseTy,
".base");
750 assert(Builder.Packed == BaseBuilder.Packed &&
751 "Non-virtual and complete types must agree on packedness");
758 Ty->setBody(Builder.FieldTypes, Builder.Packed);
762 Builder.IsZeroInitializableAsBase);
764 RL->NonVirtualBases.swap(Builder.NonVirtualBases);
765 RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
768 RL->FieldInfo.swap(Builder.Fields);
771 RL->BitFields.swap(Builder.BitFields);
774 if (getContext().getLangOpts().DumpRecordLayouts) {
775 llvm::outs() <<
"\n*** Dumping IRgen Record Layout\n";
776 llvm::outs() <<
"Record: ";
777 D->
dump(llvm::outs());
778 llvm::outs() <<
"\nLayout: ";
779 RL->
print(llvm::outs());
786 uint64_t TypeSizeInBits = getContext().toBits(Layout.
getSize());
787 assert(TypeSizeInBits == getDataLayout().getTypeAllocSizeInBits(Ty) &&
788 "Type size mismatch!");
793 uint64_t AlignedNonVirtualTypeSizeInBits =
794 getContext().toBits(NonVirtualSize);
796 assert(AlignedNonVirtualTypeSizeInBits ==
797 getDataLayout().getTypeAllocSizeInBits(BaseTy) &&
798 "Type size mismatch!");
803 const llvm::StructLayout *SL = getDataLayout().getStructLayout(ST);
818 assert(AST_RL.
getFieldOffset(
i) == SL->getElementOffsetInBits(FieldNo) &&
819 "Invalid field offset!");
838 if (getDataLayout().isBigEndian())
839 assert(static_cast<unsigned>(Info.
Offset + Info.
Size) ==
841 "Big endian union bitfield does not end at the back");
843 assert(Info.
Offset == 0 &&
844 "Little endian union bitfield with a non-zero offset");
846 "Union not large enough for bitfield storage");
849 getDataLayout().getTypeAllocSizeInBits(ElementTy) &&
850 "Storage size does not match the element type size");
852 assert(Info.
Size > 0 &&
"Empty bitfield!");
854 "Bitfield outside of its allocated storage");
862 OS <<
"<CGRecordLayout\n";
863 OS <<
" LLVMType:" << *CompleteObjectType <<
"\n";
864 if (BaseSubobjectType)
865 OS <<
" NonVirtualBaseLLVMType:" << *BaseSubobjectType <<
"\n";
866 OS <<
" IsZeroInitializable:" << IsZeroInitializable <<
"\n";
867 OS <<
" BitFields:[\n";
870 std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
871 for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
872 it = BitFields.begin(), ie = BitFields.end();
879 BFIs.push_back(std::make_pair(Index, &it->second));
881 llvm::array_pod_sort(BFIs.begin(), BFIs.end());
882 for (
unsigned i = 0, e = BFIs.size();
i != e; ++
i) {
884 BFIs[
i].second->print(OS);
896 OS <<
"<CGBitFieldInfo" 897 <<
" Offset:" << Offset
899 <<
" IsSigned:" << IsSigned
900 <<
" StorageSize:" << StorageSize
901 <<
" StorageOffset:" << StorageOffset.
getQuantity() <<
">";
Defines the clang::ASTContext interface.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const
Return the BitFieldInfo that corresponds to the field FD.
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
Decl - This represents one declaration (or definition), e.g.
const llvm::DataLayout & getDataLayout() const
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
The base class of the type hierarchy.
bool isZero() const
isZero - Test whether the quantity equals zero.
const TargetInfo & getTargetInfo() const
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
Represents a struct/union/class.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
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 ...
Represents a member of a struct/union/class.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
__DEVICE__ int max(int __a, int __b)
unsigned Size
The total size of the bit-field, in bits.
bool isBitField() const
Determines whether this field is a bitfield.
CharUnits - This is an opaque type for sizes expressed in character units.
CharUnits StorageOffset
The offset of the bitfield storage from the start of the struct.
field_iterator field_begin() const
unsigned getBitWidthValue(const ASTContext &Ctx) const
unsigned Offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the L...
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
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...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool isNearlyEmpty(const CXXRecordDecl *RD) const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
void print(raw_ostream &OS) const
std::pair< CharUnits, CharUnits > getTypeInfoDataSizeInChars(QualType T) const
The l-value was considered opaque, so the alignment was determined from a type.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
Dataflow Directional Tag Classes.
CharUnits getSize() const
getSize - Get the record size in characters.
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.
unsigned StorageSize
The storage size in bits which should be used when accessing this bitfield.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
void print(raw_ostream &OS) const
This class organizes the cross-module state that is used while lowering AST types to LLVM types...
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
ASTContext & getContext() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
true
A convenience builder class for complex constant initializers, especially for anonymous global struct...
Represents a C++ struct/union/class.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
__DEVICE__ int min(int __a, int __b)
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
CGRecordLayout * ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty)
Compute a new LLVM record layout object for the given record.
bool isZeroSize(const ASTContext &Ctx) const
Determine if this field is a subobject of zero size, that is, either a zero-length bit-field or a fie...
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
Structure with information about how a bitfield should be accessed.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.