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:
151 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:
181 return createPointerTypeForPointee(QT);
183 case BuiltinType::Bool:
184 return Builder.getIntegerType(1, getTypeAlign(QT),
false,
187 case BuiltinType::Char_S:
188 case BuiltinType::Char_U:
189 case BuiltinType::SChar:
190 case BuiltinType::UChar:
191 case BuiltinType::WChar_S:
192 case BuiltinType::WChar_U:
193 case BuiltinType::Char8:
194 case BuiltinType::Char16:
195 case BuiltinType::Char32:
196 case BuiltinType::Short:
197 case BuiltinType::UShort:
198 case BuiltinType::Int:
199 case BuiltinType::UInt:
200 case BuiltinType::Long:
201 case BuiltinType::ULong:
202 case BuiltinType::LongLong:
203 case BuiltinType::ULongLong:
204 case BuiltinType::Int128:
205 case BuiltinType::UInt128:
206 return Builder.getIntegerType(ASTCtx.getTypeSize(QT), getTypeAlign(QT),
207 BT->isSignedInteger(),
210 case BuiltinType::Half:
211 case BuiltinType::Float16:
212 case BuiltinType::BFloat16:
213 case BuiltinType::Float:
214 case BuiltinType::Double:
215 case BuiltinType::LongDouble:
216 case BuiltinType::Float128:
217 return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QT),
221 case BuiltinType::Ibm128:
222 llvm::reportFatalInternalError(
223 "IBM128 is not yet supported in the ABI lowering libary");
226 case BuiltinType::ShortAccum:
227 case BuiltinType::Accum:
228 case BuiltinType::LongAccum:
229 case BuiltinType::UShortAccum:
230 case BuiltinType::UAccum:
231 case BuiltinType::ULongAccum:
232 case BuiltinType::ShortFract:
233 case BuiltinType::Fract:
234 case BuiltinType::LongFract:
235 case BuiltinType::UShortFract:
236 case BuiltinType::UFract:
237 case BuiltinType::ULongFract:
238 case BuiltinType::SatShortAccum:
239 case BuiltinType::SatAccum:
240 case BuiltinType::SatLongAccum:
241 case BuiltinType::SatUShortAccum:
242 case BuiltinType::SatUAccum:
243 case BuiltinType::SatULongAccum:
244 case BuiltinType::SatShortFract:
245 case BuiltinType::SatFract:
246 case BuiltinType::SatLongFract:
247 case BuiltinType::SatUShortFract:
248 case BuiltinType::SatUFract:
249 case BuiltinType::SatULongFract:
250 llvm::reportFatalInternalError(
251 "Fixed Point types not yet implemented in the ABI lowering library");
254#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
255 case BuiltinType::Id:
256#include "clang/Basic/OpenCLImageTypes.def"
258#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
259#include "clang/Basic/OpenCLExtensionTypes.def"
260 case BuiltinType::OCLSampler:
261 case BuiltinType::OCLEvent:
262 case BuiltinType::OCLClkEvent:
263 case BuiltinType::OCLQueue:
264 case BuiltinType::OCLReserveID:
265 return createPointerTypeForPointee(QT);
268 case BuiltinType::ObjCId:
269 case BuiltinType::ObjCClass:
270 case BuiltinType::ObjCSel:
271 return createPointerTypeForPointee(QT);
274#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
275 case BuiltinType::Id:
276#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
277 case BuiltinType::Id:
278#include "clang/Basic/AArch64ACLETypes.def"
279 return convertSVEBuiltinType(BT);
281 case BuiltinType::SveCount:
282 return Builder.getScalablePredicateOrCountVectorType(
283 getTypeAlign(QT), llvm::abi::VectorKind::SVECount);
290 case BuiltinType::MFloat8:
291 llvm::reportFatalInternalError(
292 "__mfp8 is not yet supported in the ABI lowering library");
295#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
296#include "clang/Basic/PPCTypes.def"
297 llvm::reportFatalInternalError(
298 "PPC MMA types not yet supported in ABI lowering library");
299#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
300#include "clang/Basic/RISCVVTypes.def"
301 llvm::reportFatalInternalError(
302 "RISC-V vector types not yet supported in ABI lowering library");
303#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
304#include "clang/Basic/WebAssemblyReferenceTypes.def"
305 llvm::reportFatalInternalError(
"WebAssembly reference types not yet "
306 "supported in ABI lowering library");
307#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
308#include "clang/Basic/AMDGPUTypes.def"
309 llvm::reportFatalInternalError(
310 "AMDGPU types not yet supported in ABI lowering library");
311#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
312#include "clang/Basic/HLSLIntangibleTypes.def"
313 llvm::reportFatalInternalError(
314 "HLSL intangible types not yet Supported in ABI lowering library");
315#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
316#include "clang/Basic/HLSLPackedTypes.def"
317 llvm::reportFatalInternalError(
318 "HLSL packed types not yet Supported in ABI lowering library");
319#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
320#include "clang/Basic/SPIRVTypes.def"
321 llvm::reportFatalInternalError(
322 "SPIR-V types not yet supported in ABI lowering library");
325#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
326#define BUILTIN_TYPE(Id, SingletonId)
327#include "clang/AST/BuiltinTypes.def"
328 llvm::reportFatalInternalError(
329 "Placeholder type should not reach ABI lowering");
331 case BuiltinType::Dependent:
332 llvm::reportFatalInternalError(
333 "Dependent builtin type should not reach ABI lowering");
335 llvm_unreachable(
"unhandled builtin type kind in convertBuiltinType");
344const llvm::abi::Type *
345QualTypeMapper::convertArrayType(
const clang::ArrayType *AT) {
349 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
350 auto NumElements = CAT->getZExtSize();
351 return Builder.getArrayType(ElementType, NumElements, Size);
354 return Builder.getArrayType(ElementType, 0, 0);
355 if (
const auto *VAT = dyn_cast<VariableArrayType>(AT))
356 return createPointerTypeForPointee(VAT->getPointeeType());
357 llvm::reportFatalInternalError(
358 "unexpected array type in ABI lowering (dependent array types should be "
359 "resolved before reaching this point)");
362const llvm::abi::Type *QualTypeMapper::convertVectorType(
const VectorType *VT) {
363 const llvm::abi::Type *ElementType =
convertType(VT->getElementType());
364 QualType VectorQualType(VT, 0);
366 unsigned NElems = VT->getNumElements();
367 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
368 llvm::Align VectorAlign = getTypeAlign(VectorQualType);
374 return Builder.getVectorType(ElementType, NumElements, VectorAlign,
384const llvm::abi::Type *
385QualTypeMapper::convertSVEBuiltinType(
const BuiltinType *BT) {
386 ASTContext::BuiltinVectorTypeInfo Info = ASTCtx.getBuiltinVectorTypeInfo(BT);
388 "Expected 1, 2, 3 or 4 vectors!");
393 const llvm::abi::Type *ElementType =
395 ? Builder.getIntegerType(8, llvm::Align(1),
false)
399 ? llvm::abi::VectorKind::SVEPredicate
400 : llvm::abi::VectorKind::SVEData;
402 const llvm::abi::VectorType *VecTy = Builder.getVectorType(
403 ElementType, Info.
EC, getTypeAlign(QualType(BT, 0)), VecKind);
406 return Builder.getTupleType(VecTy, Info.
NumVectors);
415const llvm::abi::Type *
416QualTypeMapper::convertComplexType(
const ComplexType *CT) {
417 const llvm::abi::Type *ElementType =
convertType(CT->getElementType());
418 llvm::Align ComplexAlign = getTypeAlign(QualType(CT, 0));
420 return Builder.getComplexType(ElementType, ComplexAlign);
429const llvm::abi::Type *
430QualTypeMapper::convertMemberPointerType(
const clang::MemberPointerType *MPT) {
433 llvm::Align Align = getTypeAlign(QT);
437 return Builder.getMemberPointerType(IsFunctionPointer, Size, Align);
446const llvm::abi::Type *QualTypeMapper::convertRecordType(
const RecordType *RT) {
447 const RecordDecl *RD = RT->getDecl()->getDefinition();
449 return Builder.getRecordType({}, llvm::TypeSize::getFixed(0),
454 return convertUnionType(RD);
457 auto *CXXRd = dyn_cast<CXXRecordDecl>(RD);
458 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
459 return convertCXXRecordType(CXXRd);
460 return convertStructType(RD);
471const llvm::abi::RecordType *
472QualTypeMapper::convertCXXRecordType(
const CXXRecordDecl *RD) {
473 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
474 SmallVector<llvm::abi::FieldInfo, 16> Fields;
475 SmallVector<llvm::abi::FieldInfo, 8> BaseClasses;
476 SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses;
479 if (RD->isPolymorphic()) {
480 const llvm::abi::Type *VtablePointer =
481 createPointerTypeForPointee(ASTCtx.VoidPtrTy);
482 Fields.emplace_back(VtablePointer, 0);
485 for (
const auto &Base : RD->bases()) {
486 if (
Base.isVirtual())
489 const RecordType *BaseRT =
Base.getType()->castAs<RecordType>();
492 Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
494 BaseClasses.emplace_back(BaseType, BaseOffset);
497 for (
const auto &VBase : RD->vbases()) {
498 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
499 const llvm::abi::Type *VBaseType =
convertType(VBase.getType());
501 Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
504 VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset);
507 computeFieldInfo(RD, Fields, Layout);
510 [](
const llvm::abi::FieldInfo &A,
const llvm::abi::FieldInfo &B) {
511 return A.OffsetInBits < B.OffsetInBits;
514 llvm::TypeSize
Size =
515 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
516 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
517 llvm::Align UnadjustedAlign =
518 llvm::Align(Layout.getUnadjustedAlignment().getQuantity());
520 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
521 if (RD->isPolymorphic())
522 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
523 if (RD->canPassInRegisters())
524 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
525 if (RD->hasFlexibleArrayMember())
526 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
528 return Builder.getRecordType(Fields, Size, Alignment, UnadjustedAlign,
529 llvm::abi::StructPacking::Default, BaseClasses,
530 VirtualBaseClasses, RecFlags);
539const llvm::abi::Type *
540QualTypeMapper::convertEnumType(
const clang::EnumType *ET) {
541 const EnumDecl *ED = ET->getDecl();
542 QualType UnderlyingType = ED->getIntegerType();
544 if (UnderlyingType.isNull())
545 UnderlyingType = ASTCtx.IntTy;
556const llvm::abi::RecordType *
557QualTypeMapper::convertStructType(
const clang::RecordDecl *RD) {
558 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
561 SmallVector<llvm::abi::FieldInfo, 16> Fields;
562 computeFieldInfo(RD, Fields, Layout);
564 llvm::TypeSize
Size =
565 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
566 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
567 llvm::Align UnadjustedAlign =
568 llvm::Align(Layout.getUnadjustedAlignment().getQuantity());
570 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
572 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
574 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
576 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
578 return Builder.getRecordType(Fields, Size, Alignment, UnadjustedAlign,
579 llvm::abi::StructPacking::Default, {}, {},
589const llvm::abi::RecordType *
590QualTypeMapper::convertUnionType(
const clang::RecordDecl *RD) {
591 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
593 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
594 computeFieldInfo(RD, AllFields, Layout);
596 llvm::TypeSize
Size =
597 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
598 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
599 llvm::Align UnadjustedAlign =
600 llvm::Align(Layout.getUnadjustedAlignment().getQuantity());
602 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
603 if (RD->
hasAttr<TransparentUnionAttr>())
604 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
606 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
608 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
610 return Builder.getUnionType(AllFields, Size, Alignment, UnadjustedAlign,
611 llvm::abi::StructPacking::Default, RecFlags);
614llvm::Align QualTypeMapper::getTypeAlign(QualType QT)
const {
616 return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity());
619const llvm::abi::Type *
620QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
621 auto AddrSpace = PointeeType.getAddressSpace();
622 auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
623 llvm::Align Alignment =
624 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
628 unsigned TargetAddrSpace =
629 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
630 ? DL.getProgramAddressSpace()
631 : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace);
632 return Builder.getPointerType(PointerSize, llvm::Align(Alignment.value() / 8),
643void QualTypeMapper::computeFieldInfo(
644 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
645 const ASTRecordLayout &Layout) {
646 unsigned FieldIndex = 0;
648 for (
const auto *FD : RD->fields()) {
649 const llvm::abi::Type *FieldType =
convertType(FD->getType());
650 uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
652 bool IsBitField = FD->isBitField();
654 bool IsUnnamedBitField =
false;
657 BitFieldWidth = FD->getBitWidthValue();
658 IsUnnamedBitField = FD->isUnnamedBitField();
661 bool HasNoUniqueAddress = FD->hasAttr<NoUniqueAddressAttr>();
662 Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth,
663 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'.
const llvm::abi::Type * convertType(clang::QualType QT)
Main entry point for converting Clang QualType to LLVM ABI Type.
A (possibly-)qualified type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
bool hasFlexibleArrayMember() const
bool isMemberFunctionPointerType() const
TypeClass getTypeClass() const
Defines the clang::TargetInfo interface.
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)