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 case Type::BlockPointer:
129 return createPointerTypeForPointee(ASTCtx.
VoidPtrTy);
130 case Type::ConstantMatrix: {
132 return Builder.getArrayType(
convertType(MT->getElementType()),
133 MT->getNumRows() * MT->getNumColumns(),
136 case Type::MemberPointer:
140 return Builder.getIntegerType(BIT->getNumBits(), getTypeAlign(QT),
144 case Type::ObjCObject:
145 case Type::ObjCInterface:
146 case Type::ObjCObjectPointer:
148 return Builder.getPointerType(
153 case Type::OverflowBehavior:
156 case Type::DeducedTemplateSpecialization:
157 case Type::FunctionProto:
158 case Type::FunctionNoProto:
159 case Type::HLSLAttributedResource:
160 case Type::HLSLInlineSpirv:
161 llvm::reportFatalInternalError(
"Type not supported in ABI lowering");
163 llvm_unreachable(
"unhandled type class in convertTypeImpl");
169const llvm::abi::Type *
170QualTypeMapper::convertBuiltinType(
const BuiltinType *BT) {
173 switch (BT->getKind()) {
174 case BuiltinType::Void:
175 return Builder.getVoidType();
177 case BuiltinType::NullPtr:
178 return createPointerTypeForPointee(QT);
180 case BuiltinType::Bool:
181 return Builder.getIntegerType(1, getTypeAlign(QT),
false,
184 case BuiltinType::Char_S:
185 case BuiltinType::Char_U:
186 case BuiltinType::SChar:
187 case BuiltinType::UChar:
188 case BuiltinType::WChar_S:
189 case BuiltinType::WChar_U:
190 case BuiltinType::Char8:
191 case BuiltinType::Char16:
192 case BuiltinType::Char32:
193 case BuiltinType::Short:
194 case BuiltinType::UShort:
195 case BuiltinType::Int:
196 case BuiltinType::UInt:
197 case BuiltinType::Long:
198 case BuiltinType::ULong:
199 case BuiltinType::LongLong:
200 case BuiltinType::ULongLong:
201 case BuiltinType::Int128:
202 case BuiltinType::UInt128:
203 return Builder.getIntegerType(ASTCtx.getTypeSize(QT), getTypeAlign(QT),
204 BT->isSignedInteger(),
207 case BuiltinType::Half:
208 case BuiltinType::Float16:
209 case BuiltinType::BFloat16:
210 case BuiltinType::Float:
211 case BuiltinType::Double:
212 case BuiltinType::LongDouble:
213 case BuiltinType::Float128:
214 return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QT),
218 case BuiltinType::Ibm128:
219 llvm::reportFatalInternalError(
220 "IBM128 is not yet supported in the ABI lowering libary");
223 case BuiltinType::ShortAccum:
224 case BuiltinType::Accum:
225 case BuiltinType::LongAccum:
226 case BuiltinType::UShortAccum:
227 case BuiltinType::UAccum:
228 case BuiltinType::ULongAccum:
229 case BuiltinType::ShortFract:
230 case BuiltinType::Fract:
231 case BuiltinType::LongFract:
232 case BuiltinType::UShortFract:
233 case BuiltinType::UFract:
234 case BuiltinType::ULongFract:
235 case BuiltinType::SatShortAccum:
236 case BuiltinType::SatAccum:
237 case BuiltinType::SatLongAccum:
238 case BuiltinType::SatUShortAccum:
239 case BuiltinType::SatUAccum:
240 case BuiltinType::SatULongAccum:
241 case BuiltinType::SatShortFract:
242 case BuiltinType::SatFract:
243 case BuiltinType::SatLongFract:
244 case BuiltinType::SatUShortFract:
245 case BuiltinType::SatUFract:
246 case BuiltinType::SatULongFract:
247 llvm::reportFatalInternalError(
248 "Fixed Point types not yet implemented in the ABI lowering library");
251#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
252 case BuiltinType::Id:
253#include "clang/Basic/OpenCLImageTypes.def"
255#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
256#include "clang/Basic/OpenCLExtensionTypes.def"
257 case BuiltinType::OCLSampler:
258 case BuiltinType::OCLEvent:
259 case BuiltinType::OCLClkEvent:
260 case BuiltinType::OCLQueue:
261 case BuiltinType::OCLReserveID:
262 return createPointerTypeForPointee(QT);
265 case BuiltinType::ObjCId:
266 case BuiltinType::ObjCClass:
267 case BuiltinType::ObjCSel:
268 return createPointerTypeForPointee(QT);
271#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
272 case BuiltinType::Id:
273#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
274 case BuiltinType::Id:
275#include "clang/Basic/AArch64ACLETypes.def"
276 return convertSVEBuiltinType(BT);
278 case BuiltinType::SveCount:
279 return Builder.getSVECountType(getTypeAlign(QT));
286 case BuiltinType::MFloat8:
287 llvm::reportFatalInternalError(
288 "__mfp8 is not yet supported in the ABI lowering library");
291#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
292#include "clang/Basic/PPCTypes.def"
293 llvm::reportFatalInternalError(
294 "PPC MMA types not yet supported in ABI lowering library");
295#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
296#include "clang/Basic/RISCVVTypes.def"
297 llvm::reportFatalInternalError(
298 "RISC-V vector types not yet supported in ABI lowering library");
299#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
300#include "clang/Basic/WebAssemblyReferenceTypes.def"
301 llvm::reportFatalInternalError(
"WebAssembly reference types not yet "
302 "supported in ABI lowering library");
303#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
304#include "clang/Basic/AMDGPUTypes.def"
305 llvm::reportFatalInternalError(
306 "AMDGPU types not yet supported in ABI lowering library");
307#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
308#include "clang/Basic/HLSLIntangibleTypes.def"
309 llvm::reportFatalInternalError(
310 "HLSL intangible types not yet Supported in ABI lowering library");
311#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
312#include "clang/Basic/SPIRVTypes.def"
313 llvm::reportFatalInternalError(
314 "SPIR-V types not yet supported in ABI lowering library");
317#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
318#define BUILTIN_TYPE(Id, SingletonId)
319#include "clang/AST/BuiltinTypes.def"
320 llvm::reportFatalInternalError(
321 "Placeholder type should not reach ABI lowering");
323 case BuiltinType::Dependent:
324 llvm::reportFatalInternalError(
325 "Dependent builtin type should not reach ABI lowering");
327 llvm_unreachable(
"unhandled builtin type kind in convertBuiltinType");
336const llvm::abi::Type *
337QualTypeMapper::convertArrayType(
const clang::ArrayType *AT) {
341 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
342 auto NumElements = CAT->getZExtSize();
343 return Builder.getArrayType(ElementType, NumElements, Size);
346 return Builder.getArrayType(ElementType, 0, 0);
347 if (
const auto *VAT = dyn_cast<VariableArrayType>(AT))
348 return createPointerTypeForPointee(VAT->getPointeeType());
349 llvm::reportFatalInternalError(
350 "unexpected array type in ABI lowering (dependent array types should be "
351 "resolved before reaching this point)");
354const llvm::abi::Type *QualTypeMapper::convertVectorType(
const VectorType *VT) {
355 const llvm::abi::Type *ElementType =
convertType(VT->getElementType());
356 QualType VectorQualType(VT, 0);
358 unsigned NElems = VT->getNumElements();
359 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
360 llvm::Align VectorAlign = getTypeAlign(VectorQualType);
366 return Builder.getVectorType(ElementType, NumElements, VectorAlign,
376const llvm::abi::Type *
377QualTypeMapper::convertSVEBuiltinType(
const BuiltinType *BT) {
378 ASTContext::BuiltinVectorTypeInfo Info = ASTCtx.getBuiltinVectorTypeInfo(BT);
380 "Expected 1, 2, 3 or 4 vectors!");
385 const llvm::abi::Type *ElementType =
387 ? Builder.getIntegerType(8, llvm::Align(1),
false)
391 ? llvm::abi::VectorKind::SVEPredicate
392 : llvm::abi::VectorKind::SVEData;
394 const llvm::abi::VectorType *VecTy = Builder.getVectorType(
395 ElementType, Info.
EC, getTypeAlign(QualType(BT, 0)), VecKind);
398 return Builder.getTupleType(VecTy, Info.
NumVectors);
407const llvm::abi::Type *
408QualTypeMapper::convertComplexType(
const ComplexType *CT) {
409 const llvm::abi::Type *ElementType =
convertType(CT->getElementType());
410 llvm::Align ComplexAlign = getTypeAlign(QualType(CT, 0));
412 return Builder.getComplexType(ElementType, ComplexAlign);
421const llvm::abi::Type *
422QualTypeMapper::convertMemberPointerType(
const clang::MemberPointerType *MPT) {
425 llvm::Align Align = getTypeAlign(QT);
429 return Builder.getMemberPointerType(IsFunctionPointer, Size, Align);
438const llvm::abi::Type *QualTypeMapper::convertRecordType(
const RecordType *RT) {
439 const RecordDecl *RD = RT->getDecl()->getDefinition();
441 return Builder.getRecordType({}, llvm::TypeSize::getFixed(0),
445 return convertUnionType(RD);
448 auto *CXXRd = dyn_cast<CXXRecordDecl>(RD);
449 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
450 return convertCXXRecordType(CXXRd);
451 return convertStructType(RD);
462const llvm::abi::RecordType *
463QualTypeMapper::convertCXXRecordType(
const CXXRecordDecl *RD) {
464 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
465 SmallVector<llvm::abi::FieldInfo, 16> Fields;
466 SmallVector<llvm::abi::FieldInfo, 8> BaseClasses;
467 SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses;
470 if (RD->isPolymorphic()) {
471 const llvm::abi::Type *VtablePointer =
472 createPointerTypeForPointee(ASTCtx.VoidPtrTy);
473 Fields.emplace_back(VtablePointer, 0);
476 for (
const auto &Base : RD->bases()) {
477 if (
Base.isVirtual())
480 const RecordType *BaseRT =
Base.getType()->castAs<RecordType>();
483 Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
485 BaseClasses.emplace_back(BaseType, BaseOffset);
488 for (
const auto &VBase : RD->vbases()) {
489 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
490 const llvm::abi::Type *VBaseType =
convertType(VBase.getType());
492 Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
495 VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset);
498 computeFieldInfo(RD, Fields, Layout);
501 [](
const llvm::abi::FieldInfo &A,
const llvm::abi::FieldInfo &B) {
502 return A.OffsetInBits < B.OffsetInBits;
505 llvm::TypeSize
Size =
506 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
507 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
509 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
510 if (RD->isPolymorphic())
511 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
512 if (RD->canPassInRegisters())
513 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
514 if (RD->hasFlexibleArrayMember())
515 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
517 return Builder.getRecordType(Fields, Size, Alignment,
518 llvm::abi::StructPacking::Default, BaseClasses,
519 VirtualBaseClasses, RecFlags);
528const llvm::abi::Type *
529QualTypeMapper::convertEnumType(
const clang::EnumType *ET) {
530 const EnumDecl *ED = ET->getDecl();
531 QualType UnderlyingType = ED->getIntegerType();
533 if (UnderlyingType.isNull())
534 UnderlyingType = ASTCtx.IntTy;
545const llvm::abi::RecordType *
546QualTypeMapper::convertStructType(
const clang::RecordDecl *RD) {
547 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
550 SmallVector<llvm::abi::FieldInfo, 16> Fields;
551 computeFieldInfo(RD, Fields, Layout);
553 llvm::TypeSize
Size =
554 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
555 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
557 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
559 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
561 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
563 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
565 return Builder.getRecordType(Fields, Size, Alignment,
566 llvm::abi::StructPacking::Default, {}, {},
576const llvm::abi::RecordType *
577QualTypeMapper::convertUnionType(
const clang::RecordDecl *RD) {
578 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
580 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
581 computeFieldInfo(RD, AllFields, Layout);
583 llvm::TypeSize
Size =
584 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
585 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
587 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
588 if (RD->
hasAttr<TransparentUnionAttr>())
589 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
591 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
593 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
595 return Builder.getUnionType(AllFields, Size, Alignment,
596 llvm::abi::StructPacking::Default, RecFlags);
599llvm::Align QualTypeMapper::getTypeAlign(QualType QT)
const {
601 return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity());
604const llvm::abi::Type *
605QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
606 auto AddrSpace = PointeeType.getAddressSpace();
607 auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
608 llvm::Align Alignment =
609 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
613 unsigned TargetAddrSpace =
614 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
615 ? DL.getProgramAddressSpace()
616 : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace);
617 return Builder.getPointerType(PointerSize, llvm::Align(Alignment.value() / 8),
628void QualTypeMapper::computeFieldInfo(
629 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
630 const ASTRecordLayout &Layout) {
631 unsigned FieldIndex = 0;
633 for (
const auto *FD : RD->fields()) {
634 const llvm::abi::Type *FieldType =
convertType(FD->getType());
635 uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
637 bool IsBitField = FD->isBitField();
639 bool IsUnnamedBitField =
false;
642 BitFieldWidth = FD->getBitWidthValue();
643 IsUnnamedBitField = FD->isUnnamedBitField();
646 bool HasNoUniqueAddress = FD->hasAttr<NoUniqueAddressAttr>();
647 Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth,
648 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.
const TargetInfo & getTargetInfo() const
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
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
unsigned getTargetAddressSpace(LangAS AS) const
uint64_t getPointerAlign(LangAS AddrSpace) 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)