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"
18#include "clang/AST/ASTContext.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"
23#include "clang/AST/RecordLayout.h"
24#include "clang/AST/Type.h"
25#include "clang/Basic/AddressSpaces.h"
26#include "clang/Basic/LLVM.h"
27#include "clang/Basic/TargetInfo.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/// Main entry point for converting Clang QualType to LLVM ABI Type.
38/// This method performs type canonicalization, caching, and dispatches
39/// to specialized conversion methods based on the type kind.
40///
41/// \param QT The Clang QualType to convert
42/// \return Corresponding LLVM ABI Type representation
43const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
44 // Canonicalize type and strip qualifiers
45 // This ensures consistent type representation across different contexts
46 //
47 // TODO: AttributedType is NeverCanonical, so aligned typedef attributes
48 // for instance, __attribute__((aligned(N))) are lost here. Capture the
49 // effective alignment from the original QT and thread it through
50 // convertTypeImpl.
51 QT = QT.getCanonicalType().getUnqualifiedType();
52
53 // Results are cached since type conversion may be expensive.
54 auto It = TypeCache.find(Val: QT);
55 if (It != TypeCache.end())
56 return It->second;
57
58 const llvm::abi::Type *Result = convertTypeImpl(QT);
59 assert(Result && "convertTypeImpl returned nullptr");
60 TypeCache[QT] = Result;
61 return Result;
62}
63
64/// Dispatches to specialized conversion methods based on the type kind.
65const llvm::abi::Type *QualTypeMapper::convertTypeImpl(QualType QT) {
66 switch (QT->getTypeClass()) {
67 // Non-canonical and dependent types should have been stripped by
68 // getCanonicalType() above or cannot appear during code generation.
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 reason: "Non-canonical or dependent types should not reach ABI lowering");
77
78 case Type::Builtin:
79 return convertBuiltinType(BT: cast<BuiltinType>(Val&: QT));
80 case Type::Pointer:
81 return createPointerTypeForPointee(PointeeType: cast<PointerType>(Val&: QT)->getPointeeType());
82 case Type::LValueReference:
83 case Type::RValueReference:
84 return createPointerTypeForPointee(
85 PointeeType: cast<ReferenceType>(Val&: QT)->getPointeeType());
86 case Type::ConstantArray:
87 case Type::ArrayParameter:
88 case Type::IncompleteArray:
89 case Type::VariableArray:
90 return convertArrayType(AT: cast<ArrayType>(Val&: QT));
91 case Type::Vector:
92 case Type::ExtVector:
93 return convertVectorType(VT: cast<VectorType>(Val&: QT));
94 case Type::Record:
95 return convertRecordType(RT: cast<RecordType>(Val&: QT));
96 case Type::Enum:
97 return convertEnumType(ET: cast<EnumType>(Val&: QT));
98 case Type::Complex:
99 return convertComplexType(CT: cast<ComplexType>(Val&: QT));
100 case Type::Atomic:
101 return convertType(QT: cast<AtomicType>(Val&: QT)->getValueType());
102 case Type::BlockPointer:
103 case Type::Pipe:
104 return createPointerTypeForPointee(PointeeType: ASTCtx.VoidPtrTy);
105 case Type::ConstantMatrix: {
106 const auto *MT = cast<ConstantMatrixType>(Val&: QT);
107 return Builder.getArrayType(ElementType: convertType(QT: MT->getElementType()),
108 NumElements: MT->getNumRows() * MT->getNumColumns(),
109 SizeInBits: ASTCtx.getTypeSize(T: QT), /*IsMatrixType=*/true);
110 }
111 case Type::MemberPointer:
112 return convertMemberPointerType(MPT: cast<MemberPointerType>(Val&: QT));
113 case Type::BitInt: {
114 const auto *BIT = cast<BitIntType>(Val&: QT);
115 return Builder.getIntegerType(BitWidth: BIT->getNumBits(), Align: getTypeAlign(QT),
116 /*Signed=*/BIT->isSigned(),
117 /*IsBitInt=*/true);
118 }
119 case Type::ObjCObject:
120 case Type::ObjCInterface:
121 case Type::ObjCObjectPointer:
122 // Objective-C objects are represented as pointers in the ABI.
123 return Builder.getPointerType(
124 Size: ASTCtx.getTargetInfo().getPointerWidth(AddrSpace: QT.getAddressSpace()),
125 Align: llvm::Align(
126 ASTCtx.getTargetInfo().getPointerAlign(AddrSpace: QT.getAddressSpace()) / 8),
127 Addrspace: ASTCtx.getTargetInfo().getTargetAddressSpace(AS: QT.getAddressSpace()));
128 case Type::OverflowBehavior:
129 return convertType(QT: cast<OverflowBehaviorType>(Val&: QT)->getUnderlyingType());
130 case Type::Auto:
131 case Type::DeducedTemplateSpecialization:
132 case Type::FunctionProto:
133 case Type::FunctionNoProto:
134 case Type::HLSLAttributedResource:
135 case Type::HLSLInlineSpirv:
136 llvm::reportFatalInternalError(reason: "Type not supported in ABI lowering");
137 }
138 llvm_unreachable("unhandled type class in convertTypeImpl");
139}
140
141/// Converts C/C++ builtin types to LLVM ABI types.
142/// This handles all fundamental scalar types including integers, floats,
143/// and special types like void and bool.
144const llvm::abi::Type *
145QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
146 QualType QT(BT, 0);
147
148 switch (BT->getKind()) {
149 case BuiltinType::Void:
150 return Builder.getVoidType();
151
152 case BuiltinType::NullPtr:
153 return createPointerTypeForPointee(PointeeType: QT);
154
155 case BuiltinType::Bool:
156 return Builder.getIntegerType(BitWidth: 1, Align: getTypeAlign(QT), /*Signed=*/false,
157 /*IsBitInt=*/false);
158
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(BitWidth: ASTCtx.getTypeSize(T: QT), Align: getTypeAlign(QT),
179 /*Signed=*/BT->isSignedInteger(),
180 /*IsBitInt=*/false);
181
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(Semantics: ASTCtx.getFloatTypeSemantics(T: QT),
190 Align: getTypeAlign(QT));
191
192 // TODO: IBM 128-bit extended double
193 case BuiltinType::Ibm128:
194 llvm::reportFatalInternalError(
195 reason: "IBM128 is not yet supported in the ABI lowering libary");
196
197 // TODO: Fixed-point types
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 reason: "Fixed Point types not yet implemented in the ABI lowering library");
224
225 // OpenCL image types are represented as opaque pointers.
226#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
227 case BuiltinType::Id:
228#include "clang/Basic/OpenCLImageTypes.def"
229 // OpenCL extension types are represented as opaque pointers.
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(PointeeType: QT);
238
239 // Objective-C builtin types are represented as opaque pointers.
240 case BuiltinType::ObjCId:
241 case BuiltinType::ObjCClass:
242 case BuiltinType::ObjCSel:
243 return createPointerTypeForPointee(PointeeType: QT);
244
245 // Target-specific vector/matrix types — not yet implemented.
246#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
247#include "clang/Basic/AArch64ACLETypes.def"
248 llvm::reportFatalInternalError(
249 reason: "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 reason: "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 reason: "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(reason: "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 reason: "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 reason: "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 reason: "SPIR-V types not yet supported in ABI lowering library");
274
275 // Placeholder types should never reach ABI lowering.
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 reason: "Placeholder type should not reach ABI lowering");
281
282 case BuiltinType::Dependent:
283 llvm::reportFatalInternalError(
284 reason: "Dependent builtin type should not reach ABI lowering");
285 }
286 llvm_unreachable("unhandled builtin type kind in convertBuiltinType");
287}
288
289/// Converts array types to LLVM ABI array representations.
290/// Handles different array kinds: constant arrays, incomplete arrays,
291/// and variable-length arrays.
292///
293/// \param AT The ArrayType to convert
294/// \return LLVM ABI ArrayType or PointerType
295const llvm::abi::Type *
296QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
297 const llvm::abi::Type *ElementType = convertType(QT: AT->getElementType());
298 uint64_t Size = ASTCtx.getTypeSize(T: AT);
299
300 if (const auto *CAT = dyn_cast<ConstantArrayType>(Val: AT)) {
301 auto NumElements = CAT->getZExtSize();
302 return Builder.getArrayType(ElementType, NumElements, SizeInBits: Size);
303 }
304 if (isa<IncompleteArrayType>(Val: AT))
305 return Builder.getArrayType(ElementType, NumElements: 0, SizeInBits: 0);
306 if (const auto *VAT = dyn_cast<VariableArrayType>(Val: AT))
307 return createPointerTypeForPointee(PointeeType: VAT->getPointeeType());
308 llvm::reportFatalInternalError(
309 reason: "unexpected array type in ABI lowering (dependent array types should be "
310 "resolved before reaching this point)");
311}
312
313const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) {
314 const llvm::abi::Type *ElementType = convertType(QT: VT->getElementType());
315 QualType VectorQualType(VT, 0);
316
317 unsigned NElems = VT->getNumElements();
318 llvm::ElementCount NumElements = llvm::ElementCount::getFixed(MinVal: NElems);
319 llvm::Align VectorAlign = getTypeAlign(QT: VectorQualType);
320
321 return Builder.getVectorType(ElementType, NumElements, Align: VectorAlign);
322}
323
324/// Converts complex types to LLVM ABI complex representations.
325/// Complex types consist of two components of the element type
326/// (real and imaginary parts).
327///
328/// \param CT The ComplexType to convert
329/// \return LLVM ABI ComplexType with element type and alignment
330const llvm::abi::Type *
331QualTypeMapper::convertComplexType(const ComplexType *CT) {
332 const llvm::abi::Type *ElementType = convertType(QT: CT->getElementType());
333 llvm::Align ComplexAlign = getTypeAlign(QT: QualType(CT, 0));
334
335 return Builder.getComplexType(ElementType, Align: ComplexAlign);
336}
337
338/// Converts member pointer types to LLVM ABI representations.
339/// Member pointers have different layouts depending on whether they
340/// point to functions or data members.
341///
342/// \param MPT The MemberPointerType to convert
343/// \return LLVM ABI MemberPointerType
344const llvm::abi::Type *
345QualTypeMapper::convertMemberPointerType(const clang::MemberPointerType *MPT) {
346 QualType QT(MPT, 0);
347 uint64_t Size = ASTCtx.getTypeSize(T: QT);
348 llvm::Align Align = getTypeAlign(QT);
349
350 bool IsFunctionPointer = MPT->isMemberFunctionPointerType();
351
352 return Builder.getMemberPointerType(IsFunctionPointer, SizeInBits: Size, Align);
353}
354
355/// Converts record types (struct/class/union) to LLVM ABI representations.
356/// This is the main dispatch method that handles different record kinds
357/// and delegates to specialized converters.
358///
359/// \param RT The RecordType to convert
360/// \return LLVM ABI RecordType
361const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) {
362 const RecordDecl *RD = RT->getDecl()->getDefinition();
363 if (!RD)
364 return Builder.getRecordType(Fields: {}, Size: llvm::TypeSize::getFixed(ExactSize: 0),
365 Align: llvm::Align(1));
366
367 if (RD->isUnion())
368 return convertUnionType(RD);
369
370 // Handle C++ classes with base classes
371 auto *CXXRd = dyn_cast<CXXRecordDecl>(Val: RD);
372 if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0))
373 return convertCXXRecordType(RD: CXXRd);
374 return convertStructType(RD);
375}
376
377/// Converts C++ classes with inheritance to LLVM ABI struct representations.
378/// This method handles the complex layout of C++ objects including:
379/// - Virtual table pointers for polymorphic classes
380/// - Base class subobjects (both direct and virtual bases)
381/// - Member field layout with proper offsets
382///
383/// \param RD The C++ record declaration
384/// \return LLVM ABI RecordType representing the complete object layout
385const llvm::abi::RecordType *
386QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) {
387 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(D: RD);
388 SmallVector<llvm::abi::FieldInfo, 16> Fields;
389 SmallVector<llvm::abi::FieldInfo, 8> BaseClasses;
390 SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses;
391
392 // Add vtable pointer for polymorphic classes
393 if (RD->isPolymorphic()) {
394 const llvm::abi::Type *VtablePointer =
395 createPointerTypeForPointee(PointeeType: ASTCtx.VoidPtrTy);
396 Fields.emplace_back(Args&: VtablePointer, Args: 0);
397 }
398
399 for (const auto &Base : RD->bases()) {
400 const RecordType *BaseRT = Base.getType()->castAs<RecordType>();
401 const CXXRecordDecl *BaseDecl = BaseRT->getAsCXXRecordDecl();
402 const llvm::abi::Type *BaseType = convertType(QT: Base.getType());
403 // Virtual and non-virtual base offsets live in separate maps in the AST
404 // record layout.
405 uint64_t BaseOffset =
406 (Base.isVirtual() ? Layout.getVBaseClassOffset(VBase: BaseDecl)
407 : Layout.getBaseClassOffset(Base: BaseDecl))
408 .getQuantity() *
409 8;
410 BaseClasses.emplace_back(Args&: BaseType, Args&: BaseOffset, /*IsBitField=*/Args: false,
411 /*BitFieldWidth=*/Args: 0, /*IsUnnamedBitField=*/Args: false,
412 /*IsVirtualBase=*/Args: Base.isVirtual());
413 }
414
415 for (const auto &VBase : RD->vbases()) {
416 const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>();
417 const llvm::abi::Type *VBaseType = convertType(QT: VBase.getType());
418 uint64_t VBaseOffset =
419 Layout.getVBaseClassOffset(VBase: VBaseRT->getAsCXXRecordDecl())
420 .getQuantity() *
421 8;
422
423 VirtualBaseClasses.emplace_back(Args&: VBaseType, Args&: VBaseOffset,
424 /*IsBitField=*/Args: false,
425 /*BitFieldWidth=*/Args: 0,
426 /*IsUnnamedBitField=*/Args: false,
427 /*IsVirtualBase=*/Args: true);
428 }
429
430 computeFieldInfo(RD, Fields, Layout);
431
432 llvm::sort(C&: Fields,
433 Comp: [](const llvm::abi::FieldInfo &A, const llvm::abi::FieldInfo &B) {
434 return A.OffsetInBits < B.OffsetInBits;
435 });
436
437 llvm::TypeSize Size =
438 llvm::TypeSize::getFixed(ExactSize: Layout.getSize().getQuantity() * 8);
439 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
440
441 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord;
442 if (RD->isPolymorphic())
443 RecFlags |= llvm::abi::RecordFlags::IsPolymorphic;
444 if (RD->canPassInRegisters())
445 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
446 if (RD->hasFlexibleArrayMember())
447 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
448
449 return Builder.getRecordType(Fields, Size, Align: Alignment,
450 Pack: llvm::abi::StructPacking::Default, BaseClasses,
451 VirtualBaseClasses, RecFlags);
452}
453
454/// Converts enumeration types to their underlying integer representations.
455/// This method handles various enum states and falls back to safe defaults
456/// when enum information is incomplete or invalid.
457///
458/// \param ET The EnumType to convert
459/// \return LLVM ABI IntegerType representing the enum's underlying type
460const llvm::abi::Type *
461QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
462 const EnumDecl *ED = ET->getDecl();
463 QualType UnderlyingType = ED->getIntegerType();
464
465 if (UnderlyingType.isNull())
466 UnderlyingType = ASTCtx.IntTy;
467
468 return convertType(QT: UnderlyingType);
469}
470
471/// Converts plain C structs and C++ classes without inheritance.
472/// This handles the simpler case where we only need to layout member fields
473/// without considering base classes or virtual functions.
474///
475/// \param RD The RecordDecl to convert
476/// \return LLVM ABI RecordType
477const llvm::abi::RecordType *
478QualTypeMapper::convertStructType(const clang::RecordDecl *RD) {
479 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(D: RD);
480
481 bool IsCXXRecord = isa<CXXRecordDecl>(Val: RD);
482 SmallVector<llvm::abi::FieldInfo, 16> Fields;
483 computeFieldInfo(RD, Fields, Layout);
484
485 llvm::TypeSize Size =
486 llvm::TypeSize::getFixed(ExactSize: Layout.getSize().getQuantity() * 8);
487 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
488
489 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
490 if (IsCXXRecord)
491 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
492 if (RD->canPassInRegisters())
493 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
494 if (RD->hasFlexibleArrayMember())
495 RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember;
496
497 return Builder.getRecordType(Fields, Size, Align: Alignment,
498 Pack: llvm::abi::StructPacking::Default, BaseClasses: {}, VirtualBaseClasses: {},
499 RecFlags);
500}
501
502/// Converts C union types where all fields occupy the same memory location.
503/// The union size is determined by its largest member, and all fields
504/// start at offset 0.
505///
506/// \param RD The RecordDecl representing the union
507/// \return LLVM ABI UnionType
508const llvm::abi::RecordType *
509QualTypeMapper::convertUnionType(const clang::RecordDecl *RD) {
510 const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(D: RD);
511
512 SmallVector<llvm::abi::FieldInfo, 16> AllFields;
513 computeFieldInfo(RD, Fields&: AllFields, Layout);
514
515 llvm::TypeSize Size =
516 llvm::TypeSize::getFixed(ExactSize: Layout.getSize().getQuantity() * 8);
517 llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
518
519 llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None;
520 if (RD->hasAttr<TransparentUnionAttr>())
521 RecFlags |= llvm::abi::RecordFlags::IsTransparent;
522 if (RD->canPassInRegisters())
523 RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters;
524 if (isa<CXXRecordDecl>(Val: RD))
525 RecFlags |= llvm::abi::RecordFlags::IsCXXRecord;
526
527 return Builder.getUnionType(Fields: AllFields, Size, Align: Alignment,
528 Pack: llvm::abi::StructPacking::Default, RecFlags);
529}
530
531llvm::Align QualTypeMapper::getTypeAlign(QualType QT) const {
532
533 return llvm::Align(ASTCtx.getTypeAlignInChars(T: QT).getQuantity());
534}
535
536const llvm::abi::Type *
537QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
538 auto AddrSpace = PointeeType.getAddressSpace();
539 auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
540 llvm::Align Alignment =
541 llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
542 // Function types without an explicit address space qualifier use the program
543 // address space, which may differ from the default data address space on
544 // targets like AMDGPU.
545 unsigned TargetAddrSpace =
546 PointeeType->isFunctionType() && !PointeeType.hasAddressSpace()
547 ? DL.getProgramAddressSpace()
548 : ASTCtx.getTargetInfo().getTargetAddressSpace(AS: AddrSpace);
549 return Builder.getPointerType(Size: PointerSize, Align: llvm::Align(Alignment.value() / 8),
550 Addrspace: TargetAddrSpace);
551}
552
553/// Processes the fields of a record (struct/class/union) and populates
554/// the Fields vector with FieldInfo objects containing type, offset,
555/// and bitfield information.
556///
557/// \param RD The RecordDecl whose fields to process
558/// \param Fields Output vector to populate with field information
559/// \param Layout The AST record layout containing field offset information
560void QualTypeMapper::computeFieldInfo(
561 const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
562 const ASTRecordLayout &Layout) {
563 unsigned FieldIndex = 0;
564
565 for (const auto *FD : RD->fields()) {
566 const llvm::abi::Type *FieldType = convertType(QT: FD->getType());
567 uint64_t OffsetInBits = Layout.getFieldOffset(FieldNo: FieldIndex);
568
569 bool IsBitField = FD->isBitField();
570 uint64_t BitFieldWidth = 0;
571 bool IsUnnamedBitField = false;
572
573 if (IsBitField) {
574 BitFieldWidth = FD->getBitWidthValue();
575 IsUnnamedBitField = FD->isUnnamedBitField();
576 }
577
578 Fields.emplace_back(Args&: FieldType, Args&: OffsetInBits, Args&: IsBitField, Args&: BitFieldWidth,
579 Args&: IsUnnamedBitField);
580 ++FieldIndex;
581 }
582}
583
584} // namespace CodeGen
585} // namespace clang
586