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;
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 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()) {
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();
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));
412 if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
414 unsigned Width = Field->getBitWidthValue(Context);
415 if (!DataLayout.isLegalInteger(Width))
418 if (getFieldBitOffset(*Field) %
419 Context.
toBits(getAlignment(getIntNType(Width))) !=
426 bool StartFieldAsSingleRun =
false;
429 if (Run == FieldEnd) {
431 if (Field == FieldEnd)
434 if (Field->getBitWidthValue(Context) != 0) {
436 StartBitOffset = getFieldBitOffset(*Field);
437 Tail = StartBitOffset + Field->getBitWidthValue(Context);
438 StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Run);
451 if (!StartFieldAsSingleRun && Field != FieldEnd &&
452 !IsBetterAsSingleFieldRun(Field) &&
453 Field->getBitWidthValue(Context) != 0 &&
454 Tail == getFieldBitOffset(*Field)) {
455 Tail += Field->getBitWidthValue(Context);
461 llvm::Type *Type = getIntNType(Tail - StartBitOffset);
465 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
466 for (; Run != Field; ++Run)
467 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
468 MemberInfo::Field,
nullptr, *Run));
470 StartFieldAsSingleRun =
false;
474 void CGRecordLowering::accumulateBases() {
476 if (Layout.isPrimaryBaseVirtual()) {
479 getStorageType(BaseDecl), BaseDecl));
482 for (
const auto &
Base : RD->bases()) {
483 if (
Base.isVirtual())
491 Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
496 void CGRecordLowering::accumulateVPtrs() {
497 if (Layout.hasOwnVFPtr())
499 llvm::FunctionType::get(getIntNType(32),
true)->
500 getPointerTo()->getPointerTo()));
501 if (Layout.hasOwnVBPtr())
502 Members.push_back(MemberInfo(Layout.getVBPtrOffset(), MemberInfo::VBPtr,
503 llvm::Type::getInt32PtrTy(Types.getLLVMContext())));
506 void CGRecordLowering::accumulateVBases() {
507 CharUnits ScissorOffset = Layout.getNonVirtualSize();
512 if (isOverlappingVBaseABI())
513 for (
const auto &
Base : RD->vbases()) {
519 if (Context.
isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl))
521 ScissorOffset =
std::min(ScissorOffset,
522 Layout.getVBaseClassOffset(BaseDecl));
524 Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor,
nullptr,
526 for (
const auto &
Base : RD->vbases()) {
533 if (isOverlappingVBaseABI() &&
535 !hasOwnStorage(RD, BaseDecl)) {
536 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
nullptr,
541 if (Layout.getVBaseOffsetsMap().find(BaseDecl)->second.hasVtorDisp())
544 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
545 getStorageType(BaseDecl), BaseDecl));
555 if (!hasOwnStorage(
Base.getType()->getAsCXXRecordDecl(), Query))
560 void CGRecordLowering::calculateZeroInit() {
561 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
562 MemberEnd = Members.end();
563 IsZeroInitializableAsBase && Member != MemberEnd; ++Member) {
564 if (Member->Kind == MemberInfo::Field) {
567 IsZeroInitializable = IsZeroInitializableAsBase =
false;
569 Member->Kind == MemberInfo::VBase) {
572 IsZeroInitializable =
false;
574 IsZeroInitializableAsBase =
false;
579 void CGRecordLowering::clipTailPadding() {
580 std::vector<MemberInfo>::iterator Prior = Members.begin();
582 for (std::vector<MemberInfo>::iterator Member = Prior + 1,
583 MemberEnd = Members.end();
584 Member != MemberEnd; ++Member) {
586 if (!Member->Data && Member->Kind != MemberInfo::Scissor)
588 if (Member->Offset < Tail) {
589 assert(Prior->Kind == MemberInfo::Field && !Prior->FD &&
590 "Only storage fields have tail padding!");
591 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
592 cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));
596 Tail = Prior->Offset + getSize(Prior->Data);
600 void CGRecordLowering::determinePacked(
bool NVBaseType) {
607 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
608 MemberEnd = Members.end();
609 Member != MemberEnd; ++Member) {
614 if (Member->Offset % getAlignment(Member->Data))
616 if (Member->Offset < NVSize)
617 NVAlignment =
std::max(NVAlignment, getAlignment(Member->Data));
618 Alignment =
std::max(Alignment, getAlignment(Member->Data));
622 if (Members.back().Offset % Alignment)
627 if (NVSize % NVAlignment)
631 Members.back().Data = getIntNType(Context.
toBits(Alignment));
634 void CGRecordLowering::insertPadding() {
635 std::vector<std::pair<CharUnits, CharUnits> > Padding;
637 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
638 MemberEnd = Members.end();
639 Member != MemberEnd; ++Member) {
643 assert(Offset >= Size);
647 Padding.push_back(std::make_pair(Size, Offset - Size));
648 Size = Offset + getSize(Member->Data);
653 for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator
654 Pad = Padding.begin(), PadEnd = Padding.end();
655 Pad != PadEnd; ++Pad)
656 Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second)));
657 std::stable_sort(Members.begin(), Members.end());
660 void CGRecordLowering::fillOutputFields() {
661 for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
662 MemberEnd = Members.end();
663 Member != MemberEnd; ++Member) {
665 FieldTypes.push_back(Member->Data);
666 if (Member->Kind == MemberInfo::Field) {
668 Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1;
671 setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back());
673 NonVirtualBases[Member->RD] = FieldTypes.size() - 1;
674 else if (Member->Kind == MemberInfo::VBase)
675 VirtualBases[Member->RD] = FieldTypes.size() - 1;
681 uint64_t Offset, uint64_t Size,
682 uint64_t StorageSize,
694 if (Size > TypeSizeInBits) {
704 Size = TypeSizeInBits;
712 Offset = StorageSize - (Offset + Size);
715 return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
719 llvm::StructType *Ty) {
720 CGRecordLowering Builder(*
this, D,
false);
722 Builder.lower(
false);
725 llvm::StructType *BaseTy =
nullptr;
726 if (isa<CXXRecordDecl>(D) && !D->
isUnion() && !D->
hasAttr<FinalAttr>()) {
728 if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
729 CGRecordLowering BaseBuilder(*
this, D, Builder.Packed);
730 BaseBuilder.lower(
true);
732 getLLVMContext(), BaseBuilder.FieldTypes,
"", BaseBuilder.Packed);
733 addRecordTypeName(D, BaseTy,
".base");
736 assert(Builder.Packed == BaseBuilder.Packed &&
737 "Non-virtual and complete types must agree on packedness");
744 Ty->setBody(Builder.FieldTypes, Builder.Packed);
748 Builder.IsZeroInitializableAsBase);
750 RL->NonVirtualBases.swap(Builder.NonVirtualBases);
751 RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
754 RL->FieldInfo.swap(Builder.Fields);
757 RL->BitFields.swap(Builder.BitFields);
760 if (getContext().getLangOpts().DumpRecordLayouts) {
761 llvm::outs() <<
"\n*** Dumping IRgen Record Layout\n";
762 llvm::outs() <<
"Record: ";
763 D->
dump(llvm::outs());
764 llvm::outs() <<
"\nLayout: ";
765 RL->
print(llvm::outs());
772 uint64_t TypeSizeInBits = getContext().toBits(Layout.
getSize());
773 assert(TypeSizeInBits == getDataLayout().getTypeAllocSizeInBits(Ty) &&
774 "Type size mismatch!");
779 uint64_t AlignedNonVirtualTypeSizeInBits =
780 getContext().toBits(NonVirtualSize);
782 assert(AlignedNonVirtualTypeSizeInBits ==
783 getDataLayout().getTypeAllocSizeInBits(BaseTy) &&
784 "Type size mismatch!");
788 llvm::StructType *ST =
790 const llvm::StructLayout *SL = getDataLayout().getStructLayout(ST);
794 for (
unsigned i = 0, e = AST_RL.
getFieldCount(); i != e; ++i, ++it) {
801 assert(AST_RL.
getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
802 "Invalid field offset!");
825 if (getDataLayout().isBigEndian())
826 assert(static_cast<unsigned>(Info.
Offset + Info.
Size) ==
828 "Big endian union bitfield does not end at the back");
830 assert(Info.
Offset == 0 &&
831 "Little endian union bitfield with a non-zero offset");
833 "Union not large enough for bitfield storage");
836 getDataLayout().getTypeAllocSizeInBits(ElementTy) &&
837 "Storage size does not match the element type size");
839 assert(Info.
Size > 0 &&
"Empty bitfield!");
841 "Bitfield outside of its allocated storage");
849 OS <<
"<CGRecordLayout\n";
850 OS <<
" LLVMType:" << *CompleteObjectType <<
"\n";
851 if (BaseSubobjectType)
852 OS <<
" NonVirtualBaseLLVMType:" << *BaseSubobjectType <<
"\n";
853 OS <<
" IsZeroInitializable:" << IsZeroInitializable <<
"\n";
854 OS <<
" BitFields:[\n";
857 std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
858 for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
859 it = BitFields.begin(), ie = BitFields.end();
866 BFIs.push_back(std::make_pair(Index, &it->second));
868 llvm::array_pod_sort(BFIs.begin(), BFIs.end());
869 for (
unsigned i = 0, e = BFIs.size(); i != e; ++i) {
871 BFIs[i].second->print(OS);
883 OS <<
"<CGBitFieldInfo" 884 <<
" Offset:" << Offset
886 <<
" IsSigned:" << IsSigned
887 <<
" StorageSize:" << StorageSize
888 <<
" 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
getFieldIndex - Returns the index of this field within its record, as appropriate for passing to ASTR...
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.
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]).
DeclarationName getDeclName() const
getDeclName - 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 ...
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.
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 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.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
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.
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.
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
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?
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.