26#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/DerivedTypes.h"
28#include "llvm/IR/Type.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Support/MathExtras.h"
31#include "llvm/Support/raw_ostream.h"
75struct CGRecordLowering {
81 enum InfoKind { VFPtr, VBPtr, Field, Base, VBase } Kind;
85 const CXXRecordDecl *RD;
87 MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data,
88 const FieldDecl *FD =
nullptr)
89 : Offset(Offset), Kind(Kind), Data(Data), FD(FD) {}
90 MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data,
91 const CXXRecordDecl *RD)
92 : Offset(Offset), Kind(Kind), Data(Data), RD(RD) {}
94 bool operator <(
const MemberInfo& a)
const {
return Offset < a.Offset; }
97 CGRecordLowering(CodeGenTypes &Types,
const RecordDecl *D,
bool Packed);
100 static MemberInfo StorageInfo(CharUnits Offset, llvm::Type *
Data) {
101 return MemberInfo(Offset, MemberInfo::Field,
Data);
105 bool isBE()
const {
return Context.getTargetInfo().isBigEndian(); }
108 llvm::Type *getIntNType(uint64_t NumBits)
const {
109 unsigned AlignedBits = llvm::alignTo(NumBits, Context.getCharWidth());
110 return llvm::Type::getIntNTy(Types.getLLVMContext(), AlignedBits);
113 llvm::Type *getCharType()
const {
114 return llvm::Type::getIntNTy(Types.getLLVMContext(),
115 Context.getCharWidth());
118 llvm::Type *getByteArrayType(CharUnits NumChars)
const {
119 assert(!NumChars.
isZero() &&
"Empty byte arrays aren't allowed.");
120 llvm::Type *
Type = getCharType();
126 llvm::Type *getStorageType(
const FieldDecl *FD)
const {
127 llvm::Type *
Type = Types.ConvertTypeForMem(FD->
getType());
132 (
unsigned)Context.toBits(getSize(
Type))));
135 llvm::Type *getStorageType(
const CXXRecordDecl *RD)
const {
136 return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType();
138 CharUnits bitsToCharUnits(uint64_t BitOffset)
const {
139 return Context.toCharUnitsFromBits(BitOffset);
141 CharUnits getSize(llvm::Type *
Type)
const {
144 CharUnits getAlignment(llvm::Type *
Type)
const {
147 bool isZeroInitializable(
const FieldDecl *FD)
const {
148 return Types.isZeroInitializable(FD->
getType());
150 bool isZeroInitializable(
const RecordDecl *RD)
const {
151 return Types.isZeroInitializable(RD);
153 void appendPaddingBytes(CharUnits Size) {
155 FieldTypes.push_back(getByteArrayType(Size));
157 uint64_t getFieldBitOffset(
const FieldDecl *FD)
const {
161 void setBitFieldInfo(
const FieldDecl *FD, CharUnits StartOffset,
162 llvm::Type *StorageType);
164 void lower(
bool NonVirtualBaseType);
165 void lowerUnion(
bool isNonVirtualBaseType);
166 void accumulateFields(
bool isNonVirtualBaseType);
168 accumulateBitFields(
bool isNonVirtualBaseType,
171 void computeVolatileBitfields();
172 void accumulateBases();
173 void accumulateVPtrs();
174 void accumulateVBases();
175 void calculateZeroInit();
176 CharUnits calculateTailClippingOffset(
bool isNonVirtualBaseType)
const;
177 void checkBitfieldClipping(
bool isNonVirtualBaseType)
const;
179 void determinePacked(
bool NVBaseType);
181 void insertPadding();
183 void fillOutputFields();
186 const ASTContext &Context;
188 const CXXRecordDecl *RD;
189 const ASTRecordLayout &Layout;
190 const llvm::DataLayout &DataLayout;
192 std::vector<MemberInfo> Members;
194 SmallVector<llvm::Type *, 16> FieldTypes;
195 llvm::DenseMap<const FieldDecl *, unsigned> Fields;
196 llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
197 llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
198 llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
199 bool IsZeroInitializable : 1;
200 bool IsZeroInitializableAsBase : 1;
203 CGRecordLowering(
const CGRecordLowering &) =
delete;
204 void operator =(
const CGRecordLowering &) =
delete;
210 : Types(Types), Context(Types.getContext()), D(D),
212 Layout(Types.getContext().getASTRecordLayout(D)),
213 DataLayout(Types.getDataLayout()), IsZeroInitializable(
true),
216void CGRecordLowering::setBitFieldInfo(
218 uint64_t Offset = getFieldBitOffset(FD) - Context.
toBits(StartOffset);
220 DataLayout.getTypeAllocSizeInBits(StorageType).getFixedValue();
225 DataLayout.getTypeAllocSizeInBits(FieldType).getFixedValue()});
230 if (DataLayout.isBigEndian())
231 Offset = StorageSize - (Offset +
Size);
235 StorageSize, StartOffset);
238void CGRecordLowering::lower(
bool NVBaseType) {
261 lowerUnion(NVBaseType);
262 computeVolatileBitfields();
265 accumulateFields(NVBaseType);
270 if (Members.empty()) {
271 appendPaddingBytes(Size);
272 computeVolatileBitfields();
278 llvm::stable_sort(Members);
279 checkBitfieldClipping(NVBaseType);
280 Members.push_back(StorageInfo(Size, getIntNType(8)));
281 determinePacked(NVBaseType);
286 computeVolatileBitfields();
289void CGRecordLowering::lowerUnion(
bool isNonVirtualBaseType) {
290 CharUnits LayoutSize =
292 llvm::Type *StorageType =
nullptr;
293 bool SeenNamedMember =
false;
299 for (
const auto *Field : D->
fields()) {
300 if (
Field->isBitField()) {
301 if (
Field->isZeroLengthBitField())
303 llvm::Type *FieldType = getStorageType(Field);
304 if (LayoutSize < getSize(FieldType))
305 FieldType = getByteArrayType(LayoutSize);
308 Fields[
Field->getCanonicalDecl()] = 0;
309 llvm::Type *FieldType = getStorageType(Field);
316 if (!SeenNamedMember) {
317 SeenNamedMember =
Field->getIdentifier();
318 if (!SeenNamedMember)
319 if (
const auto *FieldRD =
Field->getType()->getAsRecordDecl())
320 SeenNamedMember = FieldRD->findFirstNamedDataMember();
321 if (SeenNamedMember && !isZeroInitializable(Field)) {
322 IsZeroInitializable = IsZeroInitializableAsBase =
false;
323 StorageType = FieldType;
328 if (!IsZeroInitializable)
332 getAlignment(FieldType) > getAlignment(StorageType) ||
333 (getAlignment(FieldType) == getAlignment(StorageType) &&
334 getSize(FieldType) > getSize(StorageType)))
335 StorageType = FieldType;
339 return appendPaddingBytes(LayoutSize);
342 if (LayoutSize < getSize(StorageType))
343 StorageType = getByteArrayType(LayoutSize);
344 FieldTypes.push_back(StorageType);
345 appendPaddingBytes(LayoutSize - getSize(StorageType));
347 const auto StorageAlignment = getAlignment(StorageType);
350 "Union's standard layout and no_unique_address layout must agree on "
356void CGRecordLowering::accumulateFields(
bool isNonVirtualBaseType) {
359 Field != FieldEnd;) {
360 if (
Field->isBitField()) {
361 Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd);
362 assert((Field == FieldEnd || !
Field->isBitField()) &&
363 "Failed to accumulate all the bitfields");
370 Members.push_back(MemberInfo(
371 bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
372 Field->isPotentiallyOverlapping()
373 ? getStorageType(
Field->getType()->getAsCXXRecordDecl())
374 : getStorageType(*Field),
386CGRecordLowering::accumulateBitFields(
bool isNonVirtualBaseType,
402 if (
Field->isZeroLengthBitField()) {
406 uint64_t BitOffset = getFieldBitOffset(*Field);
410 if (Run == FieldEnd || BitOffset >= Tail) {
412 StartBitOffset = BitOffset;
413 Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(
Type);
417 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset),
Type));
421 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
422 MemberInfo::Field,
nullptr, *Field));
495 CharUnits BeginOffset;
504 CharUnits BestEndOffset;
512 bool AtAlignedBoundary =
false;
513 bool Barrier =
false;
515 if (Field != FieldEnd &&
Field->isBitField()) {
516 uint64_t BitOffset = getFieldBitOffset(*Field);
517 if (Begin == FieldEnd) {
522 assert((BitOffset % CharBits) == 0 &&
"Not at start of char");
523 BeginOffset = bitsToCharUnits(BitOffset);
524 BitSizeSinceBegin = 0;
525 }
else if ((BitOffset % CharBits) != 0) {
532 assert(BitOffset == Context.
toBits(BeginOffset) + BitSizeSinceBegin &&
533 "Concatenating non-contiguous bitfields");
538 if (
Field->isZeroLengthBitField())
540 AtAlignedBoundary =
true;
545 if (Begin == FieldEnd)
549 AtAlignedBoundary =
true;
555 bool InstallBest =
false;
556 if (AtAlignedBoundary) {
562 CharUnits AccessSize = bitsToCharUnits(BitSizeSinceBegin + CharBits - 1);
563 if (BestEnd == Begin) {
567 BestEndOffset = BeginOffset + AccessSize;
570 if (!BitSizeSinceBegin)
574 }
else if (AccessSize > RegSize)
582 llvm::Type *
Type = getIntNType(Context.
toBits(AccessSize));
589 CharUnits Align = getAlignment(
Type);
599 if (InstallBest && BestEnd == Field)
602 if (getSize(
Type) == AccessSize)
611 CharUnits LimitOffset;
612 for (
auto Probe = Field; Probe != FieldEnd; ++Probe)
615 assert((getFieldBitOffset(*Probe) % CharBits) == 0 &&
616 "Next storage is not byte-aligned");
617 LimitOffset = bitsToCharUnits(getFieldBitOffset(*Probe));
622 if (ScissorOffset.
isZero()) {
623 ScissorOffset = calculateTailClippingOffset(isNonVirtualBaseType);
624 assert(!ScissorOffset.
isZero() &&
"Tail clipping at zero");
627 LimitOffset = ScissorOffset;
630 CharUnits TypeSize = getSize(
Type);
631 if (BeginOffset + TypeSize <= LimitOffset) {
634 BestEndOffset = BeginOffset + TypeSize;
649 BitSizeSinceBegin = Context.
toBits(LimitOffset - BeginOffset);
655 assert((Field == FieldEnd || !
Field->isBitField() ||
656 (getFieldBitOffset(*Field) % CharBits) == 0) &&
657 "Installing but not at an aligned bitfield or limit");
658 CharUnits AccessSize = BestEndOffset - BeginOffset;
659 if (!AccessSize.
isZero()) {
665 assert(getSize(getIntNType(Context.
toBits(AccessSize))) >
667 "Clipped access need not be clipped");
668 Type = getByteArrayType(AccessSize);
670 Type = getIntNType(Context.
toBits(AccessSize));
671 assert(getSize(
Type) == AccessSize &&
672 "Unclipped access must be clipped");
674 Members.push_back(StorageInfo(BeginOffset,
Type));
675 for (; Begin != BestEnd; ++Begin)
676 if (!Begin->isZeroLengthBitField())
678 MemberInfo(BeginOffset, MemberInfo::Field,
nullptr, *Begin));
684 assert(Field != FieldEnd &&
Field->isBitField() &&
685 "Accumulating past end of bitfields");
686 assert(!Barrier &&
"Accumulating across barrier");
688 BitSizeSinceBegin +=
Field->getBitWidthValue();
696void CGRecordLowering::accumulateBases() {
701 getStorageType(BaseDecl), BaseDecl));
704 for (
const auto &Base : RD->bases()) {
705 if (
Base.isVirtual())
710 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
714 MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
731void CGRecordLowering::computeVolatileBitfields() {
736 for (
auto &I : BitFields) {
737 const FieldDecl *
Field = I.first;
738 CGBitFieldInfo &Info = I.second;
743 ResLTy->getPrimitiveSizeInBits())
750 const unsigned OldOffset =
753 const unsigned AbsoluteOffset =
757 const unsigned StorageSize = ResLTy->getPrimitiveSizeInBits();
760 if (Info.
StorageSize == StorageSize && (OldOffset % StorageSize == 0))
764 unsigned Offset = AbsoluteOffset & (StorageSize - 1);
769 if (Offset + Info.
Size > StorageSize)
774 Offset = StorageSize - (Offset + Info.
Size);
776 const CharUnits StorageOffset =
778 const CharUnits End = StorageOffset +
782 const ASTRecordLayout &Layout =
785 const CharUnits RecordSize = Layout.
getSize();
786 if (End >= RecordSize)
790 bool Conflict =
false;
791 for (
const auto *F : D->
fields()) {
793 if (F->isBitField() && !F->isZeroLengthBitField())
803 if (F->isZeroLengthBitField()) {
804 if (End > FOffset && StorageOffset < FOffset) {
810 const CharUnits FEnd =
816 if (End < FOffset || FEnd < StorageOffset)
836void CGRecordLowering::accumulateVPtrs() {
839 Members.push_back(MemberInfo(
CharUnits::Zero(), MemberInfo::VFPtr, VPtrTy));
846CGRecordLowering::calculateTailClippingOffset(
bool isNonVirtualBaseType)
const {
856 for (
const auto &Base : RD->vbases()) {
857 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
865 ScissorOffset = std::min(ScissorOffset,
869 return ScissorOffset;
872void CGRecordLowering::accumulateVBases() {
873 for (
const auto &Base : RD->vbases()) {
874 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
883 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
nullptr,
891 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
892 getStorageType(BaseDecl), BaseDecl));
896void CGRecordLowering::calculateZeroInit() {
897 for (std::vector<MemberInfo>::const_iterator
Member = Members.begin(),
898 MemberEnd = Members.end();
899 IsZeroInitializableAsBase &&
Member != MemberEnd; ++
Member) {
900 if (
Member->Kind == MemberInfo::Field) {
903 IsZeroInitializable = IsZeroInitializableAsBase =
false;
904 }
else if (
Member->Kind == MemberInfo::Base ||
905 Member->Kind == MemberInfo::VBase) {
906 if (isZeroInitializable(
Member->RD))
908 IsZeroInitializable =
false;
909 if (
Member->Kind == MemberInfo::Base)
910 IsZeroInitializableAsBase =
false;
916void CGRecordLowering::checkBitfieldClipping(
bool IsNonVirtualBaseType)
const {
918 auto ScissorOffset = calculateTailClippingOffset(IsNonVirtualBaseType);
920 for (
const auto &M : Members) {
925 assert(M.Offset >= Tail &&
"Bitfield access unit is not clipped");
926 Tail = M.Offset + getSize(M.Data);
927 assert((Tail <= ScissorOffset || M.Offset >= ScissorOffset) &&
928 "Bitfield straddles scissor offset");
933void CGRecordLowering::determinePacked(
bool NVBaseType) {
940 for (
const MemberInfo &
Member : Members) {
945 if (!
Member.Offset.isMultipleOf(getAlignment(
Member.Data)))
947 if (
Member.Offset < NVSize)
948 NVAlignment = std::max(NVAlignment, getAlignment(
Member.Data));
949 Alignment = std::max(Alignment, getAlignment(
Member.Data));
953 if (!Members.back().Offset.isMultipleOf(Alignment))
962 Members.back().Data = getIntNType(Context.
toBits(Alignment));
965void CGRecordLowering::insertPadding() {
966 std::vector<std::pair<CharUnits, CharUnits> > Padding;
968 for (
const MemberInfo &
Member : Members) {
971 CharUnits Offset =
Member.Offset;
972 assert(Offset >= Size);
976 Padding.push_back(std::make_pair(Size, Offset - Size));
982 for (
const auto &Pad : Padding)
983 Members.push_back(StorageInfo(Pad.first, getByteArrayType(Pad.second)));
984 llvm::stable_sort(Members);
987void CGRecordLowering::fillOutputFields() {
988 for (
const MemberInfo &
Member : Members) {
990 FieldTypes.push_back(
Member.Data);
991 if (
Member.Kind == MemberInfo::Field) {
993 Fields[
Member.FD->getCanonicalDecl()] = FieldTypes.size() - 1;
997 "Member.Data is a nullptr so Member.FD should not be");
998 setBitFieldInfo(
Member.FD,
Member.Offset, FieldTypes.back());
1000 }
else if (
Member.Kind == MemberInfo::Base)
1001 NonVirtualBases[
Member.RD] = FieldTypes.size() - 1;
1002 else if (
Member.Kind == MemberInfo::VBase)
1003 VirtualBases[
Member.RD] = FieldTypes.size() - 1;
1022 if (
Size > TypeSizeInBits) {
1032 Size = TypeSizeInBits;
1046std::unique_ptr<CGRecordLayout>
1048 CGRecordLowering Builder(*
this, D,
false);
1050 Builder.lower(
false);
1053 llvm::StructType *BaseTy =
nullptr;
1056 if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
1057 CGRecordLowering BaseBuilder(*
this, D, Builder.Packed);
1058 BaseBuilder.lower(
true);
1059 BaseTy = llvm::StructType::create(
1060 getLLVMContext(), BaseBuilder.FieldTypes,
"", BaseBuilder.Packed);
1064 assert(Builder.Packed == BaseBuilder.Packed &&
1065 "Non-virtual and complete types must agree on packedness");
1072 Ty->setBody(Builder.FieldTypes, Builder.Packed);
1074 auto RL = std::make_unique<CGRecordLayout>(
1075 Ty, BaseTy, (
bool)Builder.IsZeroInitializable,
1076 (
bool)Builder.IsZeroInitializableAsBase);
1078 RL->NonVirtualBases.swap(Builder.NonVirtualBases);
1079 RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
1082 RL->FieldInfo.swap(Builder.Fields);
1085 RL->BitFields.swap(Builder.BitFields);
1088 if (
getContext().getLangOpts().DumpRecordLayouts) {
1089 llvm::outs() <<
"\n*** Dumping IRgen Record Layout\n";
1090 llvm::outs() <<
"Record: ";
1091 D->
dump(llvm::outs());
1092 llvm::outs() <<
"\nLayout: ";
1093 RL->print(llvm::outs());
1101 assert(TypeSizeInBits ==
getDataLayout().getTypeAllocSizeInBits(Ty) &&
1102 "Type size mismatch!");
1107 uint64_t AlignedNonVirtualTypeSizeInBits =
1110 assert(AlignedNonVirtualTypeSizeInBits ==
1112 "Type size mismatch!");
1116 llvm::StructType *ST = RL->getLLVMType();
1117 const llvm::StructLayout *SL =
getDataLayout().getStructLayout(ST);
1121 for (
unsigned i = 0, e = AST_RL.
getFieldCount(); i != e; ++i, ++it) {
1131 unsigned FieldNo = RL->getLLVMFieldNo(FD);
1132 assert(AST_RL.
getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
1133 "Invalid field offset!");
1142 llvm::Type *ElementTy = ST->getTypeAtIndex(RL->getLLVMFieldNo(FD));
1153 assert(
static_cast<unsigned>(Info.
Offset + Info.
Size) ==
1155 "Big endian union bitfield does not end at the back");
1157 assert(Info.
Offset == 0 &&
1158 "Little endian union bitfield with a non-zero offset");
1160 "Union not large enough for bitfield storage");
1166 "Storage size does not match the element type size");
1168 assert(Info.
Size > 0 &&
"Empty bitfield!");
1170 "Bitfield outside of its allocated storage");
1178 OS <<
"<CGRecordLayout\n";
1179 OS <<
" LLVMType:" << *CompleteObjectType <<
"\n";
1180 if (BaseSubobjectType)
1181 OS <<
" NonVirtualBaseLLVMType:" << *BaseSubobjectType <<
"\n";
1182 OS <<
" IsZeroInitializable:" << IsZeroInitializable <<
"\n";
1183 OS <<
" BitFields:[\n";
1186 std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
1187 for (
const auto &BitField : BitFields) {
1191 *it2 != BitField.first; ++it2)
1193 BFIs.push_back(std::make_pair(Index, &BitField.second));
1195 llvm::array_pod_sort(BFIs.begin(), BFIs.end());
1196 for (
auto &BFI : BFIs) {
1198 BFI.second->print(OS);
1206 print(llvm::errs());
1210 OS <<
"<CGBitFieldInfo"
1220 print(llvm::errs());
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static void print(llvm::raw_ostream &OS, const T &V, const Context &Ctx, QualType Ty)
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
bool isNearlyEmpty(const CXXRecordDecl *RD) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding,...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents a C++ struct/union/class.
This is an opaque type for sizes expressed in character units.
bool isZero() const
Test whether the quantity equals zero.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits One()
Construct a CharUnits quantity of one.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Construct a CharUnits quantity of zero.
void print(raw_ostream &OS) const
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
const CodeGenOptions & getCodeGenOpts() const
ASTContext & getContext() const
std::unique_ptr< CGRecordLayout > ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty)
Compute a new LLVM record layout object for the given record.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
CodeGenModule & getCGM() const
llvm::LLVMContext & getLLVMContext()
const llvm::DataLayout & getDataLayout() const
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...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
virtual unsigned getRegisterWidth() const
Return the "preferred" register width on this target.
bool hasCheapUnalignedBitFieldAccess() const
Return true iff unaligned accesses are cheap.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isAAPCS(const TargetInfo &TargetInfo)
Helper method to check if the underlying ABI is AAPCS.
bool isDiscreteBitFieldABI(const ASTContext &Ctx, const RecordDecl *RD)
The Microsoft bitfield layout rule allocates discrete storage units of the field's formal type and on...
bool hasOwnStorage(const ASTContext &Ctx, const CXXRecordDecl *Decl, const CXXRecordDecl *Query)
Recursively searches all of the bases of Decl to find out whether Query is not the primary vbase of s...
bool isOverlappingVBaseABI(const ASTContext &Ctx)
The Itanium base layout rule allows virtual bases to overlap other bases, which complicates layout in...
bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD)
Return true iff the field is "empty", that is, either a zero-width bit-field or an isEmptyRecordForLa...
bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T)
Return true iff a structure contains only empty base classes (per isEmptyRecordForLayout) and fields ...
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Structure with information about how a bitfield should be accessed.
CharUnits StorageOffset
The offset of the bitfield storage from the start of the struct.
CharUnits VolatileStorageOffset
The offset of the bitfield storage from the start of the struct.
unsigned VolatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the L...
unsigned Offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the L...
unsigned VolatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
void print(raw_ostream &OS) const
unsigned Size
The total size of the bit-field, in bits, not including padding.
unsigned StorageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned IsSigned
Whether the bit-field is signed.
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...
llvm::PointerType * GlobalsInt8PtrTy