24#include "llvm/Support/Casting.h"
37struct CIRRecordLowering final {
42 struct MemberInfo final {
44 enum class InfoKind { VFPtr,
Field,
Base, VBase } kind;
50 MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
53 MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
54 const CXXRecordDecl *rd)
55 : offset{offset}, kind{kind}, data{data},
cxxRecordDecl{rd} {}
57 bool operator<(
const MemberInfo &other)
const {
58 return offset < other.offset;
62 CIRRecordLowering(CIRGenTypes &cirGenTypes,
const RecordDecl *recordDecl,
66 MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) {
67 return MemberInfo(offset, MemberInfo::InfoKind::Field, data);
71 void setBitFieldInfo(
const FieldDecl *fd, CharUnits startOffset,
72 mlir::Type storageType);
74 void lower(
bool nonVirtualBaseType);
75 void lowerUnion(
bool nonVirtualBaseType);
78 void determinePacked(
bool nvBaseType);
82 void computeVolatileBitfields();
83 void accumulateBases();
84 void accumulateVPtrs();
85 void accumulateVBases();
86 void accumulateFields();
91 mlir::Type getVFPtrType();
94 return astContext.getTargetInfo().getABI().starts_with(
"aapcs");
98 bool isBigEndian()
const {
return astContext.getTargetInfo().isBigEndian(); }
104 bool isOverlappingVBaseABI() {
105 return !astContext.getTargetInfo().getCXXABI().isMicrosoft();
109 bool hasOwnStorage(
const CXXRecordDecl *
decl,
const CXXRecordDecl *query);
116 bool isDiscreteBitFieldABI() {
117 return astContext.getTargetInfo().getCXXABI().isMicrosoft() ||
118 recordDecl->isMsStruct(astContext);
121 CharUnits bitsToCharUnits(uint64_t bitOffset) {
122 return astContext.toCharUnitsFromBits(bitOffset);
125 void calculateZeroInit();
127 CharUnits getSize(mlir::Type Ty) {
130 CharUnits getSizeInBits(mlir::Type ty) {
133 CharUnits getAlignment(mlir::Type Ty) {
137 bool isZeroInitializable(
const FieldDecl *fd) {
138 return cirGenTypes.isZeroInitializable(fd->
getType());
140 bool isZeroInitializable(
const RecordDecl *rd) {
141 return cirGenTypes.isZeroInitializable(rd);
145 mlir::Type getUIntNType(uint64_t numBits) {
146 unsigned alignedBits = llvm::PowerOf2Ceil(numBits);
147 alignedBits = std::max(8u, alignedBits);
148 return cir::IntType::get(&cirGenTypes.getMLIRContext(), alignedBits,
152 mlir::Type getCharType() {
153 return cir::IntType::get(&cirGenTypes.getMLIRContext(),
154 astContext.getCharWidth(),
158 mlir::Type getByteArrayType(CharUnits numberOfChars) {
159 assert(!numberOfChars.
isZero() &&
"Empty byte arrays aren't allowed.");
160 mlir::Type
type = getCharType();
167 mlir::Type getStorageType(
const CXXRecordDecl *RD) {
168 return cirGenTypes.getCIRGenRecordLayout(RD).getBaseSubobjectCIRType();
173 mlir::Type getBitfieldStorageType(
unsigned numBits) {
174 unsigned alignedBits = llvm::alignTo(numBits, astContext.getCharWidth());
176 return builder.getUIntNTy(alignedBits);
178 mlir::Type
type = getCharType();
179 return cir::ArrayType::get(
type, alignedBits / astContext.getCharWidth());
182 mlir::Type getStorageType(
const FieldDecl *
fieldDecl) {
183 mlir::Type
type = cirGenTypes.convertTypeForMem(
fieldDecl->getType());
185 cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
186 "getStorageType for bitfields");
192 return astRecordLayout.getFieldOffset(
fieldDecl->getFieldIndex());
196 void fillOutputFields();
198 void appendPaddingBytes(CharUnits size) {
201 mlir::Type padTy = getByteArrayType(size);
203 if (recordDecl->isUnion()) {
204 assert(!unionPadding &&
"at most one union tail-padding type");
205 unionPadding = padTy;
207 fieldTypes.push_back(padTy);
211 CIRGenTypes &cirGenTypes;
212 CIRGenBuilderTy &builder;
213 const ASTContext &astContext;
214 const RecordDecl *recordDecl;
215 const CXXRecordDecl *cxxRecordDecl;
216 const ASTRecordLayout &astRecordLayout;
218 std::vector<MemberInfo> members;
220 llvm::SmallVector<mlir::Type, 16> fieldTypes;
221 mlir::Type unionPadding;
222 llvm::DenseMap<const FieldDecl *, CIRGenBitFieldInfo> bitFields;
223 llvm::DenseMap<const FieldDecl *, unsigned> fieldIdxMap;
224 llvm::DenseMap<const CXXRecordDecl *, unsigned> nonVirtualBases;
225 llvm::DenseMap<const CXXRecordDecl *, unsigned> virtualBases;
226 cir::CIRDataLayout dataLayout;
228 LLVM_PREFERRED_TYPE(
bool)
229 unsigned zeroInitializable : 1;
230 LLVM_PREFERRED_TYPE(
bool)
231 unsigned zeroInitializableAsBase : 1;
232 LLVM_PREFERRED_TYPE(
bool)
234 LLVM_PREFERRED_TYPE(
bool)
238 CIRRecordLowering(
const CIRRecordLowering &) =
delete;
239 void operator=(
const CIRRecordLowering &) =
delete;
243CIRRecordLowering::CIRRecordLowering(
CIRGenTypes &cirGenTypes,
245 : cirGenTypes{cirGenTypes}, builder{cirGenTypes.getBuilder()},
249 cirGenTypes.getASTContext().getASTRecordLayout(
recordDecl)},
250 dataLayout{cirGenTypes.getCGModule().getModule()},
251 zeroInitializable{
true}, zeroInitializableAsBase{
true}, packed{packed},
254void CIRRecordLowering::setBitFieldInfo(
const FieldDecl *fd,
256 mlir::Type storageType) {
260 (unsigned)(getFieldBitOffset(fd) - astContext.
toBits(startOffset));
262 info.
storageSize = getSizeInBits(storageType).getQuantity();
281void CIRRecordLowering::lower(
bool nonVirtualBaseType) {
283 lowerUnion(nonVirtualBaseType);
284 computeVolatileBitfields();
296 if (members.empty()) {
297 appendPaddingBytes(size);
298 computeVolatileBitfields();
301 if (!nonVirtualBaseType)
305 llvm::stable_sort(members);
309 members.push_back(makeStorageInfo(size, getUIntNType(8)));
310 determinePacked(nonVirtualBaseType);
316 computeVolatileBitfields();
319void CIRRecordLowering::fillOutputFields() {
320 for (
const MemberInfo &member : members) {
322 fieldTypes.push_back(
member.data);
323 if (
member.kind == MemberInfo::InfoKind::Field) {
325 fieldIdxMap[
member.fieldDecl->getCanonicalDecl()] =
326 fieldTypes.size() - 1;
329 assert(
member.fieldDecl &&
330 "member.data is a nullptr so member.fieldDecl should not be");
331 setBitFieldInfo(
member.fieldDecl,
member.offset, fieldTypes.back());
333 }
else if (
member.kind == MemberInfo::InfoKind::Base) {
334 nonVirtualBases[
member.cxxRecordDecl] = fieldTypes.size() - 1;
335 }
else if (
member.kind == MemberInfo::InfoKind::VBase) {
336 virtualBases[
member.cxxRecordDecl] = fieldTypes.size() - 1;
344 if (isDiscreteBitFieldABI()) {
355 for (; field != fieldEnd && field->isBitField(); ++field) {
357 if (field->isZeroLengthBitField()) {
361 uint64_t bitOffset = getFieldBitOffset(*field);
365 if (run == fieldEnd || bitOffset >= tail) {
367 startBitOffset = bitOffset;
373 makeStorageInfo(bitsToCharUnits(startBitOffset),
type));
377 members.push_back(MemberInfo(bitsToCharUnits(startBitOffset),
378 MemberInfo::InfoKind::Field,
nullptr,
395 CharUnits beginOffset;
404 CharUnits bestEndOffset;
412 bool atAlignedBoundary =
false;
414 if (field != fieldEnd && field->isBitField()) {
415 uint64_t bitOffset = getFieldBitOffset(*field);
416 if (begin == fieldEnd) {
421 assert((bitOffset % charBits) == 0 &&
"Not at start of char");
422 beginOffset = bitsToCharUnits(bitOffset);
423 bitSizeSinceBegin = 0;
424 }
else if ((bitOffset % charBits) != 0) {
432 astContext.
toBits(beginOffset) + bitSizeSinceBegin &&
433 "Concatenating non-contiguous bitfields");
438 if (field->isZeroLengthBitField())
440 atAlignedBoundary =
true;
445 if (begin == fieldEnd)
449 atAlignedBoundary =
true;
455 bool installBest =
false;
456 if (atAlignedBoundary) {
462 CharUnits accessSize = bitsToCharUnits(bitSizeSinceBegin + charBits - 1);
463 if (bestEnd == begin) {
467 bestEndOffset = beginOffset + accessSize;
470 if (!bitSizeSinceBegin)
474 }
else if (accessSize > regSize) {
483 mlir::Type
type = getUIntNType(astContext.
toBits(accessSize));
486 field->getSourceRange(),
"NYI CheapUnalignedBitFieldAccess");
493 CharUnits limitOffset;
494 for (
auto probe = field; probe != fieldEnd; ++probe)
497 assert((getFieldBitOffset(*probe) % charBits) == 0 &&
498 "Next storage is not byte-aligned");
499 limitOffset = bitsToCharUnits(getFieldBitOffset(*probe));
506 CharUnits typeSize = getSize(
type);
507 if (beginOffset + typeSize <= limitOffset) {
510 bestEndOffset = beginOffset + typeSize;
519 .FineGrainedBitfieldAccesses) {
525 bitSizeSinceBegin = astContext.
toBits(limitOffset - beginOffset);
532 assert((field == fieldEnd || !field->isBitField() ||
533 (getFieldBitOffset(*field) % charBits) == 0) &&
534 "Installing but not at an aligned bitfield or limit");
535 CharUnits accessSize = bestEndOffset - beginOffset;
536 if (!accessSize.
isZero()) {
542 assert(getSize(getUIntNType(astContext.
toBits(accessSize))) >
544 "Clipped access need not be clipped");
545 type = getByteArrayType(accessSize);
547 type = getUIntNType(astContext.
toBits(accessSize));
548 assert(getSize(
type) == accessSize &&
549 "Unclipped access must be clipped");
551 members.push_back(makeStorageInfo(beginOffset,
type));
552 for (; begin != bestEnd; ++begin)
553 if (!begin->isZeroLengthBitField())
554 members.push_back(MemberInfo(
555 beginOffset, MemberInfo::InfoKind::Field,
nullptr, *begin));
561 assert(field != fieldEnd && field->isBitField() &&
562 "Accumulating past end of bitfields");
563 assert(!
barrier &&
"Accumulating across barrier");
565 bitSizeSinceBegin += field->getBitWidthValue();
573void CIRRecordLowering::accumulateFields() {
576 field != fieldEnd;) {
577 if (field->isBitField()) {
578 field = accumulateBitFields(field, fieldEnd);
579 assert((field == fieldEnd || !field->isBitField()) &&
580 "Failed to accumulate all the bitfields");
588 members.push_back(MemberInfo(
589 bitsToCharUnits(getFieldBitOffset(*field)),
590 MemberInfo::InfoKind::Field,
591 field->isPotentiallyOverlapping()
592 ? getStorageType(field->getType()->getAsCXXRecordDecl())
593 : getStorageType(*field),
600void CIRRecordLowering::calculateZeroInit() {
601 for (
const MemberInfo &member : members) {
602 if (
member.kind == MemberInfo::InfoKind::Field) {
603 if (!
member.fieldDecl || isZeroInitializable(
member.fieldDecl))
605 zeroInitializable = zeroInitializableAsBase =
false;
607 }
else if (
member.kind == MemberInfo::InfoKind::Base ||
608 member.kind == MemberInfo::InfoKind::VBase) {
609 if (isZeroInitializable(
member.cxxRecordDecl))
611 zeroInitializable =
false;
612 if (
member.kind == MemberInfo::InfoKind::Base)
613 zeroInitializableAsBase =
false;
618void CIRRecordLowering::determinePacked(
bool nvBaseType) {
627 for (
const MemberInfo &member : members) {
632 if (!
member.offset.isMultipleOf(getAlignment(
member.data)))
634 if (
member.offset < nvSize)
635 nvAlignment = std::max(nvAlignment, getAlignment(
member.data));
636 alignment = std::max(alignment, getAlignment(
member.data));
640 if (!members.back().offset.isMultipleOf(alignment))
649 members.back().data = getUIntNType(astContext.
toBits(alignment));
652void CIRRecordLowering::insertPadding() {
653 std::vector<std::pair<CharUnits, CharUnits>> padding;
655 for (
const MemberInfo &member : members) {
658 CharUnits offset =
member.offset;
659 assert(offset >= size);
663 padding.push_back(std::make_pair(size, offset - size));
664 size = offset + getSize(
member.data);
670 for (
const std::pair<CharUnits, CharUnits> &paddingPair : padding)
671 members.push_back(makeStorageInfo(paddingPair.first,
672 getByteArrayType(paddingPair.second)));
673 llvm::stable_sort(members);
676static cir::ArgPassingKind
680 return cir::ArgPassingKind::CanPassInRegs;
682 return cir::ArgPassingKind::CannotPassInRegs;
684 return cir::ArgPassingKind::CanNeverPassInRegs;
686 llvm_unreachable(
"unknown RecordArgPassingKind");
689std::unique_ptr<CIRGenRecordLayout>
691 CIRRecordLowering lowering(*
this, rd,
false);
692 assert(ty->
isIncomplete() &&
"recomputing record layout?");
693 lowering.lower(
false);
705 if (llvm::isa<CXXRecordDecl>(rd)) {
714 lowering.astRecordLayout.
getSize()) {
715 CIRRecordLowering baseLowering(*
this, rd, lowering.packed);
716 baseLowering.lower(
true);
718 baseTy = builder.getCompleteNamedRecordType(
719 baseLowering.fieldTypes, baseLowering.packed, baseLowering.padded,
729 assert((rd->
isUnion() || lowering.packed == baseLowering.packed) &&
730 "Non-virtual and complete types must agree on packedness");
738 ty->
complete(lowering.fieldTypes, lowering.packed, lowering.padded,
739 lowering.unionPadding);
743 mlir::MLIRContext *mlirCtx = ty->getContext();
744 cir::ArgPassingKind apk =
747 bool hasTrivialDestructor =
true;
748 if (
auto *cxxRD = dyn_cast<CXXRecordDecl>(rd))
749 hasTrivialDestructor = cxxRD->hasTrivialDestructor();
750 const auto &astLayout = astContext.getASTRecordLayout(rd);
751 uint64_t recordAlignInBytes = astLayout.getAlignment().getQuantity();
753 cgm.addRecordLayout(ty->
getName(), cir::RecordLayoutAttr::get(
754 mlirCtx, apk, hasTrivialDestructor,
755 recordAlignInBytes));
758 auto rl = std::make_unique<CIRGenRecordLayout>(
760 (bool)lowering.zeroInitializable, (bool)lowering.zeroInitializableAsBase);
762 rl->nonVirtualBases.swap(lowering.nonVirtualBases);
763 rl->completeObjectVirtualBases.swap(lowering.virtualBases);
766 rl->fieldIdxMap.swap(lowering.fieldIdxMap);
768 rl->bitFields.swap(lowering.bitFields);
772 llvm::outs() <<
"\n*** Dumping CIRgen Record Layout\n";
773 llvm::outs() <<
"Record: ";
774 rd->
dump(llvm::outs());
775 llvm::outs() <<
"\nLayout: ";
776 rl->print(llvm::outs());
784 os <<
"<CIRecordLayout\n";
785 os <<
" CIR Type:" << completeObjectType <<
"\n";
786 if (baseSubobjectType)
787 os <<
" NonVirtualBaseCIRType:" << baseSubobjectType <<
"\n";
788 os <<
" IsZeroInitializable:" << zeroInitializable <<
"\n";
789 os <<
" BitFields:[\n";
790 std::vector<std::pair<unsigned, const CIRGenBitFieldInfo *>> bitInfo;
791 for (
auto &[
decl, info] : bitFields) {
796 bitInfo.push_back(std::make_pair(
index, &info));
798 llvm::array_pod_sort(bitInfo.begin(), bitInfo.end());
799 for (std::pair<unsigned, const CIRGenBitFieldInfo *> &info : bitInfo) {
801 info.second->
print(os);
808 os <<
"<CIRBitFieldInfo" <<
" name:" <<
name <<
" offset:" <<
offset
821void CIRRecordLowering::lowerUnion(
bool nonVirtualBaseType) {
828 mlir::Type storageType =
nullptr;
829 bool seenNamedMember =
false;
834 mlir::Type fieldType;
835 if (field->isBitField()) {
836 if (field->isZeroLengthBitField())
838 fieldType = getBitfieldStorageType(field->getBitWidthValue());
841 fieldType = getStorageType(field);
845 fieldIdxMap[field->getCanonicalDecl()] = 0;
853 if (!seenNamedMember) {
854 seenNamedMember = field->getIdentifier();
855 if (!seenNamedMember)
856 if (
const RecordDecl *fieldRD = field->getType()->getAsRecordDecl())
857 seenNamedMember = fieldRD->findFirstNamedDataMember();
858 if (seenNamedMember && !isZeroInitializable(field)) {
859 zeroInitializable = zeroInitializableAsBase =
false;
860 storageType = fieldType;
866 if (!zeroInitializable)
870 if (!storageType || getAlignment(fieldType) > getAlignment(storageType) ||
871 (getAlignment(fieldType) == getAlignment(storageType) &&
872 getSize(fieldType) > getSize(storageType)))
873 storageType = fieldType;
881 if (!nonVirtualBaseType)
882 fieldTypes.push_back(fieldType);
886 appendPaddingBytes(layoutSize);
890 if (layoutSize < getSize(storageType))
891 storageType = getByteArrayType(layoutSize);
893 if (nonVirtualBaseType) {
897 fieldTypes.push_back(storageType);
898 CharUnits padding = layoutSize - getSize(storageType);
900 fieldTypes.push_back(getByteArrayType(padding));
904 appendPaddingBytes(layoutSize - getSize(storageType));
908 if (!layoutSize.
isMultipleOf(getAlignment(storageType)))
912bool CIRRecordLowering::hasOwnStorage(
const CXXRecordDecl *
decl,
913 const CXXRecordDecl *query) {
917 for (
const auto &base :
decl->bases())
918 if (!hasOwnStorage(base.getType()->getAsCXXRecordDecl(), query))
936void CIRRecordLowering::computeVolatileBitfields() {
941 for (
auto &[field, info] : bitFields) {
945 getSizeInBits(resLTy).getQuantity())
953 const unsigned oldOffset =
957 const unsigned absoluteOffset =
961 const unsigned storageSize = getSizeInBits(resLTy).getQuantity();
964 if (info.
storageSize == storageSize && (oldOffset % storageSize == 0))
968 unsigned offset = absoluteOffset & (storageSize - 1);
973 if (offset + info.
size > storageSize)
978 offset = storageSize - (offset + info.
size);
980 const CharUnits storageOffset =
982 const CharUnits end = storageOffset +
986 const ASTRecordLayout &layout =
989 const CharUnits recordSize = layout.
getSize();
990 if (end >= recordSize)
994 bool conflict =
false;
997 if (f->isBitField() && !f->isZeroLengthBitField())
1007 if (f->isZeroLengthBitField()) {
1008 if (end > fOffset && storageOffset < fOffset) {
1014 const CharUnits fEnd =
1021 if (end < fOffset || fEnd < storageOffset)
1042void CIRRecordLowering::accumulateBases() {
1045 const CXXRecordDecl *baseDecl = astRecordLayout.
getPrimaryBase();
1046 members.push_back(MemberInfo(
CharUnits::Zero(), MemberInfo::InfoKind::Base,
1047 getStorageType(baseDecl), baseDecl));
1052 if (base.isVirtual())
1056 const CXXRecordDecl *baseDecl = base.getType()->getAsCXXRecordDecl();
1060 MemberInfo::InfoKind::Base,
1061 getStorageType(baseDecl), baseDecl));
1066void CIRRecordLowering::accumulateVBases() {
1068 const CXXRecordDecl *baseDecl = base.getType()->getAsCXXRecordDecl();
1074 if (isOverlappingVBaseABI() && astContext.
isNearlyEmpty(baseDecl) &&
1077 MemberInfo(offset, MemberInfo::InfoKind::VBase,
nullptr, baseDecl));
1083 ->second.hasVtorDisp())
1086 members.push_back(MemberInfo(offset, MemberInfo::InfoKind::VBase,
1087 getStorageType(baseDecl), baseDecl));
1091void CIRRecordLowering::accumulateVPtrs() {
1093 members.push_back(MemberInfo(
CharUnits::Zero(), MemberInfo::InfoKind::VFPtr,
1098 "accumulateVPtrs: hasOwnVBPtr");
1101mlir::Type CIRRecordLowering::getVFPtrType() {
1102 return cir::VPtrType::get(builder.getContext());
Defines the clang::ASTContext interface.
static bool isAAPCS(const TargetInfo &targetInfo)
Helper method to check if the underlying ABI is AAPCS.
static cir::ArgPassingKind convertRecordArgPassingKind(RecordArgPassingKind kind)
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)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
llvm::TypeSize getTypeAllocSizeInBits(mlir::Type ty) const
Returns the offset in bits between successive objects of the specified type, including alignment padd...
C++ view class that accepts both !cir.struct and !cir.union types.
bool isIncomplete() const
void complete(llvm::ArrayRef< mlir::Type > members, bool packed, bool padded, mlir::Type padding={})
mlir::StringAttr getName() const
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.
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.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
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...
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
const clang::CodeGenOptions & getCodeGenOpts() const
LLVM_DUMP_METHOD void dump() const
void print(raw_ostream &os) const
This class organizes the cross-module state that is used while lowering AST types to CIR types.
CIRGenModule & getCGModule() const
std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)
clang::ASTContext & getASTContext() const
std::unique_ptr< CIRGenRecordLayout > computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty)
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
Represents a C++ struct/union/class.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
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)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
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 ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Represents a member of a struct/union/class.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents a struct/union/class.
RecordArgPassingKind getArgPassingRestrictions() 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 isValidFundamentalIntWidth(unsigned width)
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
bool isEmptyRecordForLayout(const ASTContext &context, QualType t)
isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl
Matches class, struct, and union declarations.
The JSON file list parser is used to communicate input to InstallAPI.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
RecordArgPassingKind
Enum that represents the different ways arguments are passed to and returned from function calls.
@ CanPassInRegs
The argument of this type can be passed directly in registers.
@ CanNeverPassInRegs
The argument of this type cannot be passed directly in registers.
@ CannotPassInRegs
The argument of this type cannot be passed directly in registers.
Diagnostic wrappers for TextAPI types for error reporting.
void __ovld __conv barrier(cl_mem_fence_flags)
All work-items in a work-group executing the kernel on a processor must execute this function before ...
static bool zeroSizeRecordMembers()
static bool checkBitfieldClipping()
static bool astRecordDeclAttr()
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
void print(llvm::raw_ostream &os) const
LLVM_DUMP_METHOD void dump() const
unsigned storageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned volatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
clang::CharUnits storageOffset
The offset of the bitfield storage from the start of the record.
unsigned size
The total size of the bit-field, in bits.
unsigned isSigned
Whether the bit-field is signed.
clang::CharUnits volatileStorageOffset
The offset of the bitfield storage from the start of the record.
unsigned volatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
llvm::StringRef name
The name of a bitfield.