28#include "llvm/ABI/Types.h"
29#include "llvm/Support/Alignment.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/TypeSize.h"
41#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
42 case BuiltinType::Id: \
44#include "clang/Basic/AArch64ACLETypes.def"
54 return llvm::abi::VectorKind::SVEData;
56 return llvm::abi::VectorKind::SVEPredicate;
58 return llvm::abi::VectorKind::Generic;
79 auto It = TypeCache.find(QT);
80 if (It != TypeCache.end())
83 const llvm::abi::Type *
Result = convertTypeImpl(QT);
84 assert(
Result &&
"convertTypeImpl returned nullptr");
90const llvm::abi::Type *QualTypeMapper::convertTypeImpl(
QualType QT) {
94#define TYPE(Class, Base)
95#define ABSTRACT_TYPE(Class, Base)
96#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
97#define DEPENDENT_TYPE(Class, Base) case Type::Class:
98#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
99#include "clang/AST/TypeNodes.inc"
100 llvm::reportFatalInternalError(
101 "Non-canonical or dependent types should not reach ABI lowering");
107 case Type::LValueReference:
108 case Type::RValueReference:
109 return createPointerTypeForPointee(
111 case Type::ConstantArray:
112 case Type::ArrayParameter:
113 case Type::IncompleteArray:
114 case Type::VariableArray:
117 case Type::ExtVector:
127 return Builder.getAtomicType(
convertType(AT->getValueType()),
130 case Type::BlockPointer:
132 return createPointerTypeForPointee(ASTCtx.
VoidPtrTy);
133 case Type::ConstantMatrix: {
135 return Builder.getArrayType(
convertType(MT->getElementType()),
136 MT->getNumRows() * MT->getNumColumns(),
139 case Type::MemberPointer:
143 return Builder.getIntegerType(BIT->getNumBits(), getTypeAlign(QT),
147 case Type::ObjCObject:
148 case Type::ObjCInterface:
149 case Type::ObjCObjectPointer:
152 return Builder.getPointerType(
156 case Type::OverflowBehavior:
159 case Type::DeducedTemplateSpecialization:
160 case Type::FunctionProto:
161 case Type::FunctionNoProto:
162 case Type::HLSLAttributedResource:
163 case Type::HLSLInlineSpirv:
164 llvm::reportFatalInternalError(
"Type not supported in ABI lowering");
166 llvm_unreachable(
"unhandled type class in convertTypeImpl");
172const llvm::abi::Type *
173QualTypeMapper::convertBuiltinType(
const BuiltinType *BT) {
176 switch (BT->getKind()) {
177 case BuiltinType::Void:
178 return Builder.getVoidType();
180 case BuiltinType::NullPtr:
182 return Builder.getPointerType(
187 case BuiltinType::Bool:
188 return Builder.getIntegerType(1, getTypeAlign(QT),
false,
191 case BuiltinType::MetaInfo:
192 llvm::reportFatalInternalError(
"std::meta::info is consteval-only type");
194 case BuiltinType::Char_S:
195 case BuiltinType::Char_U:
196 case BuiltinType::SChar:
197 case BuiltinType::UChar:
198 case BuiltinType::WChar_S:
199 case BuiltinType::WChar_U:
200 case BuiltinType::Char8:
201 case BuiltinType::Char16:
202 case BuiltinType::Char32:
203 case BuiltinType::Short:
204 case BuiltinType::UShort:
205 case BuiltinType::Int:
206 case BuiltinType::UInt:
207 case BuiltinType::Long:
208 case BuiltinType::ULong:
209 case BuiltinType::LongLong:
210 case BuiltinType::ULongLong:
211 case BuiltinType::Int128:
212 case BuiltinType::UInt128:
213 return Builder.getIntegerType(ASTCtx.getTypeSize(QT), getTypeAlign(QT),
214 BT->isSignedInteger(),
217 case BuiltinType::Half:
218 case BuiltinType::Float16:
219 case BuiltinType::BFloat16:
220 case BuiltinType::Float:
221 case BuiltinType::Double:
222 case BuiltinType::LongDouble:
223 case BuiltinType::Float128:
224 return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QT),
228 case BuiltinType::Ibm128:
229 llvm::reportFatalInternalError(
230 "IBM128 is not yet supported in the ABI lowering libary");
233 case BuiltinType::ShortAccum:
234 case BuiltinType::Accum:
235 case BuiltinType::LongAccum:
236 case BuiltinType::UShortAccum:
237 case BuiltinType::UAccum:
238 case BuiltinType::ULongAccum:
239 case BuiltinType::ShortFract:
240 case BuiltinType::Fract:
241 case BuiltinType::LongFract:
242 case BuiltinType::UShortFract:
243 case BuiltinType::UFract:
244 case BuiltinType::ULongFract:
245 case BuiltinType::SatShortAccum:
246 case BuiltinType::SatAccum:
247 case BuiltinType::SatLongAccum:
248 case BuiltinType::SatUShortAccum:
249 case BuiltinType::SatUAccum:
250 case BuiltinType::SatULongAccum:
251 case BuiltinType::SatShortFract:
252 case BuiltinType::SatFract:
253 case BuiltinType::SatLongFract:
254 case BuiltinType::SatUShortFract:
255 case BuiltinType::SatUFract:
256 case BuiltinType::SatULongFract:
257 llvm::reportFatalInternalError(
258 "Fixed Point types not yet implemented in the ABI lowering library");
261#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
262 case BuiltinType::Id:
263#include "clang/Basic/OpenCLImageTypes.def"
265#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
266#include "clang/Basic/OpenCLExtensionTypes.def"
267 case BuiltinType::OCLSampler:
268 case BuiltinType::OCLEvent:
269 case BuiltinType::OCLClkEvent:
270 case BuiltinType::OCLQueue:
271 case BuiltinType::OCLReserveID:
272 return createPointerTypeForPointee(QT);
275 case BuiltinType::ObjCId:
276 case BuiltinType::ObjCClass:
277 case BuiltinType::ObjCSel:
278 return createPointerTypeForPointee(QT);
281#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
282 case BuiltinType::Id:
283#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
284 case BuiltinType::Id:
285#include "clang/Basic/AArch64ACLETypes.def"
286 return convertSVEBuiltinType(BT);
288 case BuiltinType::SveCount:
289 return Builder.getScalablePredicateOrCountVectorType(
290 getTypeAlign(QT), llvm::abi::VectorKind::SVECount);
294 case BuiltinType::MFloat8:
295 return Builder.getOpaqueFloat8Type(getTypeAlign(QT));
298#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
299#include "clang/Basic/PPCTypes.def"
300 llvm::reportFatalInternalError(
301 "PPC MMA types not yet supported in ABI lowering library");
302#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
303#include "clang/Basic/RISCVVTypes.def"
304 llvm::reportFatalInternalError(
305 "RISC-V vector types not yet supported in ABI lowering library");
306#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
307#include "clang/Basic/WebAssemblyReferenceTypes.def"
308 llvm::reportFatalInternalError(
"WebAssembly reference types not yet "
309 "supported in ABI lowering library");
310#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
311#include "clang/Basic/AMDGPUTypes.def"
312 llvm::reportFatalInternalError(
313 "AMDGPU types not yet supported in ABI lowering library");
314#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
315#include "clang/Basic/HLSLIntangibleTypes.def"
316 llvm::reportFatalInternalError(
317 "HLSL intangible types not yet Supported in ABI lowering library");
318#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
319#include "clang/Basic/HLSLPackedTypes.def"
320 llvm::reportFatalInternalError(
321 "HLSL packed types not yet Supported in ABI lowering library");
322#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
323#include "clang/Basic/SPIRVTypes.def"
324 llvm::reportFatalInternalError(
325 "SPIR-V types not yet supported in ABI lowering library");
328#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
329#define BUILTIN_TYPE(Id, SingletonId)
330#include "clang/AST/BuiltinTypes.def"
331 llvm::reportFatalInternalError(
332 "Placeholder type should not reach ABI lowering");
334 case BuiltinType::Dependent:
335 llvm::reportFatalInternalError(
336 "Dependent builtin type should not reach ABI lowering");
338 llvm_unreachable(
"unhandled builtin type kind in convertBuiltinType");
347const llvm::abi::Type *
348QualTypeMapper::convertArrayType(
const clang::ArrayType *AT) {
352 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
353 auto NumElements = CAT->getZExtSize();
354 return Builder.getArrayType(ElementType, NumElements, Size);
357 return Builder.getArrayType(ElementType, 0, 0);
358 if (
const auto *VAT = dyn_cast<VariableArrayType>(AT))
359 return createPointerTypeForPointee(VAT->getPointeeType());
360 llvm::reportFatalInternalError(
361 "unexpected array type in ABI lowering (dependent array types should be "
362 "resolved before reaching this point)");
365const llvm::abi::Type *QualTypeMapper::convertVectorType(
const VectorType *VT) {
368 const llvm::abi::Type *ElementType =
369 VT->getElementType()->isMFloat8Type()
370 ? Builder.getIntegerType(8, llvm::Align(1),
false)
372 QualType VectorQualType(VT, 0);
374 unsigned NElems = VT->getNumElements();
375 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
376 llvm::Align VectorAlign = getTypeAlign(VectorQualType);
382 return Builder.getVectorType(ElementType, NumElements, VectorAlign,
392const llvm::abi::Type *
393QualTypeMapper::convertSVEBuiltinType(
const BuiltinType *BT) {
394 ASTContext::BuiltinVectorTypeInfo Info = ASTCtx.getBuiltinVectorTypeInfo(BT);
396 "Expected 1, 2, 3 or 4 vectors!");
401 const llvm::abi::Type *ElementType =
403 ? Builder.getIntegerType(8, llvm::Align(1),
false)
407 ? llvm::abi::VectorKind::SVEPredicate
408 : llvm::abi::VectorKind::SVEData;
410 const llvm::abi::VectorType *VecTy = Builder.getVectorType(
411 ElementType, Info.
EC, getTypeAlign(QualType(BT, 0)), VecKind);
414 return Builder.getTupleType(VecTy, Info.
NumVectors);
423const llvm::abi::Type *
424QualTypeMapper::convertComplexType(
const ComplexType *CT) {
425 const llvm::abi::Type *ElementType =
convertType(CT->getElementType());
426 llvm::Align ComplexAlign = getTypeAlign(QualType(CT, 0));
428 return Builder.getComplexType(ElementType, ComplexAlign);
437const llvm::abi::Type *
438QualTypeMapper::convertMemberPointerType(
const clang::MemberPointerType *MPT) {
441 llvm::Align Align = getTypeAlign(QT);
445 return Builder.getMemberPointerType(IsFunctionPointer, Size, Align);
450 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
452 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
454 RecFlags |= llvm::abi::RecordFlags::IsCXXEmpty;
456 RecFlags |= llvm::abi::RecordFlags::HasNonTrivialCopyAssignment;
458 RecFlags |= llvm::abi::RecordFlags::HasNonTrivialDestructor;
460 RecFlags |= llvm::abi::RecordFlags::HasNonTrivialDefaultConstructor;
470const llvm::abi::Type *QualTypeMapper::convertRecordType(
const RecordType *RT) {
473 return Builder.getRecordType({}, llvm::TypeSize::getFixed(0),
478 return convertUnionType(RD);
481 auto *CXXRd = dyn_cast<CXXRecordDecl>(RD);
482 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
483 return convertCXXRecordType(CXXRd);
484 return convertStructType(RD);
495const llvm::abi::RecordType *
496QualTypeMapper::convertCXXRecordType(
const CXXRecordDecl *RD) {
497 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
498 SmallVector<llvm::abi::FieldInfo, 16> Fields;
499 SmallVector<llvm::abi::FieldInfo, 8> BaseClasses;
500 SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses;
503 if (RD->isPolymorphic()) {
504 const llvm::abi::Type *VtablePointer =
505 createPointerTypeForPointee(ASTCtx.VoidPtrTy);
506 Fields.emplace_back(VtablePointer, 0);
509 for (
const auto &Base : RD->bases()) {
510 if (
Base.isVirtual())
513 const RecordType *BaseRT =
Base.getType()->castAs<RecordType>();
516 Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
518 BaseClasses.emplace_back(BaseType, BaseOffset);
521 for (
const auto &VBase : RD->vbases()) {
522 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
523 const llvm::abi::Type *VBaseType =
convertType(VBase.getType());
525 Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
528 VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset);
531 computeFieldInfo(RD, Fields, Layout);
534 [](
const llvm::abi::FieldInfo &A,
const llvm::abi::FieldInfo &B) {
535 return A.OffsetInBits < B.OffsetInBits;
538 llvm::TypeSize
Size =
539 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
540 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
541 llvm::Align UnadjustedAlign =
542 llvm::Align(Layout.getUnadjustedAlignment().getQuantity());
545 if (RD->canPassInRegisters())
546 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
547 if (RD->hasFlexibleArrayMember())
548 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
550 return Builder.getRecordType(Fields, Size, Alignment, UnadjustedAlign,
551 llvm::abi::StructPacking::Default, BaseClasses,
552 VirtualBaseClasses, RecFlags);
561const llvm::abi::Type *
562QualTypeMapper::convertEnumType(
const clang::EnumType *ET) {
563 const EnumDecl *ED = ET->getDecl();
564 QualType UnderlyingType = ED->getIntegerType();
566 if (UnderlyingType.isNull())
567 UnderlyingType = ASTCtx.IntTy;
578const llvm::abi::RecordType *
579QualTypeMapper::convertStructType(
const clang::RecordDecl *RD) {
580 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
582 SmallVector<llvm::abi::FieldInfo, 16> Fields;
583 computeFieldInfo(RD, Fields, Layout);
585 llvm::TypeSize
Size =
586 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
587 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
588 llvm::Align UnadjustedAlign =
589 llvm::Align(Layout.getUnadjustedAlignment().getQuantity());
591 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
592 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
595 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
597 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
599 return Builder.getRecordType(Fields, Size, Alignment, UnadjustedAlign,
600 llvm::abi::StructPacking::Default, {}, {},
610const llvm::abi::RecordType *
611QualTypeMapper::convertUnionType(
const clang::RecordDecl *RD) {
612 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
614 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
615 computeFieldInfo(RD, AllFields, Layout);
617 llvm::TypeSize
Size =
618 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
619 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
620 llvm::Align UnadjustedAlign =
621 llvm::Align(Layout.getUnadjustedAlignment().getQuantity());
623 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
624 if (RD->
hasAttr<TransparentUnionAttr>())
625 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
627 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
628 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
631 return Builder.getUnionType(AllFields, Size, Alignment, UnadjustedAlign,
632 llvm::abi::StructPacking::Default, RecFlags);
635llvm::Align QualTypeMapper::getTypeAlign(QualType QT)
const {
637 return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity());
640const llvm::abi::Type *
641QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
642 auto AddrSpace = PointeeType.getAddressSpace();
643 auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
644 llvm::Align Alignment =
645 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
649 unsigned TargetAddrSpace =
650 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
651 ? DL.getProgramAddressSpace()
652 : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace);
655 return Builder.getPointerType(
656 PointerSize, llvm::Align(Alignment.value() / 8), TargetAddrSpace,
657 PointeeType.hasAddressSpace() || TargetAddrSpace != 0);
667void QualTypeMapper::computeFieldInfo(
668 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
669 const ASTRecordLayout &Layout) {
670 unsigned FieldIndex = 0;
672 for (
const auto *FD : RD->fields()) {
673 const llvm::abi::Type *FieldType =
convertType(FD->getType());
674 uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
676 bool IsBitField = FD->isBitField();
678 bool IsUnnamedBitField =
false;
681 BitFieldWidth = FD->getBitWidthValue();
682 IsUnnamedBitField = FD->isUnnamedBitField();
685 bool HasNoUniqueAddress = FD->hasAttr<NoUniqueAddressAttr>();
686 Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth,
687 IsUnnamedBitField, HasNoUniqueAddress);
Defines the clang::ASTContext interface.
Forward declaration of all AST node types.
Provides definitions for the various language-specific address spaces.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Maps Clang QualType instances to corresponding LLVM ABI type representations.
static QualType getUnderlyingType(const SubRegion *R)
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
QualType getElementType() const
This class is used for builtin types like 'int'.
Represents a C++ struct/union/class.
bool hasNonTrivialCopyAssignment() const
Determine whether this class has a non-trivial copy assignment operator (C++ [class....
bool hasNonTrivialDestructor() const
Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
bool hasNonTrivialDefaultConstructor() const
Determine whether this class has a non-trivial default constructor (C++11 [class.ctor]p5).
const llvm::abi::Type * convertType(clang::QualType QT)
Main entry point for converting Clang QualType to LLVM ABI Type.
A (possibly-)qualified type.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Represents a struct/union/class.
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
bool hasFlexibleArrayMember() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
bool isMemberFunctionPointerType() const
TypeClass getTypeClass() const
Defines the clang::TargetInfo interface.
static llvm::abi::RecordFlags getCXXRecordFlags(const CXXRecordDecl *RD)
Returns the record flags that describe C++ class properties of RD.
static llvm::abi::VectorKind getABIVectorKind(clang::VectorKind Kind)
Maps a Clang vector kind onto the ABI library's notion of a vector flavor.
static bool isSVEPredicateBuiltinType(const BuiltinType *BT)
Returns true if BT is one of the AArch64 SVE predicate types, i.e.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.
@ SveFixedLengthData
is AArch64 SVE fixed-length data vector
@ SveFixedLengthPredicate
is AArch64 SVE fixed-length predicate vector
U cast(CodeGen::Address addr)