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");
272#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
273#define BUILTIN_TYPE(Id, SingletonId)
274#include "clang/AST/BuiltinTypes.def"
275 llvm::reportFatalInternalError(
276 "Placeholder type should not reach ABI lowering");
278 case BuiltinType::Dependent:
279 llvm::reportFatalInternalError(
280 "Dependent builtin type should not reach ABI lowering");
282 llvm_unreachable(
"unhandled builtin type kind in convertBuiltinType");
291const llvm::abi::Type *
292QualTypeMapper::convertArrayType(
const clang::ArrayType *AT) {
296 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
297 auto NumElements = CAT->getZExtSize();
298 return Builder.getArrayType(ElementType, NumElements, Size);
301 return Builder.getArrayType(ElementType, 0, 0);
302 if (
const auto *VAT = dyn_cast<VariableArrayType>(AT))
303 return createPointerTypeForPointee(VAT->getPointeeType());
304 llvm::reportFatalInternalError(
305 "unexpected array type in ABI lowering (dependent array types should be "
306 "resolved before reaching this point)");
309const llvm::abi::Type *QualTypeMapper::convertVectorType(
const VectorType *VT) {
310 const llvm::abi::Type *ElementType =
convertType(VT->getElementType());
311 QualType VectorQualType(VT, 0);
313 unsigned NElems = VT->getNumElements();
314 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
315 llvm::Align VectorAlign = getTypeAlign(VectorQualType);
317 return Builder.getVectorType(ElementType, NumElements, VectorAlign);
326const llvm::abi::Type *
327QualTypeMapper::convertComplexType(
const ComplexType *CT) {
328 const llvm::abi::Type *ElementType =
convertType(CT->getElementType());
329 llvm::Align ComplexAlign = getTypeAlign(QualType(CT, 0));
331 return Builder.getComplexType(ElementType, ComplexAlign);
340const llvm::abi::Type *
341QualTypeMapper::convertMemberPointerType(
const clang::MemberPointerType *MPT) {
344 llvm::Align Align = getTypeAlign(QT);
348 return Builder.getMemberPointerType(IsFunctionPointer, Size, Align);
357const llvm::abi::Type *QualTypeMapper::convertRecordType(
const RecordType *RT) {
358 const RecordDecl *RD = RT->getDecl()->getDefinition();
360 return Builder.getRecordType({}, llvm::TypeSize::getFixed(0),
364 return convertUnionType(RD);
367 auto *CXXRd = dyn_cast<CXXRecordDecl>(RD);
368 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
369 return convertCXXRecordType(CXXRd);
370 return convertStructType(RD);
381const llvm::abi::RecordType *
382QualTypeMapper::convertCXXRecordType(
const CXXRecordDecl *RD) {
383 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
384 SmallVector<llvm::abi::FieldInfo, 16> Fields;
385 SmallVector<llvm::abi::FieldInfo, 8> BaseClasses;
386 SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses;
389 if (RD->isPolymorphic()) {
390 const llvm::abi::Type *VtablePointer =
391 createPointerTypeForPointee(ASTCtx.VoidPtrTy);
392 Fields.emplace_back(VtablePointer, 0);
395 for (
const auto &Base : RD->bases()) {
396 if (
Base.isVirtual())
399 const RecordType *BaseRT =
Base.getType()->castAs<RecordType>();
402 Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
405 BaseClasses.emplace_back(BaseType, BaseOffset);
408 for (
const auto &VBase : RD->vbases()) {
409 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
410 const llvm::abi::Type *VBaseType =
convertType(VBase.getType());
412 Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
416 VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset);
419 computeFieldInfo(RD, Fields, Layout);
422 [](
const llvm::abi::FieldInfo &A,
const llvm::abi::FieldInfo &B) {
423 return A.OffsetInBits < B.OffsetInBits;
426 llvm::TypeSize
Size =
427 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
428 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
430 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
431 if (RD->isPolymorphic())
432 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
433 if (RD->canPassInRegisters())
434 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
435 if (RD->hasFlexibleArrayMember())
436 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
438 return Builder.getRecordType(Fields, Size, Alignment,
439 llvm::abi::StructPacking::Default, BaseClasses,
440 VirtualBaseClasses, RecFlags);
449const llvm::abi::Type *
450QualTypeMapper::convertEnumType(
const clang::EnumType *ET) {
451 const EnumDecl *ED = ET->getDecl();
452 QualType UnderlyingType = ED->getIntegerType();
454 if (UnderlyingType.isNull())
455 UnderlyingType = ASTCtx.IntTy;
466const llvm::abi::RecordType *
467QualTypeMapper::convertStructType(
const clang::RecordDecl *RD) {
468 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
471 SmallVector<llvm::abi::FieldInfo, 16> Fields;
472 computeFieldInfo(RD, Fields, Layout);
474 llvm::TypeSize
Size =
475 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
476 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
478 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
480 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
482 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
484 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
486 return Builder.getRecordType(Fields, Size, Alignment,
487 llvm::abi::StructPacking::Default, {}, {},
497const llvm::abi::RecordType *
498QualTypeMapper::convertUnionType(
const clang::RecordDecl *RD) {
499 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
501 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
502 computeFieldInfo(RD, AllFields, Layout);
504 llvm::TypeSize
Size =
505 llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
506 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
508 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
509 if (RD->
hasAttr<TransparentUnionAttr>())
510 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
512 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
514 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
516 return Builder.getUnionType(AllFields, Size, Alignment,
517 llvm::abi::StructPacking::Default, RecFlags);
520llvm::Align QualTypeMapper::getTypeAlign(QualType QT)
const {
522 return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity());
525const llvm::abi::Type *
526QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
527 auto AddrSpace = PointeeType.getAddressSpace();
528 auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
529 llvm::Align Alignment =
530 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
534 unsigned TargetAddrSpace =
535 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
536 ? DL.getProgramAddressSpace()
537 : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace);
538 return Builder.getPointerType(PointerSize, llvm::Align(Alignment.value() / 8),
549void QualTypeMapper::computeFieldInfo(
550 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
551 const ASTRecordLayout &Layout) {
552 unsigned FieldIndex = 0;
554 for (
const auto *FD : RD->fields()) {
555 const llvm::abi::Type *FieldType =
convertType(FD->getType());
556 uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
558 bool IsBitField = FD->isBitField();
560 bool IsUnnamedBitField =
false;
563 BitFieldWidth = FD->getBitWidthValue();
564 IsUnnamedBitField = FD->isUnnamedBitField();
567 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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)