================ @@ -0,0 +1,560 @@ +//==---- 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 "clang/CodeGen/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/Error.h" +#include "llvm/Support/TypeSize.h" +#include "llvm/Support/raw_ostream.h" + +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; + if (const auto *BT = dyn_cast<BuiltinType>(QT.getTypePtr())) + Result = convertBuiltinType(BT); + else if (const auto *PT = dyn_cast<PointerType>(QT.getTypePtr())) + Result = convertPointerType(PT); + else if (const auto *RT = dyn_cast<ReferenceType>(QT.getTypePtr())) + Result = convertReferenceType(RT); + else if (const auto *AT = dyn_cast<ArrayType>(QT.getTypePtr())) + Result = convertArrayType(AT); + else if (const auto *VT = dyn_cast<VectorType>(QT.getTypePtr())) + Result = convertVectorType(VT); + else if (const auto *RT = dyn_cast<RecordType>(QT.getTypePtr())) + Result = convertRecordType(RT); + else if (const auto *ET = dyn_cast<EnumType>(QT.getTypePtr())) + Result = convertEnumType(ET); + else if (const auto *CT = dyn_cast<ComplexType>(QT.getTypePtr())) + Result = convertComplexType(CT); + else if (const auto *AT = dyn_cast<AtomicType>(QT.getTypePtr())) + return convertType(AT->getValueType()); + else if (const auto *BPT = dyn_cast<BlockPointerType>(QT.getTypePtr())) + return createPointerTypeForPointee(ASTCtx.VoidPtrTy); + else if (const auto *PipeT = dyn_cast<PipeType>(QT.getTypePtr())) + Result = createPointerTypeForPointee(ASTCtx.VoidPtrTy); + else if (const auto *MT = dyn_cast<ConstantMatrixType>(QT.getTypePtr())) { + const llvm::abi::Type *ElementType = convertType(MT->getElementType()); + uint64_t NumElements = MT->getNumRows() * MT->getNumColumns(); + return Builder.getArrayType(ElementType, NumElements, true); + } else if (const auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) { + Result = convertMemberPointerType(MPT); + } else if (const auto *BIT = dyn_cast<BitIntType>(QT.getTypePtr())) { + unsigned RawNumBits = BIT->getNumBits(); + unsigned ABINumBits = ASTCtx.getTargetInfo().getBitIntWidth(RawNumBits); + + bool IsSigned = BIT->isSigned(); + llvm::Align TypeAlign = getTypeAlign(QT); + return Builder.getIntegerType(RawNumBits, TypeAlign, IsSigned, false, true, + ABINumBits); + } else if (isa<ObjCObjectType>(QT.getTypePtr()) || + isa<ObjCObjectPointerType>(QT.getTypePtr())) { + // Objective-C objects are represented as pointers in the ABI + auto PointerSize = + ASTCtx.getTargetInfo().getPointerWidth(QT.getAddressSpace()); + llvm::Align PointerAlign = + llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(LangAS::Default)); + return Builder.getPointerType( + PointerSize, llvm::Align(PointerAlign.value() / 8), + ASTCtx.getTargetInfo().getTargetAddressSpace(QT.getAddressSpace())); + } else + QT.dump(); + + 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), false, true); + 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), + BT->isSignedInteger()); + + 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)); + + case BuiltinType::OCLImage1dRO: + case BuiltinType::OCLImage1dWO: + case BuiltinType::OCLImage1dRW: + case BuiltinType::OCLImage1dArrayRO: + case BuiltinType::OCLImage1dArrayWO: + case BuiltinType::OCLImage1dArrayRW: + case BuiltinType::OCLImage1dBufferRO: + case BuiltinType::OCLImage1dBufferWO: + case BuiltinType::OCLImage1dBufferRW: + case BuiltinType::OCLImage2dRO: + case BuiltinType::OCLImage2dWO: + case BuiltinType::OCLImage2dRW: + case BuiltinType::OCLImage2dArrayRO: + case BuiltinType::OCLImage2dArrayWO: + case BuiltinType::OCLImage2dArrayRW: + case BuiltinType::OCLImage2dDepthRO: + case BuiltinType::OCLImage2dDepthWO: + case BuiltinType::OCLImage2dDepthRW: + case BuiltinType::OCLImage2dArrayDepthRO: + case BuiltinType::OCLImage2dArrayDepthWO: + case BuiltinType::OCLImage2dArrayDepthRW: + case BuiltinType::OCLImage2dMSAARO: + case BuiltinType::OCLImage2dMSAAWO: + case BuiltinType::OCLImage2dMSAARW: + case BuiltinType::OCLImage2dArrayMSAARO: + case BuiltinType::OCLImage2dArrayMSAAWO: + case BuiltinType::OCLImage2dArrayMSAARW: + case BuiltinType::OCLImage2dMSAADepthRO: + case BuiltinType::OCLImage2dMSAADepthWO: + case BuiltinType::OCLImage2dMSAADepthRW: + case BuiltinType::OCLImage2dArrayMSAADepthRO: + case BuiltinType::OCLImage2dArrayMSAADepthWO: + case BuiltinType::OCLImage2dArrayMSAADepthRW: + case BuiltinType::OCLImage3dRO: + case BuiltinType::OCLImage3dWO: + case BuiltinType::OCLImage3dRW: + return createPointerTypeForPointee(QT); + + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: + case BuiltinType::OCLQueue: + return createPointerTypeForPointee(QT); + + default: + // Unhandled BuiltinTypes are treated as unsigned integers. + return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)), + getTypeAlign(QualType(BT, 0)), false); + } +} + +/// 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()); + + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { + auto NumElements = CAT->getZExtSize(); + return Builder.getArrayType(ElementType, NumElements); + } + if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT)) + return Builder.getArrayType(ElementType, 0); + if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) + return createPointerTypeForPointee(VAT->getPointeeType()); + // Fallback for other array types + return Builder.getArrayType(ElementType, 1); +} + +const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) { + const llvm::abi::Type *ElementType = convertType(VT->getElementType()); + QualType VectorQualType(VT, 0); + + // Handle element size adjustments for sub-byte types + if (auto *IT = llvm::dyn_cast<llvm::abi::IntegerType>(ElementType)) { + unsigned BW = IT->getSizeInBits().getFixedValue(); + if (BW != 1 && (BW & 7)) { + BW = llvm::bit_ceil(BW); + BW = std::clamp(BW, 8u, 64u); + bool Signed = IT->isSigned(); + ElementType = Builder.getIntegerType(BW, llvm::Align(BW / 8), Signed); + } else if (BW < 8 && BW != 1) { + bool Signed = IT->isSigned(); + ElementType = Builder.getIntegerType(8, llvm::Align(1), Signed); + } + } ---------------- vortex73 wrote:
Um, I don't believe I use getBitIntWidth anywhere yet... https://github.com/llvm/llvm-project/pull/140112 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits