28#include "llvm/ABI/Types.h"
29#include "llvm/Support/Alignment.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/TypeSize.h"
54 auto It = TypeCache.find(QT);
55 if (It != TypeCache.end())
58 const llvm::abi::Type *
Result = convertTypeImpl(QT);
59 assert(
Result &&
"convertTypeImpl returned nullptr");
65const llvm::abi::Type *QualTypeMapper::convertTypeImpl(
QualType QT) {
69#define TYPE(Class, Base)
70#define ABSTRACT_TYPE(Class, Base)
71#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
72#define DEPENDENT_TYPE(Class, Base) case Type::Class:
73#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
74#include "clang/AST/TypeNodes.inc"
75 llvm::reportFatalInternalError(
76 "Non-canonical or dependent types should not reach ABI lowering");
82 case Type::LValueReference:
83 case Type::RValueReference:
84 return createPointerTypeForPointee(
86 case Type::ConstantArray:
87 case Type::ArrayParameter:
88 case Type::IncompleteArray:
89 case Type::VariableArray:
102 case Type::BlockPointer:
104 return createPointerTypeForPointee(ASTCtx.
VoidPtrTy);
105 case Type::ConstantMatrix: {
107 return Builder.getArrayType(
convertType(MT->getElementType()),
108 MT->getNumRows() * MT->getNumColumns(),
111 case Type::MemberPointer:
115 return Builder.getIntegerType(BIT->getNumBits(), getTypeAlign(QT),
119 case Type::ObjCObject:
120 case Type::ObjCInterface:
121 case Type::ObjCObjectPointer:
123 return Builder.getPointerType(
128 case Type::OverflowBehavior:
131 case Type::DeducedTemplateSpecialization:
132 case Type::FunctionProto:
133 case Type::FunctionNoProto:
134 case Type::HLSLAttributedResource:
135 case Type::HLSLInlineSpirv:
136 llvm::reportFatalInternalError(
"Type not supported in ABI lowering");
138 llvm_unreachable(
"unhandled type class in convertTypeImpl");
144const llvm::abi::Type *
145QualTypeMapper::convertBuiltinType(
const BuiltinType *BT) {
148 switch (BT->getKind()) {
149 case BuiltinType::Void:
150 return Builder.getVoidType();
152 case BuiltinType::NullPtr:
153 return createPointerTypeForPointee(QT);
155 case BuiltinType::Bool:
156 return Builder.getIntegerType(1, getTypeAlign(QT),
false,
159 case BuiltinType::Char_S:
160 case BuiltinType::Char_U:
161 case BuiltinType::SChar:
162 case BuiltinType::UChar:
163 case BuiltinType::WChar_S:
164 case BuiltinType::WChar_U:
165 case BuiltinType::Char8:
166 case BuiltinType::Char16:
167 case BuiltinType::Char32:
168 case BuiltinType::Short:
169 case BuiltinType::UShort:
170 case BuiltinType::Int:
171 case BuiltinType::UInt:
172 case BuiltinType::Long:
173 case BuiltinType::ULong:
174 case BuiltinType::LongLong:
175 case BuiltinType::ULongLong:
176 case BuiltinType::Int128:
177 case BuiltinType::UInt128:
178 return Builder.getIntegerType(ASTCtx.getTypeSize(QT), getTypeAlign(QT),
179 BT->isSignedInteger(),
182 case BuiltinType::Half:
183 case BuiltinType::Float16:
184 case BuiltinType::BFloat16:
185 case BuiltinType::Float:
186 case BuiltinType::Double:
187 case BuiltinType::LongDouble:
188 case BuiltinType::Float128:
189 return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QT),
193 case BuiltinType::Ibm128:
194 llvm::reportFatalInternalError(
195 "IBM128 is not yet supported in the ABI lowering libary");
198 case BuiltinType::ShortAccum:
199 case BuiltinType::Accum:
200 case BuiltinType::LongAccum:
201 case BuiltinType::UShortAccum:
202 case BuiltinType::UAccum:
203 case BuiltinType::ULongAccum:
204 case BuiltinType::ShortFract:
205 case BuiltinType::Fract:
206 case BuiltinType::LongFract:
207 case BuiltinType::UShortFract:
208 case BuiltinType::UFract:
209 case BuiltinType::ULongFract:
210 case BuiltinType::SatShortAccum:
211 case BuiltinType::SatAccum:
212 case BuiltinType::SatLongAccum:
213 case BuiltinType::SatUShortAccum:
214 case BuiltinType::SatUAccum:
215 case BuiltinType::SatULongAccum:
216 case BuiltinType::SatShortFract:
217 case BuiltinType::SatFract:
218 case BuiltinType::SatLongFract:
219 case BuiltinType::SatUShortFract:
220 case BuiltinType::SatUFract:
221 case BuiltinType::SatULongFract:
222 llvm::reportFatalInternalError(
223 "Fixed Point types not yet implemented in the ABI lowering library");
226#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
227 case BuiltinType::Id:
228#include "clang/Basic/OpenCLImageTypes.def"
230#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
231#include "clang/Basic/OpenCLExtensionTypes.def"
232 case BuiltinType::OCLSampler:
233 case BuiltinType::OCLEvent:
234 case BuiltinType::OCLClkEvent:
235 case BuiltinType::OCLQueue:
236 case BuiltinType::OCLReserveID:
237 return createPointerTypeForPointee(QT);
240 case BuiltinType::ObjCId:
241 case BuiltinType::ObjCClass:
242 case BuiltinType::ObjCSel:
243 return createPointerTypeForPointee(QT);
246#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
247#include "clang/Basic/AArch64ACLETypes.def"
248 llvm::reportFatalInternalError(
249 "AArch64 SVE types not yet supported in ABI lowering library");
250#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
251#include "clang/Basic/PPCTypes.def"
252 llvm::reportFatalInternalError(
253 "PPC MMA types not yet supported in ABI lowering library");
254#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
255#include "clang/Basic/RISCVVTypes.def"
256 llvm::reportFatalInternalError(
257 "RISC-V vector types not yet supported in ABI lowering library");
258#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
259#include "clang/Basic/WebAssemblyReferenceTypes.def"
260 llvm::reportFatalInternalError(
"WebAssembly reference types not yet "
261 "supported in ABI lowering library");
262#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
263#include "clang/Basic/AMDGPUTypes.def"
264 llvm::reportFatalInternalError(
265 "AMDGPU types not yet supported in ABI lowering library");
266#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
267#include "clang/Basic/HLSLIntangibleTypes.def"
268 llvm::reportFatalInternalError(
269 "HLSL intangible types not yet Supported in ABI lowering library");
270#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
271#include "clang/Basic/SPIRVTypes.def"
272 llvm::reportFatalInternalError(
273 "SPIR-V types not yet supported in ABI lowering library");
276#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
277#define BUILTIN_TYPE(Id, SingletonId)
278#include "clang/AST/BuiltinTypes.def"
279 llvm::reportFatalInternalError(
280 "Placeholder type should not reach ABI lowering");
282 case BuiltinType::Dependent:
283 llvm::reportFatalInternalError(
284 "Dependent builtin type should not reach ABI lowering");
286 llvm_unreachable(
"unhandled builtin type kind in convertBuiltinType");
295const llvm::abi::Type *
296QualTypeMapper::convertArrayType(
const clang::ArrayType *AT) {
300 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
301 auto NumElements = CAT->getZExtSize();
302 return Builder.getArrayType(ElementType, NumElements, Size);
305 return Builder.getArrayType(ElementType, 0, 0);
306 if (
const auto *VAT = dyn_cast<VariableArrayType>(AT))
307 return createPointerTypeForPointee(VAT->getPointeeType());
308 llvm::reportFatalInternalError(
309 "unexpected array type in ABI lowering (dependent array types should be "
310 "resolved before reaching this point)");
313const llvm::abi::Type *QualTypeMapper::convertVectorType(
const VectorType *VT) {
314 const llvm::abi::Type *ElementType =
convertType(VT->getElementType());
315 QualType VectorQualType(VT, 0);
317 unsigned NElems = VT->getNumElements();
318 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
319 llvm::Align VectorAlign = getTypeAlign(VectorQualType);
321 return Builder.getVectorType(ElementType, NumElements, VectorAlign);
330const llvm::abi::Type *
331QualTypeMapper::convertComplexType(
const ComplexType *CT) {
332 const llvm::abi::Type *ElementType =
convertType(CT->getElementType());
333 llvm::Align ComplexAlign = getTypeAlign(QualType(CT, 0));
335 return Builder.getComplexType(ElementType, ComplexAlign);
344const llvm::abi::Type *
345QualTypeMapper::convertMemberPointerType(
const clang::MemberPointerType *MPT) {
348 llvm::Align Align = getTypeAlign(QT);
352 return Builder.getMemberPointerType(IsFunctionPointer, Size, Align);
361const llvm::abi::Type *QualTypeMapper::convertRecordType(
const RecordType *RT) {
362 const RecordDecl *RD = RT->getDecl()->getDefinition();
364 return Builder.getRecordType({}, llvm::TypeSize::getFixed(0),
368 return convertUnionType(RD);
371 auto *CXXRd = dyn_cast<CXXRecordDecl>(RD);
372 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
373 return convertCXXRecordType(CXXRd);
374 return convertStructType(RD);
385const llvm::abi::RecordType *
386QualTypeMapper::convertCXXRecordType(
const CXXRecordDecl *RD) {
387 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
388 SmallVector<llvm::abi::FieldInfo, 16> Fields;
389 SmallVector<llvm::abi::FieldInfo, 8> BaseClasses;
390 SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses;
393 if (RD->isPolymorphic()) {
394 const llvm::abi::Type *VtablePointer =
395 createPointerTypeForPointee(ASTCtx.VoidPtrTy);
396 Fields.emplace_back(VtablePointer, 0);
399 for (
const auto &Base : RD->bases()) {
400 if (
Base.isVirtual())
403 const RecordType *BaseRT =
Base.getType()->castAs<RecordType>();
406 Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
409 BaseClasses.emplace_back(BaseType, BaseOffset);
412 for (
const auto &VBase : RD->vbases()) {
413 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
414 const llvm::abi::Type *VBaseType =
convertType(VBase.getType());
416 Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
420 VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset);
423 computeFieldInfo(RD, Fields, Layout);
426 [](
const llvm::abi::FieldInfo &A,
const llvm::abi::FieldInfo &B) {
427 return A.OffsetInBits < B.OffsetInBits;
430 llvm::TypeSize
Size =
431 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
432 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
434 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
435 if (RD->isPolymorphic())
436 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
437 if (RD->canPassInRegisters())
438 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
439 if (RD->hasFlexibleArrayMember())
440 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
442 return Builder.getRecordType(Fields, Size, Alignment,
443 llvm::abi::StructPacking::Default, BaseClasses,
444 VirtualBaseClasses, RecFlags);
453const llvm::abi::Type *
454QualTypeMapper::convertEnumType(
const clang::EnumType *ET) {
455 const EnumDecl *ED = ET->getDecl();
456 QualType UnderlyingType = ED->getIntegerType();
458 if (UnderlyingType.isNull())
459 UnderlyingType = ASTCtx.IntTy;
470const llvm::abi::RecordType *
471QualTypeMapper::convertStructType(
const clang::RecordDecl *RD) {
472 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
475 SmallVector<llvm::abi::FieldInfo, 16> Fields;
476 computeFieldInfo(RD, Fields, Layout);
478 llvm::TypeSize
Size =
479 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
480 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
482 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
484 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
486 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
488 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
490 return Builder.getRecordType(Fields, Size, Alignment,
491 llvm::abi::StructPacking::Default, {}, {},
501const llvm::abi::RecordType *
502QualTypeMapper::convertUnionType(
const clang::RecordDecl *RD) {
503 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
505 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
506 computeFieldInfo(RD, AllFields, Layout);
508 llvm::TypeSize
Size =
509 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
510 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
512 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
513 if (RD->
hasAttr<TransparentUnionAttr>())
514 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
516 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
518 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
520 return Builder.getUnionType(AllFields, Size, Alignment,
521 llvm::abi::StructPacking::Default, RecFlags);
524llvm::Align QualTypeMapper::getTypeAlign(QualType QT)
const {
526 return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity());
529const llvm::abi::Type *
530QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
531 auto AddrSpace = PointeeType.getAddressSpace();
532 auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
533 llvm::Align Alignment =
534 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
538 unsigned TargetAddrSpace =
539 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
540 ? DL.getProgramAddressSpace()
541 : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace);
542 return Builder.getPointerType(PointerSize, llvm::Align(Alignment.value() / 8),
553void QualTypeMapper::computeFieldInfo(
554 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
555 const ASTRecordLayout &Layout) {
556 unsigned FieldIndex = 0;
558 for (
const auto *FD : RD->fields()) {
559 const llvm::abi::Type *FieldType =
convertType(FD->getType());
560 uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
562 bool IsBitField = FD->isBitField();
564 bool IsUnnamedBitField =
false;
567 BitFieldWidth = FD->getBitWidthValue();
568 IsUnnamedBitField = FD->isUnnamedBitField();
571 Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth,
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
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.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)