================
@@ -0,0 +1,556 @@
+//==---- 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/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;
+ 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 (isa<BlockPointerType>(QT.getTypePtr()))
+ return createPointerTypeForPointee(ASTCtx.VoidPtrTy);
+ else if (isa<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,
+ ASTCtx.getTypeSize(QT), 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();
+ bool IsSigned = BIT->isSigned();
+ llvm::Align TypeAlign = getTypeAlign(QT);
+ return Builder.getIntegerType(RawNumBits, TypeAlign, IsSigned, true);
+ } 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
+ llvm_unreachable("Unsupported type for ABI lowering!");
+
+ if (Result)
+ 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, 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),
+ BT->isSignedInteger(), 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));
+
+ 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());
+ 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());
+ // Fallback for other array types
+ return Builder.getArrayType(ElementType, 1, Size);
+}
+
+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);
+ ElementType =
+ Builder.getIntegerType(BW, llvm::Align(BW / 8), IT->isSigned());
+ } else if (BW < 8 && BW != 1)
+ ElementType = Builder.getIntegerType(8, llvm::Align(1), IT->isSigned());
+ }
+
+ 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;
+ }
+ }
+ // For larger vectors, keep exact element count
+
+ 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 different 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 different 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();
+ bool canPassInRegs = false;
+ if (RD) {
+ canPassInRegs = RD->canPassInRegisters();
+ }
+ if (!RD) {
+ SmallVector<llvm::abi::FieldInfo, 0> Fields;
+ return Builder.getRecordType(Fields, llvm::TypeSize::getFixed(0),
+ llvm::Align(1),
+ llvm::abi::StructPacking::Default, {}, {},
+ llvm::abi::RecordFlags::None);
----------------
nikic wrote:
```suggestion
llvm::Align(1));
```
Can use the defaults here.
https://github.com/llvm/llvm-project/pull/174634
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits