Author: Narayan Date: 2026-03-08T20:18:49+05:30 New Revision: af7c352fa38d49096888df6c99d010d274362aa6
URL: https://github.com/llvm/llvm-project/commit/af7c352fa38d49096888df6c99d010d274362aa6 DIFF: https://github.com/llvm/llvm-project/commit/af7c352fa38d49096888df6c99d010d274362aa6.diff LOG: [LLVMABI] Introduce the QualTypeMapper (#174634) This PR introduces the `QualTypeMapper` class, which bridges Clang's type system with the LLVM ABI type system introduced in https://github.com/llvm/llvm-project/pull/158329. The `QualTypeMapper` translates Clang `QualType` instances into their corresponding LLVM ABI type representations, preserving all ABI-relevant information while abstracting away frontend-specific details. The mapper queries the `ASTContext` for layout information computed by the frontend and uses the `TypeBuilder` API(from the above merged PR) to construct the corresponding ABI types. This separation ensures that ABI logic remains independent of frontend AST details while still having access to all necessary type information. This is a prerequisite for implementing target-specific ABI lowering, as demonstrated in https://github.com/llvm/llvm-project/pull/140112 Added: clang/lib/CodeGen/QualTypeMapper.cpp clang/lib/CodeGen/QualTypeMapper.h Modified: clang/lib/CodeGen/CMakeLists.txt Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index dbbc35b372f42..434781b3c4f02 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -116,6 +116,7 @@ add_clang_library(clangCodeGen ModuleBuilder.cpp ObjectFilePCHContainerWriter.cpp PatternInit.cpp + QualTypeMapper.cpp SanitizerMetadata.cpp SwiftCallingConv.cpp TargetBuiltins/ARM.cpp diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp new file mode 100644 index 0000000000000..31d9250a48ec9 --- /dev/null +++ b/clang/lib/CodeGen/QualTypeMapper.cpp @@ -0,0 +1,574 @@ +//==---- QualTypeMapper.cpp - Maps Clang QualType to LLVMABI Types ---------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Maps Clang QualType instances to corresponding LLVM ABI type +/// representations. This mapper translates high-level type information from the +/// AST into low-level ABI-specific types that encode size, alignment, and +/// layout details required for code generation and cross-language +/// interoperability. +/// +//===----------------------------------------------------------------------===// +#include "QualTypeMapper.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTFwd.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/Type.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ABI/Types.h" +#include "llvm/Support/Alignment.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TypeSize.h" +#include <cstdint> + +namespace clang { +namespace CodeGen { + +/// Main entry point for converting Clang QualType to LLVM ABI Type. +/// This method performs type canonicalization, caching, and dispatches +/// to specialized conversion methods based on the type kind. +/// +/// \param QT The Clang QualType to convert +/// \return Corresponding LLVM ABI Type representation +const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) { + // Canonicalize type and strip qualifiers + // This ensures consistent type representation across diff erent contexts + // + // TODO: AttributedType is NeverCanonical, so aligned typedef attributes + // for instance, __attribute__((aligned(N))) are lost here. Capture the + // effective alignment from the original QT and thread it through + // convertTypeImpl. + QT = QT.getCanonicalType().getUnqualifiedType(); + + // Results are cached since type conversion may be expensive. + auto It = TypeCache.find(QT); + if (It != TypeCache.end()) + return It->second; + + const llvm::abi::Type *Result = convertTypeImpl(QT); + assert(Result && "convertTypeImpl returned nullptr"); + TypeCache[QT] = Result; + return Result; +} + +/// Dispatches to specialized conversion methods based on the type kind. +const llvm::abi::Type *QualTypeMapper::convertTypeImpl(QualType QT) { + switch (QT->getTypeClass()) { + // Non-canonical and dependent types should have been stripped by + // getCanonicalType() above or cannot appear during code generation. +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#include "clang/AST/TypeNodes.inc" + llvm::reportFatalInternalError( + "Non-canonical or dependent types should not reach ABI lowering"); + + case Type::Builtin: + return convertBuiltinType(cast<BuiltinType>(QT)); + case Type::Pointer: + return createPointerTypeForPointee(cast<PointerType>(QT)->getPointeeType()); + case Type::LValueReference: + case Type::RValueReference: + return createPointerTypeForPointee( + cast<ReferenceType>(QT)->getPointeeType()); + case Type::ConstantArray: + case Type::ArrayParameter: + case Type::IncompleteArray: + case Type::VariableArray: + return convertArrayType(cast<ArrayType>(QT)); + case Type::Vector: + case Type::ExtVector: + return convertVectorType(cast<VectorType>(QT)); + case Type::Record: + return convertRecordType(cast<RecordType>(QT)); + case Type::Enum: + return convertEnumType(cast<EnumType>(QT)); + case Type::Complex: + return convertComplexType(cast<ComplexType>(QT)); + case Type::Atomic: + return convertType(cast<AtomicType>(QT)->getValueType()); + case Type::BlockPointer: + case Type::Pipe: + return createPointerTypeForPointee(ASTCtx.VoidPtrTy); + case Type::ConstantMatrix: { + const auto *MT = cast<ConstantMatrixType>(QT); + return Builder.getArrayType(convertType(MT->getElementType()), + MT->getNumRows() * MT->getNumColumns(), + ASTCtx.getTypeSize(QT), /*IsMatrixType=*/true); + } + case Type::MemberPointer: + return convertMemberPointerType(cast<MemberPointerType>(QT)); + case Type::BitInt: { + const auto *BIT = cast<BitIntType>(QT); + return Builder.getIntegerType(BIT->getNumBits(), getTypeAlign(QT), + /*Signed=*/BIT->isSigned(), + /*IsBitInt=*/true); + } + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + // Objective-C objects are represented as pointers in the ABI. + return Builder.getPointerType( + ASTCtx.getTargetInfo().getPointerWidth(QT.getAddressSpace()), + llvm::Align( + ASTCtx.getTargetInfo().getPointerAlign(QT.getAddressSpace()) / 8), + ASTCtx.getTargetInfo().getTargetAddressSpace(QT.getAddressSpace())); + case Type::OverflowBehavior: + return convertType(cast<OverflowBehaviorType>(QT)->getUnderlyingType()); + case Type::Auto: + case Type::DeducedTemplateSpecialization: + case Type::FunctionProto: + case Type::FunctionNoProto: + case Type::HLSLAttributedResource: + case Type::HLSLInlineSpirv: + llvm::reportFatalInternalError("Type not supported in ABI lowering"); + } + llvm_unreachable("unhandled type class in convertTypeImpl"); +} + +/// Converts C/C++ builtin types to LLVM ABI types. +/// This handles all fundamental scalar types including integers, floats, +/// and special types like void and bool. +const llvm::abi::Type * +QualTypeMapper::convertBuiltinType(const BuiltinType *BT) { + QualType QT(BT, 0); + + switch (BT->getKind()) { + case BuiltinType::Void: + return Builder.getVoidType(); + + case BuiltinType::NullPtr: + return createPointerTypeForPointee(QT); + + case BuiltinType::Bool: + return Builder.getIntegerType(1, getTypeAlign(QT), /*Signed=*/false, + /*IsBitInt=*/false); + + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + case BuiltinType::Char8: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::Int: + case BuiltinType::UInt: + case BuiltinType::Long: + case BuiltinType::ULong: + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + case BuiltinType::Int128: + case BuiltinType::UInt128: + return Builder.getIntegerType(ASTCtx.getTypeSize(QT), getTypeAlign(QT), + /*Signed=*/BT->isSignedInteger(), + /*IsBitInt=*/false); + + case BuiltinType::Half: + case BuiltinType::Float16: + case BuiltinType::BFloat16: + case BuiltinType::Float: + case BuiltinType::Double: + case BuiltinType::LongDouble: + case BuiltinType::Float128: + return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QT), + getTypeAlign(QT)); + + // TODO: IBM 128-bit extended double + case BuiltinType::Ibm128: + llvm::reportFatalInternalError( + "IBM128 is not yet supported in the ABI lowering libary"); + + // TODO: Fixed-point types + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: + llvm::reportFatalInternalError( + "Fixed Point types not yet implemented in the ABI lowering library"); + + // OpenCL image types are represented as opaque pointers. +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" + // OpenCL extension types are represented as opaque pointers. +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id: +#include "clang/Basic/OpenCLExtensionTypes.def" + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLReserveID: + return createPointerTypeForPointee(QT); + + // Objective-C builtin types are represented as opaque pointers. + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return createPointerTypeForPointee(QT); + + // Target-specific vector/matrix types — not yet implemented. +#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/AArch64ACLETypes.def" + llvm::reportFatalInternalError( + "AArch64 SVE types not yet supported in ABI lowering library"); +#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id: +#include "clang/Basic/PPCTypes.def" + llvm::reportFatalInternalError( + "PPC MMA types not yet supported in ABI lowering library"); +#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/RISCVVTypes.def" + llvm::reportFatalInternalError( + "RISC-V vector types not yet supported in ABI lowering library"); +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" + llvm::reportFatalInternalError("WebAssembly reference types not yet " + "supported in ABI lowering library"); +#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id: +#include "clang/Basic/AMDGPUTypes.def" + llvm::reportFatalInternalError( + "AMDGPU types not yet supported in ABI lowering library"); +#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLIntangibleTypes.def" + llvm::reportFatalInternalError( + "HLSL intangible types not yet Supported in ABI lowering library"); + + // Placeholder types should never reach ABI lowering. +#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: +#define BUILTIN_TYPE(Id, SingletonId) +#include "clang/AST/BuiltinTypes.def" + llvm::reportFatalInternalError( + "Placeholder type should not reach ABI lowering"); + + case BuiltinType::Dependent: + llvm::reportFatalInternalError( + "Dependent builtin type should not reach ABI lowering"); + } + llvm_unreachable("unhandled builtin type kind in convertBuiltinType"); +} + +/// Converts array types to LLVM ABI array representations. +/// Handles diff erent array kinds: constant arrays, incomplete arrays, +/// and variable-length arrays. +/// +/// \param AT The ArrayType to convert +/// \return LLVM ABI ArrayType or PointerType +const llvm::abi::Type * +QualTypeMapper::convertArrayType(const clang::ArrayType *AT) { + const llvm::abi::Type *ElementType = convertType(AT->getElementType()); + uint64_t Size = ASTCtx.getTypeSize(AT); + + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { + auto NumElements = CAT->getZExtSize(); + return Builder.getArrayType(ElementType, NumElements, Size); + } + if (isa<IncompleteArrayType>(AT)) + return Builder.getArrayType(ElementType, 0, 0); + if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) + return createPointerTypeForPointee(VAT->getPointeeType()); + llvm::reportFatalInternalError( + "unexpected array type in ABI lowering (dependent array types should be " + "resolved before reaching this point)"); +} + +const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) { + const llvm::abi::Type *ElementType = convertType(VT->getElementType()); + QualType VectorQualType(VT, 0); + + unsigned NElems = VT->getNumElements(); + llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems); + llvm::Align VectorAlign = getTypeAlign(VectorQualType); + + return Builder.getVectorType(ElementType, NumElements, VectorAlign); +} + +/// Converts complex types to LLVM ABI complex representations. +/// Complex types consist of two components of the element type +/// (real and imaginary parts). +/// +/// \param CT The ComplexType to convert +/// \return LLVM ABI ComplexType with element type and alignment +const llvm::abi::Type * +QualTypeMapper::convertComplexType(const ComplexType *CT) { + const llvm::abi::Type *ElementType = convertType(CT->getElementType()); + llvm::Align ComplexAlign = getTypeAlign(QualType(CT, 0)); + + return Builder.getComplexType(ElementType, ComplexAlign); +} + +/// Converts member pointer types to LLVM ABI representations. +/// Member pointers have diff erent layouts depending on whether they +/// point to functions or data members. +/// +/// \param MPT The MemberPointerType to convert +/// \return LLVM ABI MemberPointerType +const llvm::abi::Type * +QualTypeMapper::convertMemberPointerType(const clang::MemberPointerType *MPT) { + QualType QT(MPT, 0); + uint64_t Size = ASTCtx.getTypeSize(QT); + llvm::Align Align = getTypeAlign(QT); + + bool IsFunctionPointer = MPT->isMemberFunctionPointerType(); + + return Builder.getMemberPointerType(IsFunctionPointer, Size, Align); +} + +/// Converts record types (struct/class/union) to LLVM ABI representations. +/// This is the main dispatch method that handles diff erent record kinds +/// and delegates to specialized converters. +/// +/// \param RT The RecordType to convert +/// \return LLVM ABI RecordType +const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) { + const RecordDecl *RD = RT->getDecl()->getDefinition(); + if (!RD) + return Builder.getRecordType({}, llvm::TypeSize::getFixed(0), + llvm::Align(1)); + + if (RD->isUnion()) + return convertUnionType(RD); + + // Handle C++ classes with base classes + auto *CXXRd = dyn_cast<CXXRecordDecl>(RD); + if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0)) + return convertCXXRecordType(CXXRd); + return convertStructType(RD); +} + +/// Converts C++ classes with inheritance to LLVM ABI struct representations. +/// This method handles the complex layout of C++ objects including: +/// - Virtual table pointers for polymorphic classes +/// - Base class subobjects (both direct and virtual bases) +/// - Member field layout with proper offsets +/// +/// \param RD The C++ record declaration +/// \return LLVM ABI RecordType representing the complete object layout +const llvm::abi::RecordType * +QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) { + const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD); + SmallVector<llvm::abi::FieldInfo, 16> Fields; + SmallVector<llvm::abi::FieldInfo, 8> BaseClasses; + SmallVector<llvm::abi::FieldInfo, 8> VirtualBaseClasses; + + // Add vtable pointer for polymorphic classes + if (RD->isPolymorphic()) { + const llvm::abi::Type *VtablePointer = + createPointerTypeForPointee(ASTCtx.VoidPtrTy); + Fields.emplace_back(VtablePointer, 0); + } + + for (const auto &Base : RD->bases()) { + if (Base.isVirtual()) + continue; + + const RecordType *BaseRT = Base.getType()->castAs<RecordType>(); + const llvm::abi::Type *BaseType = convertType(Base.getType()); + uint64_t BaseOffset = + Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() * + 8; + + BaseClasses.emplace_back(BaseType, BaseOffset); + } + + for (const auto &VBase : RD->vbases()) { + const RecordType *VBaseRT = VBase.getType()->castAs<RecordType>(); + const llvm::abi::Type *VBaseType = convertType(VBase.getType()); + uint64_t VBaseOffset = + Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl()) + .getQuantity() * + 8; + + VirtualBaseClasses.emplace_back(VBaseType, VBaseOffset); + } + + computeFieldInfo(RD, Fields, Layout); + + llvm::sort(Fields, + [](const llvm::abi::FieldInfo &A, const llvm::abi::FieldInfo &B) { + return A.OffsetInBits < B.OffsetInBits; + }); + + llvm::TypeSize Size = + llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8); + llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity()); + + llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::IsCXXRecord; + if (RD->isPolymorphic()) + RecFlags |= llvm::abi::RecordFlags::IsPolymorphic; + if (RD->canPassInRegisters()) + RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters; + if (RD->hasFlexibleArrayMember()) + RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember; + + return Builder.getRecordType(Fields, Size, Alignment, + llvm::abi::StructPacking::Default, BaseClasses, + VirtualBaseClasses, RecFlags); +} + +/// Converts enumeration types to their underlying integer representations. +/// This method handles various enum states and falls back to safe defaults +/// when enum information is incomplete or invalid. +/// +/// \param ET The EnumType to convert +/// \return LLVM ABI IntegerType representing the enum's underlying type +const llvm::abi::Type * +QualTypeMapper::convertEnumType(const clang::EnumType *ET) { + const EnumDecl *ED = ET->getDecl(); + QualType UnderlyingType = ED->getIntegerType(); + + if (UnderlyingType.isNull()) + UnderlyingType = ASTCtx.IntTy; + + return convertType(UnderlyingType); +} + +/// Converts plain C structs and C++ classes without inheritance. +/// This handles the simpler case where we only need to layout member fields +/// without considering base classes or virtual functions. +/// +/// \param RD The RecordDecl to convert +/// \return LLVM ABI RecordType +const llvm::abi::RecordType * +QualTypeMapper::convertStructType(const clang::RecordDecl *RD) { + const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD); + + bool IsCXXRecord = isa<CXXRecordDecl>(RD); + SmallVector<llvm::abi::FieldInfo, 16> Fields; + computeFieldInfo(RD, Fields, Layout); + + llvm::TypeSize Size = + llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8); + llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity()); + + llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None; + if (IsCXXRecord) + RecFlags |= llvm::abi::RecordFlags::IsCXXRecord; + if (RD->canPassInRegisters()) + RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters; + if (RD->hasFlexibleArrayMember()) + RecFlags |= llvm::abi::RecordFlags::HasFlexibleArrayMember; + + return Builder.getRecordType(Fields, Size, Alignment, + llvm::abi::StructPacking::Default, {}, {}, + RecFlags); +} + +/// Converts C union types where all fields occupy the same memory location. +/// The union size is determined by its largest member, and all fields +/// start at offset 0. +/// +/// \param RD The RecordDecl representing the union +/// \return LLVM ABI UnionType +const llvm::abi::RecordType * +QualTypeMapper::convertUnionType(const clang::RecordDecl *RD) { + const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD); + + SmallVector<llvm::abi::FieldInfo, 16> AllFields; + computeFieldInfo(RD, AllFields, Layout); + + llvm::TypeSize Size = + llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8); + llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity()); + + llvm::abi::RecordFlags RecFlags = llvm::abi::RecordFlags::None; + if (RD->hasAttr<TransparentUnionAttr>()) + RecFlags |= llvm::abi::RecordFlags::IsTransparent; + if (RD->canPassInRegisters()) + RecFlags |= llvm::abi::RecordFlags::CanPassInRegisters; + if (isa<CXXRecordDecl>(RD)) + RecFlags |= llvm::abi::RecordFlags::IsCXXRecord; + + return Builder.getUnionType(AllFields, Size, Alignment, + llvm::abi::StructPacking::Default, RecFlags); +} + +llvm::Align QualTypeMapper::getTypeAlign(QualType QT) const { + + return llvm::Align(ASTCtx.getTypeAlignInChars(QT).getQuantity()); +} + +const llvm::abi::Type * +QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) { + auto AddrSpace = PointeeType.getAddressSpace(); + auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace); + llvm::Align Alignment = + llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace)); + // Function types without an explicit address space qualifier use the program + // address space, which may diff er from the default data address space on + // targets like AMDGPU. + unsigned TargetAddrSpace = + PointeeType->isFunctionType() && !PointeeType.hasAddressSpace() + ? DL.getProgramAddressSpace() + : ASTCtx.getTargetInfo().getTargetAddressSpace(AddrSpace); + return Builder.getPointerType(PointerSize, llvm::Align(Alignment.value() / 8), + TargetAddrSpace); +} + +/// Processes the fields of a record (struct/class/union) and populates +/// the Fields vector with FieldInfo objects containing type, offset, +/// and bitfield information. +/// +/// \param RD The RecordDecl whose fields to process +/// \param Fields Output vector to populate with field information +/// \param Layout The AST record layout containing field offset information +void QualTypeMapper::computeFieldInfo( + const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields, + const ASTRecordLayout &Layout) { + unsigned FieldIndex = 0; + + for (const auto *FD : RD->fields()) { + const llvm::abi::Type *FieldType = convertType(FD->getType()); + uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex); + + bool IsBitField = FD->isBitField(); + uint64_t BitFieldWidth = 0; + bool IsUnnamedBitField = false; + + if (IsBitField) { + BitFieldWidth = FD->getBitWidthValue(); + IsUnnamedBitField = FD->isUnnamedBitField(); + } + + Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth, + IsUnnamedBitField); + ++FieldIndex; + } +} + +} // namespace CodeGen +} // namespace clang diff --git a/clang/lib/CodeGen/QualTypeMapper.h b/clang/lib/CodeGen/QualTypeMapper.h new file mode 100644 index 0000000000000..11e8ba86cfcdf --- /dev/null +++ b/clang/lib/CodeGen/QualTypeMapper.h @@ -0,0 +1,80 @@ +//==---- QualTypeMapper.h - Maps Clang QualType to LLVMABI Types -----------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Maps Clang QualType instances to corresponding LLVM ABI type +/// representations. This mapper translates high-level type information from the +/// AST into low-level ABI-specific types that encode size, alignment, and +/// layout details required for code generation and cross-language +/// interoperability. +/// +//===----------------------------------------------------------------------===// +#ifndef CLANG_LIB_CODEGEN_QUALTYPE_MAPPER_H +#define CLANG_LIB_CODEGEN_QUALTYPE_MAPPER_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeOrdering.h" +#include "llvm/ABI/Types.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Support/Allocator.h" + +namespace clang { +namespace CodeGen { + +class QualTypeMapper { +private: + clang::ASTContext &ASTCtx; + const llvm::DataLayout &DL; + llvm::abi::TypeBuilder Builder; + + llvm::DenseMap<QualType, const llvm::abi::Type *> TypeCache; + + const llvm::abi::Type *convertTypeImpl(QualType QT); + const llvm::abi::Type *convertBuiltinType(const clang::BuiltinType *BT); + const llvm::abi::Type *convertArrayType(const clang::ArrayType *AT); + const llvm::abi::Type *convertVectorType(const clang::VectorType *VT); + const llvm::abi::Type *convertRecordType(const clang::RecordType *RT); + const llvm::abi::Type *convertEnumType(const clang::EnumType *ET); + const llvm::abi::Type *convertComplexType(const ComplexType *CT); + const llvm::abi::Type * + convertMemberPointerType(const clang::MemberPointerType *MPT); + const llvm::abi::Type *convertMatrixType(const ConstantMatrixType *MT); + + const llvm::abi::RecordType *convertStructType(const clang::RecordDecl *RD); + const llvm::abi::RecordType *convertUnionType(const clang::RecordDecl *RD); + const llvm::abi::Type *createPointerTypeForPointee(QualType PointeeType); + const llvm::abi::RecordType *convertCXXRecordType(const CXXRecordDecl *RD); + + void computeFieldInfo(const clang::RecordDecl *RD, + SmallVectorImpl<llvm::abi::FieldInfo> &Fields, + const clang::ASTRecordLayout &Layout); + + llvm::TypeSize getTypeSize(clang::QualType QT) const; + llvm::Align getTypeAlign(clang::QualType QT) const; + uint64_t getPointerSize() const; + uint64_t getPointerAlign() const; + +public: + explicit QualTypeMapper(clang::ASTContext &Ctx, const llvm::DataLayout &DL, + llvm::BumpPtrAllocator &Alloc) + : ASTCtx(Ctx), DL(DL), Builder(Alloc) {} + + const llvm::abi::Type *convertType(clang::QualType QT); + + void clearCache() { TypeCache.clear(); } + + llvm::abi::TypeBuilder getTypeBuilder() { return Builder; } +}; + +} // namespace CodeGen +} // namespace clang + +#endif // CLANG_LIB_CODEGEN_QUALTYPE_MAPPER_H _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
