clang 24.0.0git
QualTypeMapper.cpp
Go to the documentation of this file.
1//==---- QualTypeMapper.cpp - Maps Clang QualType to LLVMABI Types ---------==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Maps Clang QualType instances to corresponding LLVM ABI type
11/// representations. This mapper translates high-level type information from the
12/// AST into low-level ABI-specific types that encode size, alignment, and
13/// layout details required for code generation and cross-language
14/// interoperability.
15///
16//===----------------------------------------------------------------------===//
17#include "QualTypeMapper.h"
19#include "clang/AST/ASTFwd.h"
20#include "clang/AST/Attr.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
24#include "clang/AST/Type.h"
26#include "clang/Basic/LLVM.h"
28#include "llvm/ABI/Types.h"
29#include "llvm/Support/Alignment.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/TypeSize.h"
32#include <cstdint>
33
34namespace clang {
35namespace CodeGen {
36
37/// Returns true if \p BT is one of the AArch64 SVE predicate types, i.e.
38/// svbool_t or one of its tuples.
39static bool isSVEPredicateBuiltinType(const BuiltinType *BT) {
40 switch (BT->getKind()) {
41#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
42 case BuiltinType::Id: \
43 return true;
44#include "clang/Basic/AArch64ACLETypes.def"
45 default:
46 return false;
47 }
48}
49
50/// Maps a Clang vector kind onto the ABI library's notion of a vector flavor.
51static llvm::abi::VectorKind getABIVectorKind(clang::VectorKind Kind) {
52 switch (Kind) {
54 return llvm::abi::VectorKind::SVEData;
56 return llvm::abi::VectorKind::SVEPredicate;
57 default:
58 return llvm::abi::VectorKind::Generic;
59 }
60}
61
62/// Main entry point for converting Clang QualType to LLVM ABI Type.
63/// This method performs type canonicalization, caching, and dispatches
64/// to specialized conversion methods based on the type kind.
65///
66/// \param QT The Clang QualType to convert
67/// \return Corresponding LLVM ABI Type representation
68const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
69 // Canonicalize type and strip qualifiers
70 // This ensures consistent type representation across different contexts
71 //
72 // TODO: AttributedType is NeverCanonical, so aligned typedef attributes
73 // for instance, __attribute__((aligned(N))) are lost here. Capture the
74 // effective alignment from the original QT and thread it through
75 // convertTypeImpl.
77
78 // Results are cached since type conversion may be expensive.
79 auto It = TypeCache.find(QT);
80 if (It != TypeCache.end())
81 return It->second;
82
83 const llvm::abi::Type *Result = convertTypeImpl(QT);
84 assert(Result && "convertTypeImpl returned nullptr");
85 TypeCache[QT] = Result;
86 return Result;
87}
88
89/// Dispatches to specialized conversion methods based on the type kind.
90const llvm::abi::Type *QualTypeMapper::convertTypeImpl(QualType QT) {
91 switch (QT->getTypeClass()) {
92 // Non-canonical and dependent types should have been stripped by
93 // getCanonicalType() above or cannot appear during code generation.
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");
102
103 case Type::Builtin:
104 return convertBuiltinType(cast<BuiltinType>(QT));
105 case Type::Pointer:
106 return createPointerTypeForPointee(cast<PointerType>(QT)->getPointeeType());
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:
115 return convertArrayType(cast<ArrayType>(QT));
116 case Type::Vector:
117 case Type::ExtVector:
118 return convertVectorType(cast<VectorType>(QT));
119 case Type::Record:
120 return convertRecordType(cast<RecordType>(QT));
121 case Type::Enum:
122 return convertEnumType(cast<EnumType>(QT));
123 case Type::Complex:
124 return convertComplexType(cast<ComplexType>(QT));
125 case Type::Atomic: {
126 const auto *AT = cast<AtomicType>(QT);
127 return Builder.getAtomicType(convertType(AT->getValueType()),
128 ASTCtx.getTypeSize(QT), getTypeAlign(QT));
129 }
130 case Type::BlockPointer:
131 case Type::Pipe:
132 return createPointerTypeForPointee(ASTCtx.VoidPtrTy);
133 case Type::ConstantMatrix: {
134 const auto *MT = cast<ConstantMatrixType>(QT);
135 return Builder.getArrayType(convertType(MT->getElementType()),
136 MT->getNumRows() * MT->getNumColumns(),
137 ASTCtx.getTypeSize(QT), /*IsMatrixType=*/true);
138 }
139 case Type::MemberPointer:
140 return convertMemberPointerType(cast<MemberPointerType>(QT));
141 case Type::BitInt: {
142 const auto *BIT = cast<BitIntType>(QT);
143 return Builder.getIntegerType(BIT->getNumBits(), getTypeAlign(QT),
144 /*Signed=*/BIT->isSigned(),
145 /*IsBitInt=*/true);
146 }
147 case Type::ObjCObject:
148 case Type::ObjCInterface:
149 case Type::ObjCObjectPointer:
150 // Objective-C objects are represented as pointers in the ABI. Clang lowers
151 // them to a pointer in address space 0.
152 return Builder.getPointerType(
153 ASTCtx.getTargetInfo().getPointerWidth(LangAS::Default),
154 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(LangAS::Default) /
155 8));
156 case Type::OverflowBehavior:
158 case Type::Auto:
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");
165 }
166 llvm_unreachable("unhandled type class in convertTypeImpl");
167}
168
169/// Converts C/C++ builtin types to LLVM ABI types.
170/// This handles all fundamental scalar types including integers, floats,
171/// and special types like void and bool.
172const llvm::abi::Type *
173QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
174 QualType QT(BT, 0);
175
176 switch (BT->getKind()) {
177 case BuiltinType::Void:
178 return Builder.getVoidType();
179
180 case BuiltinType::NullPtr:
181 // Clang lowers std::nullptr_t to a pointer in address space 0.
182 return Builder.getPointerType(
183 ASTCtx.getTargetInfo().getPointerWidth(LangAS::Default),
184 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(LangAS::Default) /
185 8));
186
187 case BuiltinType::Bool:
188 return Builder.getIntegerType(1, getTypeAlign(QT), /*Signed=*/false,
189 /*IsBitInt=*/false);
190
191 case BuiltinType::MetaInfo:
192 llvm::reportFatalInternalError("std::meta::info is consteval-only type");
193
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 /*Signed=*/BT->isSignedInteger(),
215 /*IsBitInt=*/false);
216
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),
225 getTypeAlign(QT));
226
227 // TODO: IBM 128-bit extended double
228 case BuiltinType::Ibm128:
229 llvm::reportFatalInternalError(
230 "IBM128 is not yet supported in the ABI lowering libary");
231
232 // TODO: Fixed-point types
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");
259
260 // OpenCL image types are represented as opaque pointers.
261#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
262 case BuiltinType::Id:
263#include "clang/Basic/OpenCLImageTypes.def"
264 // OpenCL extension types are represented as opaque pointers.
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);
273
274 // Objective-C builtin types are represented as opaque pointers.
275 case BuiltinType::ObjCId:
276 case BuiltinType::ObjCClass:
277 case BuiltinType::ObjCSel:
278 return createPointerTypeForPointee(QT);
279
280 // AArch64 SVE data and predicate types, including the x2/x3/x4 tuples.
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);
287
288 case BuiltinType::SveCount:
289 return Builder.getScalablePredicateOrCountVectorType(
290 getTypeAlign(QT), llvm::abi::VectorKind::SVECount);
291
292 // __mfp8 is an opaque 8-bit float. Vector elements stay 8-bit
293 // integers, which is also their representation in LLVM IR.
294 case BuiltinType::MFloat8:
295 return Builder.getOpaqueFloat8Type(getTypeAlign(QT));
296
297 // Target-specific vector/matrix types — not yet implemented.
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");
326
327 // Placeholder types should never reach ABI lowering.
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");
333
334 case BuiltinType::Dependent:
335 llvm::reportFatalInternalError(
336 "Dependent builtin type should not reach ABI lowering");
337 }
338 llvm_unreachable("unhandled builtin type kind in convertBuiltinType");
339}
340
341/// Converts array types to LLVM ABI array representations.
342/// Handles different array kinds: constant arrays, incomplete arrays,
343/// and variable-length arrays.
344///
345/// \param AT The ArrayType to convert
346/// \return LLVM ABI ArrayType or PointerType
347const llvm::abi::Type *
348QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
349 const llvm::abi::Type *ElementType = convertType(AT->getElementType());
350 uint64_t Size = ASTCtx.getTypeSize(AT);
351
352 if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
353 auto NumElements = CAT->getZExtSize();
354 return Builder.getArrayType(ElementType, NumElements, Size);
355 }
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)");
363}
364
365const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) {
366 // Vectors of __mfp8 are stored as 8-bit integers. The scalar type is
367 // mapped separately as an opaque float.
368 const llvm::abi::Type *ElementType =
369 VT->getElementType()->isMFloat8Type()
370 ? Builder.getIntegerType(8, llvm::Align(1), /*Signed=*/false)
371 : convertType(VT->getElementType());
372 QualType VectorQualType(VT, 0);
373
374 unsigned NElems = VT->getNumElements();
375 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
376 llvm::Align VectorAlign = getTypeAlign(VectorQualType);
377
378 // SveFixedLengthPredicate is tagged SVEPredicate, like sizeless svbool_t.
379 // The element type is left as the AST unsigned char (i8). The builtin path
380 // below maps sizeless predicates to i1. Both match the Clang AST, but
381 // consumers that key only off VectorKind cannot assume a 1-bit element.
382 return Builder.getVectorType(ElementType, NumElements, VectorAlign,
383 getABIVectorKind(VT->getVectorKind()));
384}
385
386/// Converts the sizeless AArch64 SVE data and predicate builtin types.
387/// Single vectors become a scalable LLVM ABI VectorType. The x2/x3/x4
388/// forms become a TupleType of that vector.
389///
390/// \param BT The SVE BuiltinType to convert
391/// \return LLVM ABI VectorType or TupleType
392const llvm::abi::Type *
393QualTypeMapper::convertSVEBuiltinType(const BuiltinType *BT) {
394 ASTContext::BuiltinVectorTypeInfo Info = ASTCtx.getBuiltinVectorTypeInfo(BT);
395 assert(Info.NumVectors > 0 && Info.NumVectors <= 4 &&
396 "Expected 1, 2, 3 or 4 vectors!");
397
398 // __mfp8 carries no floating-point semantics, so mfloat8 vectors use an
399 // 8-bit integer element type, which is also how they are represented in
400 // LLVM IR.
401 const llvm::abi::Type *ElementType =
402 Info.ElementType->isMFloat8Type()
403 ? Builder.getIntegerType(8, llvm::Align(1), /*Signed=*/false)
404 : convertType(Info.ElementType);
405
406 llvm::abi::VectorKind VecKind = isSVEPredicateBuiltinType(BT)
407 ? llvm::abi::VectorKind::SVEPredicate
408 : llvm::abi::VectorKind::SVEData;
409
410 const llvm::abi::VectorType *VecTy = Builder.getVectorType(
411 ElementType, Info.EC, getTypeAlign(QualType(BT, 0)), VecKind);
412 if (Info.NumVectors == 1)
413 return VecTy;
414 return Builder.getTupleType(VecTy, Info.NumVectors);
415}
416
417/// Converts complex types to LLVM ABI complex representations.
418/// Complex types consist of two components of the element type
419/// (real and imaginary parts).
420///
421/// \param CT The ComplexType to convert
422/// \return LLVM ABI ComplexType with element type and alignment
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));
427
428 return Builder.getComplexType(ElementType, ComplexAlign);
429}
430
431/// Converts member pointer types to LLVM ABI representations.
432/// Member pointers have different layouts depending on whether they
433/// point to functions or data members.
434///
435/// \param MPT The MemberPointerType to convert
436/// \return LLVM ABI MemberPointerType
437const llvm::abi::Type *
438QualTypeMapper::convertMemberPointerType(const clang::MemberPointerType *MPT) {
439 QualType QT(MPT, 0);
440 uint64_t Size = ASTCtx.getTypeSize(QT);
441 llvm::Align Align = getTypeAlign(QT);
442
443 bool IsFunctionPointer = MPT->isMemberFunctionPointerType();
444
445 return Builder.getMemberPointerType(IsFunctionPointer, Size, Align);
446}
447
448/// Returns the record flags that describe C++ class properties of \p RD.
449static llvm::abi::RecordFlags getCXXRecordFlags(const CXXRecordDecl *RD) {
450 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
451 if (RD->isPolymorphic())
452 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
453 if (RD->isEmpty())
454 RecFlags |= llvm::abi::RecordFlags::IsCXXEmpty;
456 RecFlags |= llvm::abi::RecordFlags::HasNonTrivialCopyAssignment;
457 if (RD->hasNonTrivialDestructor())
458 RecFlags |= llvm::abi::RecordFlags::HasNonTrivialDestructor;
460 RecFlags |= llvm::abi::RecordFlags::HasNonTrivialDefaultConstructor;
461 return RecFlags;
462}
463
464/// Converts record types (struct/class/union) to LLVM ABI representations.
465/// This is the main dispatch method that handles different record kinds
466/// and delegates to specialized converters.
467///
468/// \param RT The RecordType to convert
469/// \return LLVM ABI RecordType
470const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) {
471 const RecordDecl *RD = RT->getDecl()->getDefinition();
472 if (!RD)
473 return Builder.getRecordType({}, llvm::TypeSize::getFixed(0),
474 llvm::Align(1),
475 /*UnadjustedAlign=*/llvm::Align(1));
476
477 if (RD->isUnion())
478 return convertUnionType(RD);
479
480 // Handle C++ classes with base classes
481 auto *CXXRd = dyn_cast<CXXRecordDecl>(RD);
482 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
483 return convertCXXRecordType(CXXRd);
484 return convertStructType(RD);
485}
486
487/// Converts C++ classes with inheritance to LLVM ABI struct representations.
488/// This method handles the complex layout of C++ objects including:
489/// - Virtual table pointers for polymorphic classes
490/// - Base class subobjects (both direct and virtual bases)
491/// - Member field layout with proper offsets
492///
493/// \param RD The C++ record declaration
494/// \return LLVM ABI RecordType representing the complete object layout
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;
501
502 // Add vtable pointer for polymorphic classes
503 if (RD->isPolymorphic()) {
504 const llvm::abi::Type *VtablePointer =
505 createPointerTypeForPointee(ASTCtx.VoidPtrTy);
506 Fields.emplace_back(VtablePointer, 0);
507 }
508
509 for (const auto &Base : RD->bases()) {
510 if (Base.isVirtual())
511 continue;
512
513 const RecordType *BaseRT = Base.getType()->castAs<RecordType>();
514 const llvm::abi::Type *BaseType = convertType(Base.getType());
515 uint64_t BaseOffset =
516 Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
517 8;
518 BaseClasses.emplace_back(BaseType, BaseOffset);
519 }
520
521 for (const auto &VBase : RD->vbases()) {
522 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
523 const llvm::abi::Type *VBaseType = convertType(VBase.getType());
524 uint64_t VBaseOffset =
525 Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
526 .getQuantity() *
527 8;
528 VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset);
529 }
530
531 computeFieldInfo(RD, Fields, Layout);
532
533 llvm::sort(Fields,
534 [](const llvm::abi::FieldInfo &A, const llvm::abi::FieldInfo &B) {
535 return A.OffsetInBits < B.OffsetInBits;
536 });
537
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());
543
544 llvm::abi::RecordFlags RecFlags = getCXXRecordFlags(RD);
545 if (RD->canPassInRegisters())
546 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
547 if (RD->hasFlexibleArrayMember())
548 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
549
550 return Builder.getRecordType(Fields, Size, Alignment, UnadjustedAlign,
551 llvm::abi::StructPacking::Default, BaseClasses,
552 VirtualBaseClasses, RecFlags);
553}
554
555/// Converts enumeration types to their underlying integer representations.
556/// This method handles various enum states and falls back to safe defaults
557/// when enum information is incomplete or invalid.
558///
559/// \param ET The EnumType to convert
560/// \return LLVM ABI IntegerType representing the enum's underlying type
561const llvm::abi::Type *
562QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
563 const EnumDecl *ED = ET->getDecl();
564 QualType UnderlyingType = ED->getIntegerType();
565
566 if (UnderlyingType.isNull())
567 UnderlyingType = ASTCtx.IntTy;
568
569 return convertType(UnderlyingType);
570}
571
572/// Converts plain C structs and C++ classes without inheritance.
573/// This handles the simpler case where we only need to layout member fields
574/// without considering base classes or virtual functions.
575///
576/// \param RD The RecordDecl to convert
577/// \return LLVM ABI RecordType
578const llvm::abi::RecordType *
579QualTypeMapper::convertStructType(const clang::RecordDecl *RD) {
580 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
581
582 SmallVector<llvm::abi::FieldInfo, 16> Fields;
583 computeFieldInfo(RD, Fields, Layout);
584
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());
590
591 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
592 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
593 RecFlags |= getCXXRecordFlags(CXXRD);
594 if (RD->canPassInRegisters())
595 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
596 if (RD->hasFlexibleArrayMember())
597 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
598
599 return Builder.getRecordType(Fields, Size, Alignment, UnadjustedAlign,
600 llvm::abi::StructPacking::Default, {}, {},
601 RecFlags);
602}
603
604/// Converts C union types where all fields occupy the same memory location.
605/// The union size is determined by its largest member, and all fields
606/// start at offset 0.
607///
608/// \param RD The RecordDecl representing the union
609/// \return LLVM ABI UnionType
610const llvm::abi::RecordType *
611QualTypeMapper::convertUnionType(const clang::RecordDecl *RD) {
612 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
613
614 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
615 computeFieldInfo(RD, AllFields, Layout);
616
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());
622
623 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
624 if (RD->hasAttr<TransparentUnionAttr>())
625 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
626 if (RD->canPassInRegisters())
627 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
628 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
629 RecFlags |= getCXXRecordFlags(CXXRD);
630
631 return Builder.getUnionType(AllFields, Size, Alignment, UnadjustedAlign,
632 llvm::abi::StructPacking::Default, RecFlags);
633}
634
635llvm::Align QualTypeMapper::getTypeAlign(QualType QT) const {
636
637 return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity());
638}
639
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));
646 // Function types without an explicit address space qualifier use the program
647 // address space, which may differ from the default data address space on
648 // targets like AMDGPU.
649 unsigned TargetAddrSpace =
650 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
651 ? DL.getProgramAddressSpace()
652 : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace);
653 // The default address space may map to a non-zero target address space
654 // (e.g. the SPIR-V generic one), which still makes the pointer qualified.
655 return Builder.getPointerType(
656 PointerSize, llvm::Align(Alignment.value() / 8), TargetAddrSpace,
657 PointeeType.hasAddressSpace() || TargetAddrSpace != 0);
658}
659
660/// Processes the fields of a record (struct/class/union) and populates
661/// the Fields vector with FieldInfo objects containing type, offset,
662/// and bitfield information.
663///
664/// \param RD The RecordDecl whose fields to process
665/// \param Fields Output vector to populate with field information
666/// \param Layout The AST record layout containing field offset information
667void QualTypeMapper::computeFieldInfo(
668 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
669 const ASTRecordLayout &Layout) {
670 unsigned FieldIndex = 0;
671
672 for (const auto *FD : RD->fields()) {
673 const llvm::abi::Type *FieldType = convertType(FD->getType());
674 uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
675
676 bool IsBitField = FD->isBitField();
677 uint64_t BitFieldWidth = 0;
678 bool IsUnnamedBitField = false;
679
680 if (IsBitField) {
681 BitFieldWidth = FD->getBitWidthValue();
682 IsUnnamedBitField = FD->isUnnamedBitField();
683 }
684
685 bool HasNoUniqueAddress = FD->hasAttr<NoUniqueAddressAttr>();
686 Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth,
687 IsUnnamedBitField, HasNoUniqueAddress);
688 ++FieldIndex;
689 }
690}
691
692} // namespace CodeGen
693} // namespace clang
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.
CanQualType VoidPtrTy
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
QualType getElementType() const
Definition TypeBase.h:3832
This class is used for builtin types like 'int'.
Definition TypeBase.h:3245
Kind getKind() const
Definition TypeBase.h:3299
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasNonTrivialCopyAssignment() const
Determine whether this class has a non-trivial copy assignment operator (C++ [class....
Definition DeclCXX.h:1350
bool hasNonTrivialDestructor() const
Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1392
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
Definition DeclCXX.h:1224
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1196
bool hasNonTrivialDefaultConstructor() const
Determine whether this class has a non-trivial default constructor (C++11 [class.ctor]p5).
Definition DeclCXX.h:1263
const llvm::abi::Type * convertType(clang::QualType QT)
Main entry point for converting Clang QualType to LLVM ABI Type.
bool hasAttr() const
Definition DeclBase.h:586
A (possibly-)qualified type.
Definition TypeBase.h:938
QualType getCanonicalType() const
Definition TypeBase.h:8630
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8672
Represents a struct/union/class.
Definition Decl.h:4506
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
Definition Decl.h:4643
bool hasFlexibleArrayMember() const
Definition Decl.h:4539
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4690
bool isUnion() const
Definition Decl.h:4109
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8900
TypeClass getTypeClass() const
Definition TypeBase.h:2449
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)
Definition Address.h:330
@ Result
The result type of a method or function.
Definition TypeBase.h:906
@ SveFixedLengthData
is AArch64 SVE fixed-length data vector
Definition TypeBase.h:4252
@ SveFixedLengthPredicate
is AArch64 SVE fixed-length predicate vector
Definition TypeBase.h:4255
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t