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() {
123 return llvm::Type::getIntNTy(Types.getLLVMContext(),
124 (
unsigned)llvm::alignTo(NumBits, 8));
128 assert(!NumBytes.
isZero() &&
"Empty byte arrays aren't allowed.");
131 (
llvm::Type *)llvm::ArrayType::get(Type, NumBytes.getQuantity());
138 if (isDiscreteBitFieldABI())
return Type;
144 return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType();
146 CharUnits bitsToCharUnits(uint64_t BitOffset) {
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) {
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() {
289 bool SeenNamedMember =
false;
295 for (
const auto *Field : D->fields()) {
296 if (
Field->isBitField()) {
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()) {
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() {
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::alignTo(
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);
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!");
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.
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix)
addRecordTypeName - Compute a name from the given record decl with an optional suffix and name the gi...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTContext & getContext() const
The base class of the type hierarchy.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
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 ...
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)
ConvertTypeForMem - Convert type T into a llvm::Type.
RecordDecl - Represents a struct/union/class.
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 ...
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
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 - 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.
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
getFieldOffset - Get the offset of the given field index, in bits.
unsigned Offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the L...
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...
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
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.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
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
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
void print(raw_ostream &OS) const
The l-value was considered opaque, so the alignment was determined from a type.
CharUnits getSize() const
getSize - Get the record size in characters.
const TemplateArgument * iterator
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)
Ordering on two declaration names.
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.
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).
This class organizes the cross-module state that is used while lowering AST types to LLVM types...
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
unsigned getFieldIndex() const
getFieldIndex - Returns the index of this field within its record, as appropriate for passing to ASTR...
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
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.
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.