================ @@ -0,0 +1,586 @@ +//==---- 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, or nullptr on error +const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) { + // Canonicalize type and strip qualifiers + // This ensures consistent type representation across different contexts + 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 = nullptr; + 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: + Result = convertBuiltinType(cast<BuiltinType>(QT)); + break; + case Type::Pointer: + Result = + createPointerTypeForPointee(cast<PointerType>(QT)->getPointeeType()); + break; + case Type::LValueReference: + case Type::RValueReference: + Result = + createPointerTypeForPointee(cast<ReferenceType>(QT)->getPointeeType()); + break; + case Type::ConstantArray: + case Type::ArrayParameter: + case Type::IncompleteArray: + case Type::VariableArray: + Result = convertArrayType(cast<ArrayType>(QT)); + break; + case Type::Vector: + case Type::ExtVector: + Result = convertVectorType(cast<VectorType>(QT)); + break; + case Type::Record: + Result = convertRecordType(cast<RecordType>(QT)); + break; + case Type::Enum: + Result = convertEnumType(cast<EnumType>(QT)); + break; + case Type::Complex: + Result = convertComplexType(cast<ComplexType>(QT)); + break; + case Type::Atomic: + return convertType(cast<AtomicType>(QT)->getValueType()); + case Type::BlockPointer: + return createPointerTypeForPointee(ASTCtx.VoidPtrTy); + case Type::Pipe: + Result = createPointerTypeForPointee(ASTCtx.VoidPtrTy); + break; + 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: + Result = convertMemberPointerType(cast<MemberPointerType>(QT)); + break; + 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(LangAS::Default) / + 8), + ASTCtx.getTargetInfo().getTargetAddressSpace(QT.getAddressSpace())); + case Type::Auto: + case Type::DeducedTemplateSpecialization: + case Type::FunctionProto: + case Type::FunctionNoProto: + case Type::HLSLAttributedResource: + llvm::reportFatalInternalError("Type not supported in ABI lowering"); + } + + assert(Result && "convertType returned nullptr"); + TypeCache[QT] = Result; + return Result; +} + +/// 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. +/// +/// \param BT The BuiltinType to convert +/// \return Corresponding LLVM ABI integer, float, or void type +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"); + } +} + +/// Converts array types to LLVM ABI array representations. +/// Handles different 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(); + uint64_t LogicalSizeInBits = + NElems * ElementType->getSizeInBits().getFixedValue(); + + // Only round up for small vectors (≤ 64 bits) + if (LogicalSizeInBits <= 64) { + uint64_t ABISizeInBits = ASTCtx.getTypeSize(VectorQualType); + if (ABISizeInBits > LogicalSizeInBits) { + uint64_t ElementSizeInBits = ElementType->getSizeInBits().getFixedValue(); + NElems = ABISizeInBits / ElementSizeInBits; ---------------- nikic wrote:
Hm, this code looks very suspect to me. If this kind of adjustment is necessary, I don't think it should be happening during the QualType -> ABIType mapping, but sometime later. I'd omit this code for now, until we need it. https://github.com/llvm/llvm-project/pull/174634 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
