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(
220 Info.
Offset = (unsigned)(getFieldBitOffset(FD) - Context.
toBits(StartOffset));
222 Info.
StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
228 unsigned FieldTypeSize = DataLayout.getTypeAllocSizeInBits(FieldType);
229 if (Info.
Size > FieldTypeSize)
230 Info.
Size = FieldTypeSize;
235 if (DataLayout.isBigEndian())
243void CGRecordLowering::lower(
bool NVBaseType) {
266 lowerUnion(NVBaseType);
267 computeVolatileBitfields();
270 accumulateFields(NVBaseType);
275 if (Members.empty()) {
276 appendPaddingBytes(Size);
277 computeVolatileBitfields();
283 llvm::stable_sort(Members);
284 checkBitfieldClipping(NVBaseType);
285 Members.push_back(StorageInfo(Size, getIntNType(8)));
286 determinePacked(NVBaseType);
291 computeVolatileBitfields();
294void CGRecordLowering::lowerUnion(
bool isNonVirtualBaseType) {
295 CharUnits LayoutSize =
297 llvm::Type *StorageType =
nullptr;
298 bool SeenNamedMember =
false;
304 for (
const auto *Field : D->
fields()) {
305 if (
Field->isBitField()) {
306 if (
Field->isZeroLengthBitField())
308 llvm::Type *FieldType = getStorageType(Field);
309 if (LayoutSize < getSize(FieldType))
310 FieldType = getByteArrayType(LayoutSize);
313 Fields[
Field->getCanonicalDecl()] = 0;
314 llvm::Type *FieldType = getStorageType(Field);
321 if (!SeenNamedMember) {
322 SeenNamedMember =
Field->getIdentifier();
323 if (!SeenNamedMember)
324 if (
const auto *FieldRD =
Field->getType()->getAsRecordDecl())
325 SeenNamedMember = FieldRD->findFirstNamedDataMember();
326 if (SeenNamedMember && !isZeroInitializable(Field)) {
327 IsZeroInitializable = IsZeroInitializableAsBase =
false;
328 StorageType = FieldType;
333 if (!IsZeroInitializable)
337 getAlignment(FieldType) > getAlignment(StorageType) ||
338 (getAlignment(FieldType) == getAlignment(StorageType) &&
339 getSize(FieldType) > getSize(StorageType)))
340 StorageType = FieldType;
344 return appendPaddingBytes(LayoutSize);
347 if (LayoutSize < getSize(StorageType))
348 StorageType = getByteArrayType(LayoutSize);
349 FieldTypes.push_back(StorageType);
350 appendPaddingBytes(LayoutSize - getSize(StorageType));
352 const auto StorageAlignment = getAlignment(StorageType);
355 "Union's standard layout and no_unique_address layout must agree on "
361void CGRecordLowering::accumulateFields(
bool isNonVirtualBaseType) {
364 Field != FieldEnd;) {
365 if (
Field->isBitField()) {
366 Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd);
367 assert((Field == FieldEnd || !
Field->isBitField()) &&
368 "Failed to accumulate all the bitfields");
375 Members.push_back(MemberInfo(
376 bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
377 Field->isPotentiallyOverlapping()
378 ? getStorageType(
Field->getType()->getAsCXXRecordDecl())
379 : getStorageType(*Field),
391CGRecordLowering::accumulateBitFields(
bool isNonVirtualBaseType,
407 if (
Field->isZeroLengthBitField()) {
411 uint64_t BitOffset = getFieldBitOffset(*Field);
415 if (Run == FieldEnd || BitOffset >= Tail) {
417 StartBitOffset = BitOffset;
418 Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(
Type);
422 Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset),
Type));
426 Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
427 MemberInfo::Field,
nullptr, *Field));
500 CharUnits BeginOffset;
509 CharUnits BestEndOffset;
517 bool AtAlignedBoundary =
false;
518 bool Barrier =
false;
520 if (Field != FieldEnd &&
Field->isBitField()) {
521 uint64_t BitOffset = getFieldBitOffset(*Field);
522 if (Begin == FieldEnd) {
527 assert((BitOffset % CharBits) == 0 &&
"Not at start of char");
528 BeginOffset = bitsToCharUnits(BitOffset);
529 BitSizeSinceBegin = 0;
530 }
else if ((BitOffset % CharBits) != 0) {
537 assert(BitOffset == Context.
toBits(BeginOffset) + BitSizeSinceBegin &&
538 "Concatenating non-contiguous bitfields");
543 if (
Field->isZeroLengthBitField())
545 AtAlignedBoundary =
true;
550 if (Begin == FieldEnd)
554 AtAlignedBoundary =
true;
560 bool InstallBest =
false;
561 if (AtAlignedBoundary) {
567 CharUnits AccessSize = bitsToCharUnits(BitSizeSinceBegin + CharBits - 1);
568 if (BestEnd == Begin) {
572 BestEndOffset = BeginOffset + AccessSize;
575 if (!BitSizeSinceBegin)
579 }
else if (AccessSize > RegSize)
587 llvm::Type *
Type = getIntNType(Context.
toBits(AccessSize));
594 CharUnits Align = getAlignment(
Type);
604 if (InstallBest && BestEnd == Field)
607 if (getSize(
Type) == AccessSize)
616 CharUnits LimitOffset;
617 for (
auto Probe = Field; Probe != FieldEnd; ++Probe)
620 assert((getFieldBitOffset(*Probe) % CharBits) == 0 &&
621 "Next storage is not byte-aligned");
622 LimitOffset = bitsToCharUnits(getFieldBitOffset(*Probe));
627 if (ScissorOffset.
isZero()) {
628 ScissorOffset = calculateTailClippingOffset(isNonVirtualBaseType);
629 assert(!ScissorOffset.
isZero() &&
"Tail clipping at zero");
632 LimitOffset = ScissorOffset;
635 CharUnits TypeSize = getSize(
Type);
636 if (BeginOffset + TypeSize <= LimitOffset) {
639 BestEndOffset = BeginOffset + TypeSize;
654 BitSizeSinceBegin = Context.
toBits(LimitOffset - BeginOffset);
660 assert((Field == FieldEnd || !
Field->isBitField() ||
661 (getFieldBitOffset(*Field) % CharBits) == 0) &&
662 "Installing but not at an aligned bitfield or limit");
663 CharUnits AccessSize = BestEndOffset - BeginOffset;
664 if (!AccessSize.
isZero()) {
670 assert(getSize(getIntNType(Context.
toBits(AccessSize))) >
672 "Clipped access need not be clipped");
673 Type = getByteArrayType(AccessSize);
675 Type = getIntNType(Context.
toBits(AccessSize));
676 assert(getSize(
Type) == AccessSize &&
677 "Unclipped access must be clipped");
679 Members.push_back(StorageInfo(BeginOffset,
Type));
680 for (; Begin != BestEnd; ++Begin)
681 if (!Begin->isZeroLengthBitField())
683 MemberInfo(BeginOffset, MemberInfo::Field,
nullptr, *Begin));
689 assert(Field != FieldEnd &&
Field->isBitField() &&
690 "Accumulating past end of bitfields");
691 assert(!Barrier &&
"Accumulating across barrier");
693 BitSizeSinceBegin +=
Field->getBitWidthValue();
701void CGRecordLowering::accumulateBases() {
706 getStorageType(BaseDecl), BaseDecl));
709 for (
const auto &Base : RD->bases()) {
710 if (
Base.isVirtual())
715 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
719 MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
736void CGRecordLowering::computeVolatileBitfields() {
741 for (
auto &I : BitFields) {
742 const FieldDecl *
Field = I.first;
743 CGBitFieldInfo &Info = I.second;
748 ResLTy->getPrimitiveSizeInBits())
755 const unsigned OldOffset =
758 const unsigned AbsoluteOffset =
762 const unsigned StorageSize = ResLTy->getPrimitiveSizeInBits();
765 if (Info.
StorageSize == StorageSize && (OldOffset % StorageSize == 0))
769 unsigned Offset = AbsoluteOffset & (StorageSize - 1);
774 if (Offset + Info.
Size > StorageSize)
779 Offset = StorageSize - (Offset + Info.
Size);
781 const CharUnits StorageOffset =
783 const CharUnits End = StorageOffset +
787 const ASTRecordLayout &Layout =
790 const CharUnits RecordSize = Layout.
getSize();
791 if (End >= RecordSize)
795 bool Conflict =
false;
796 for (
const auto *F : D->
fields()) {
798 if (F->isBitField() && !F->isZeroLengthBitField())
808 if (F->isZeroLengthBitField()) {
809 if (End > FOffset && StorageOffset < FOffset) {
815 const CharUnits FEnd =
821 if (End < FOffset || FEnd < StorageOffset)
841void CGRecordLowering::accumulateVPtrs() {
853CGRecordLowering::calculateTailClippingOffset(
bool isNonVirtualBaseType)
const {
863 for (
const auto &Base : RD->vbases()) {
864 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
872 ScissorOffset = std::min(ScissorOffset,
876 return ScissorOffset;
879void CGRecordLowering::accumulateVBases() {
880 for (
const auto &Base : RD->vbases()) {
881 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
890 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
nullptr,
898 Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
899 getStorageType(BaseDecl), BaseDecl));
903void CGRecordLowering::calculateZeroInit() {
904 for (std::vector<MemberInfo>::const_iterator
Member = Members.begin(),
905 MemberEnd = Members.end();
906 IsZeroInitializableAsBase &&
Member != MemberEnd; ++
Member) {
907 if (
Member->Kind == MemberInfo::Field) {
910 IsZeroInitializable = IsZeroInitializableAsBase =
false;
911 }
else if (
Member->Kind == MemberInfo::Base ||
912 Member->Kind == MemberInfo::VBase) {
913 if (isZeroInitializable(
Member->RD))
915 IsZeroInitializable =
false;
916 if (
Member->Kind == MemberInfo::Base)
917 IsZeroInitializableAsBase =
false;
923void CGRecordLowering::checkBitfieldClipping(
bool IsNonVirtualBaseType)
const {
925 auto ScissorOffset = calculateTailClippingOffset(IsNonVirtualBaseType);
927 for (
const auto &M : Members) {
932 assert(M.Offset >= Tail &&
"Bitfield access unit is not clipped");
933 Tail = M.Offset + getSize(M.Data);
934 assert((Tail <= ScissorOffset || M.Offset >= ScissorOffset) &&
935 "Bitfield straddles scissor offset");
940void CGRecordLowering::determinePacked(
bool NVBaseType) {
947 for (
const MemberInfo &
Member : Members) {
952 if (!
Member.Offset.isMultipleOf(getAlignment(
Member.Data)))
954 if (
Member.Offset < NVSize)
955 NVAlignment = std::max(NVAlignment, getAlignment(
Member.Data));
956 Alignment = std::max(Alignment, getAlignment(
Member.Data));
960 if (!Members.back().Offset.isMultipleOf(Alignment))
969 Members.back().Data = getIntNType(Context.
toBits(Alignment));
972void CGRecordLowering::insertPadding() {
973 std::vector<std::pair<CharUnits, CharUnits> > Padding;
975 for (
const MemberInfo &
Member : Members) {
978 CharUnits Offset =
Member.Offset;
979 assert(Offset >= Size);
983 Padding.push_back(std::make_pair(Size, Offset - Size));
989 for (
const auto &Pad : Padding)
990 Members.push_back(StorageInfo(Pad.first, getByteArrayType(Pad.second)));
991 llvm::stable_sort(Members);
994void CGRecordLowering::fillOutputFields() {
995 for (
const MemberInfo &
Member : Members) {
997 FieldTypes.push_back(
Member.Data);
998 if (
Member.Kind == MemberInfo::Field) {
1000 Fields[
Member.FD->getCanonicalDecl()] = FieldTypes.size() - 1;
1004 "Member.Data is a nullptr so Member.FD should not be");
1005 setBitFieldInfo(
Member.FD,
Member.Offset, FieldTypes.back());
1007 }
else if (
Member.Kind == MemberInfo::Base)
1008 NonVirtualBases[
Member.RD] = FieldTypes.size() - 1;
1009 else if (
Member.Kind == MemberInfo::VBase)
1010 VirtualBases[
Member.RD] = FieldTypes.size() - 1;
1029 if (
Size > TypeSizeInBits) {
1039 Size = TypeSizeInBits;
1053std::unique_ptr<CGRecordLayout>
1055 CGRecordLowering Builder(*
this, D,
false);
1057 Builder.lower(
false);
1060 llvm::StructType *BaseTy =
nullptr;
1063 if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
1064 CGRecordLowering BaseBuilder(*
this, D, Builder.Packed);
1065 BaseBuilder.lower(
true);
1066 BaseTy = llvm::StructType::create(
1067 getLLVMContext(), BaseBuilder.FieldTypes,
"", BaseBuilder.Packed);
1071 assert(Builder.Packed == BaseBuilder.Packed &&
1072 "Non-virtual and complete types must agree on packedness");
1079 Ty->setBody(Builder.FieldTypes, Builder.Packed);
1081 auto RL = std::make_unique<CGRecordLayout>(
1082 Ty, BaseTy, (
bool)Builder.IsZeroInitializable,
1083 (
bool)Builder.IsZeroInitializableAsBase);
1085 RL->NonVirtualBases.swap(Builder.NonVirtualBases);
1086 RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
1089 RL->FieldInfo.swap(Builder.Fields);
1092 RL->BitFields.swap(Builder.BitFields);
1095 if (
getContext().getLangOpts().DumpRecordLayouts) {
1096 llvm::outs() <<
"\n*** Dumping IRgen Record Layout\n";
1097 llvm::outs() <<
"Record: ";
1098 D->
dump(llvm::outs());
1099 llvm::outs() <<
"\nLayout: ";
1100 RL->print(llvm::outs());
1108 assert(TypeSizeInBits ==
getDataLayout().getTypeAllocSizeInBits(Ty) &&
1109 "Type size mismatch!");
1114 uint64_t AlignedNonVirtualTypeSizeInBits =
1117 assert(AlignedNonVirtualTypeSizeInBits ==
1119 "Type size mismatch!");
1123 llvm::StructType *ST = RL->getLLVMType();
1124 const llvm::StructLayout *SL =
getDataLayout().getStructLayout(ST);
1128 for (
unsigned i = 0, e = AST_RL.
getFieldCount(); i != e; ++i, ++it) {
1138 unsigned FieldNo = RL->getLLVMFieldNo(FD);
1139 assert(AST_RL.
getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
1140 "Invalid field offset!");
1149 llvm::Type *ElementTy = ST->getTypeAtIndex(RL->getLLVMFieldNo(FD));
1160 assert(
static_cast<unsigned>(Info.
Offset + Info.
Size) ==
1162 "Big endian union bitfield does not end at the back");
1164 assert(Info.
Offset == 0 &&
1165 "Little endian union bitfield with a non-zero offset");
1167 "Union not large enough for bitfield storage");
1173 "Storage size does not match the element type size");
1175 assert(Info.
Size > 0 &&
"Empty bitfield!");
1177 "Bitfield outside of its allocated storage");
1185 OS <<
"<CGRecordLayout\n";
1186 OS <<
" LLVMType:" << *CompleteObjectType <<
"\n";
1187 if (BaseSubobjectType)
1188 OS <<
" NonVirtualBaseLLVMType:" << *BaseSubobjectType <<
"\n";
1189 OS <<
" IsZeroInitializable:" << IsZeroInitializable <<
"\n";
1190 OS <<
" BitFields:[\n";
1193 std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
1194 for (
const auto &BitField : BitFields) {
1198 *it2 != BitField.first; ++it2)
1200 BFIs.push_back(std::make_pair(Index, &BitField.second));
1202 llvm::array_pod_sort(BFIs.begin(), BFIs.end());
1203 for (
auto &BFI : BFIs) {
1205 BFI.second->print(OS);
1213 print(llvm::errs());
1217 OS <<
"<CGBitFieldInfo"
1227 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.
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.
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...