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) {}
93 bool operator <(
const MemberInfo& a)
const {
return Offset < a.Offset; }
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;
140 (unsigned)Context.
toBits(getSize(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;
219 : Types(Types), Context(Types.
getContext()), D(D),
221 Layout(Types.
getContext().getASTRecordLayout(D)),
223 IsZeroInitializableAsBase(
true), Packed(Packed) {}
225 void CGRecordLowering::setBitFieldInfo(
229 Info.
Offset = (unsigned)(getFieldBitOffset(FD) - Context.
toBits(StartOffset));
231 Info.
StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
239 if (DataLayout.isBigEndian())
243 void CGRecordLowering::lower(
bool NVBaseType) {
264 CharUnits Size = NVBaseType ? Layout.getNonVirtualSize() : Layout.getSize();
273 return appendPaddingBytes(Size);
277 std::stable_sort(Members.begin(), Members.end());
278 Members.push_back(StorageInfo(Size, getIntNType(8)));
280 determinePacked(NVBaseType);
287 void CGRecordLowering::lowerUnion() {
290 bool SeenNamedMember =
false;
296 for (
const auto *Field : D->fields()) {
297 if (
Field->isBitField()) {
298 if (
Field->isZeroLengthBitField(Context))
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 =
Field->getType()->getAsRecordDecl())
317 SeenNamedMember = FieldRD->findFirstNamedDataMember();
319 IsZeroInitializable = IsZeroInitializableAsBase =
false;
320 StorageType = FieldType;
325 if (!IsZeroInitializable)
329 getAlignment(FieldType) > getAlignment(StorageType) ||
330 (getAlignment(FieldType) == getAlignment(StorageType) &&
331 getSize(FieldType) > getSize(StorageType)))
332 StorageType = FieldType;
336 return appendPaddingBytes(LayoutSize);
339 if (LayoutSize < getSize(StorageType))
340 StorageType = getByteArrayType(LayoutSize);
341 FieldTypes.push_back(StorageType);
342 appendPaddingBytes(LayoutSize - getSize(StorageType));
344 if (LayoutSize % getAlignment(StorageType))
348 void CGRecordLowering::accumulateFields() {
350 FieldEnd = D->field_end();
352 if (
Field->isBitField()) {
356 accumulateBitFields(Start, Field);
358 Members.push_back(MemberInfo(
359 bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
360 getStorageType(*Field), *Field));
377 uint64_t StartBitOffset, Tail = 0;
378 if (isDiscreteBitFieldABI()) {
379 for (; Field != FieldEnd; ++Field) {
380 uint64_t BitOffset = getFieldBitOffset(*Field);
382 if (Field->isZeroLengthBitField(Context)) {
386 llvm::Type *Type = Types.ConvertTypeForMem(Field->getType());
389 if (Run == FieldEnd || BitOffset >= Tail) {
391 StartBitOffset = BitOffset;
392 Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(Type);
396 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
400 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
401 MemberInfo::Field,
nullptr, *Field));
410 auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord,
411 uint64_t StartBitOffset) {
412 if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
414 if (!DataLayout.isLegalInteger(OffsetInRecord))
419 Context.
toBits(getAlignment(getIntNType(OffsetInRecord))) !=
426 bool StartFieldAsSingleRun =
false;
429 if (Run == FieldEnd) {
431 if (Field == FieldEnd)
434 if (!Field->isZeroLengthBitField(Context)) {
436 StartBitOffset = getFieldBitOffset(*Field);
437 Tail = StartBitOffset + Field->getBitWidthValue(Context);
438 StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Tail - StartBitOffset,
454 if (!StartFieldAsSingleRun && Field != FieldEnd &&
455 !IsBetterAsSingleFieldRun(Tail - StartBitOffset, StartBitOffset) &&
456 (!Field->isZeroLengthBitField(Context) ||
459 Tail == getFieldBitOffset(*Field)) {
460 Tail += Field->getBitWidthValue(Context);
466 llvm::Type *Type = getIntNType(Tail - StartBitOffset);
470 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
471 for (; Run != Field; ++Run)
472 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
473 MemberInfo::Field,
nullptr, *Run));
475 StartFieldAsSingleRun =
false;
479 void CGRecordLowering::accumulateBases() {
481 if (Layout.isPrimaryBaseVirtual()) {
484 getStorageType(BaseDecl), BaseDecl));
487 for (
const auto &
Base : RD->bases()) {
488 if (
Base.isVirtual())
496 Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
501 void CGRecordLowering::accumulateVPtrs() {
502 if (Layout.hasOwnVFPtr())
504 llvm::FunctionType::get(getIntNType(32),
true)->
505 getPointerTo()->getPointerTo()));
506 if (Layout.hasOwnVBPtr())
507 Members.push_back(MemberInfo(Layout.getVBPtrOffset(), MemberInfo::VBPtr,
508 llvm::Type::getInt32PtrTy(Types.getLLVMContext())));
511 void CGRecordLowering::accumulateVBases() {
512 CharUnits ScissorOffset = Layout.getNonVirtualSize();
517 if (isOverlappingVBaseABI())
518 for (
const auto &
Base : RD->vbases()) {
524 if (Context.
isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl))
526 ScissorOffset =
std::min(ScissorOffset,
527 Layout.getVBaseClassOffset(BaseDecl));
529 Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor,
nullptr,
531 for (
const auto &
Base : RD->vbases()) {
538 if (isOverlappingVBaseABI() &&
540 !hasOwnStorage(RD, BaseDecl)) {
541 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
nullptr,
546 if (Layout.getVBaseOffsetsMap().find(BaseDecl)->second.hasVtorDisp())
549 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
550 getStorageType(BaseDecl), BaseDecl));
560 if (!hasOwnStorage(
Base.getType()->getAsCXXRecordDecl(), Query))
565 void CGRecordLowering::calculateZeroInit() {
566 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
567 MemberEnd = Members.end();
568 IsZeroInitializableAsBase && Member != MemberEnd; ++Member) {
569 if (Member->Kind == MemberInfo::Field) {
572 IsZeroInitializable = IsZeroInitializableAsBase =
false;
574 Member->Kind == MemberInfo::VBase) {
577 IsZeroInitializable =
false;
579 IsZeroInitializableAsBase =
false;
584 void CGRecordLowering::clipTailPadding() {
585 std::vector<MemberInfo>::iterator Prior = Members.begin();
587 for (std::vector<MemberInfo>::iterator Member = Prior + 1,
588 MemberEnd = Members.end();
589 Member != MemberEnd; ++Member) {
591 if (!Member->Data && Member->Kind != MemberInfo::Scissor)
593 if (Member->Offset < Tail) {
594 assert(Prior->Kind == MemberInfo::Field && !Prior->FD &&
595 "Only storage fields have tail padding!");
596 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
597 cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));
601 Tail = Prior->Offset + getSize(Prior->Data);
605 void CGRecordLowering::determinePacked(
bool NVBaseType) {
612 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
613 MemberEnd = Members.end();
614 Member != MemberEnd; ++Member) {
619 if (Member->Offset % getAlignment(Member->Data))
621 if (Member->Offset < NVSize)
622 NVAlignment =
std::max(NVAlignment, getAlignment(Member->Data));
623 Alignment =
std::max(Alignment, getAlignment(Member->Data));
627 if (Members.back().Offset % Alignment)
632 if (NVSize % NVAlignment)
636 Members.back().Data = getIntNType(Context.
toBits(Alignment));
639 void CGRecordLowering::insertPadding() {
640 std::vector<std::pair<CharUnits, CharUnits> > Padding;
642 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
643 MemberEnd = Members.end();
644 Member != MemberEnd; ++Member) {
648 assert(Offset >= Size);
652 Padding.push_back(std::make_pair(Size, Offset - Size));
653 Size = Offset + getSize(Member->Data);
658 for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator
659 Pad = Padding.begin(), PadEnd = Padding.end();
660 Pad != PadEnd; ++Pad)
661 Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second)));
662 std::stable_sort(Members.begin(), Members.end());
665 void CGRecordLowering::fillOutputFields() {
666 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
667 MemberEnd = Members.end();
668 Member != MemberEnd; ++Member) {
670 FieldTypes.push_back(Member->Data);
671 if (Member->Kind == MemberInfo::Field) {
673 Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1;
676 setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back());
678 NonVirtualBases[Member->RD] = FieldTypes.size() - 1;
679 else if (Member->Kind == MemberInfo::VBase)
680 VirtualBases[Member->RD] = FieldTypes.size() - 1;
686 uint64_t Offset, uint64_t Size,
687 uint64_t StorageSize,
699 if (Size > TypeSizeInBits) {
709 Size = TypeSizeInBits;
717 Offset = StorageSize - (Offset + Size);
720 return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
724 llvm::StructType *Ty) {
725 CGRecordLowering Builder(*
this, D,
false);
727 Builder.lower(
false);
730 llvm::StructType *BaseTy =
nullptr;
731 if (isa<CXXRecordDecl>(D) && !D->
isUnion() && !D->
hasAttr<FinalAttr>()) {
733 if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
734 CGRecordLowering BaseBuilder(*
this, D, Builder.Packed);
735 BaseBuilder.lower(
true);
737 getLLVMContext(), BaseBuilder.FieldTypes,
"", BaseBuilder.Packed);
738 addRecordTypeName(D, BaseTy,
".base");
741 assert(Builder.Packed == BaseBuilder.Packed &&
742 "Non-virtual and complete types must agree on packedness");
749 Ty->setBody(Builder.FieldTypes, Builder.Packed);
753 Builder.IsZeroInitializableAsBase);
755 RL->NonVirtualBases.swap(Builder.NonVirtualBases);
756 RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
759 RL->FieldInfo.swap(Builder.Fields);
762 RL->BitFields.swap(Builder.BitFields);
765 if (getContext().getLangOpts().DumpRecordLayouts) {
766 llvm::outs() <<
"\n*** Dumping IRgen Record Layout\n";
767 llvm::outs() <<
"Record: ";
768 D->
dump(llvm::outs());
769 llvm::outs() <<
"\nLayout: ";
770 RL->
print(llvm::outs());
777 uint64_t TypeSizeInBits = getContext().toBits(Layout.
getSize());
778 assert(TypeSizeInBits == getDataLayout().getTypeAllocSizeInBits(Ty) &&
779 "Type size mismatch!");
784 uint64_t AlignedNonVirtualTypeSizeInBits =
785 getContext().toBits(NonVirtualSize);
787 assert(AlignedNonVirtualTypeSizeInBits ==
788 getDataLayout().getTypeAllocSizeInBits(BaseTy) &&
789 "Type size mismatch!");
794 const llvm::StructLayout *SL = getDataLayout().getStructLayout(ST);
798 for (
unsigned i = 0, e = AST_RL.
getFieldCount(); i != e; ++i, ++it) {
805 assert(AST_RL.
getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
806 "Invalid field offset!");
829 if (getDataLayout().isBigEndian())
830 assert(static_cast<unsigned>(Info.
Offset + Info.
Size) ==
832 "Big endian union bitfield does not end at the back");
834 assert(Info.
Offset == 0 &&
835 "Little endian union bitfield with a non-zero offset");
837 "Union not large enough for bitfield storage");
840 getDataLayout().getTypeAllocSizeInBits(ElementTy) &&
841 "Storage size does not match the element type size");
843 assert(Info.
Size > 0 &&
"Empty bitfield!");
845 "Bitfield outside of its allocated storage");
853 OS <<
"<CGRecordLayout\n";
854 OS <<
" LLVMType:" << *CompleteObjectType <<
"\n";
855 if (BaseSubobjectType)
856 OS <<
" NonVirtualBaseLLVMType:" << *BaseSubobjectType <<
"\n";
857 OS <<
" IsZeroInitializable:" << IsZeroInitializable <<
"\n";
858 OS <<
" BitFields:[\n";
861 std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
862 for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
863 it = BitFields.begin(), ie = BitFields.end();
870 BFIs.push_back(std::make_pair(Index, &it->second));
872 llvm::array_pod_sort(BFIs.begin(), BFIs.end());
873 for (
unsigned i = 0, e = BFIs.size(); i != e; ++i) {
875 BFIs[i].second->print(OS);
887 OS <<
"<CGBitFieldInfo" 888 <<
" Offset:" << Offset
890 <<
" IsSigned:" << IsSigned
891 <<
" StorageSize:" << StorageSize
892 <<
" 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
bool isZeroLengthBitField(const ASTContext &Ctx) const
Is this a zero-length bit-field? Such bit-fields aren't really bit-fields at all and instead act as a...
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.
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
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...
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
__DEVICE__ int max(int __a, int __b)
__DEVICE__ int min(int __a, int __b)
CGRecordLayout * ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty)
Compute a new LLVM record layout object for the given record.
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.