================
@@ -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:
----------------
nikic wrote:

I think it's important to avoid this `default`, as there are lots of builtin 
types, and it's easy to miss something important.

We should do this similar to CodeGenTypes and make use of helper includes like 
in:
https://github.com/llvm/llvm-project/blob/48565d9e7224c29c991674769822ab61a89bc9d2/clang/lib/CodeGen/CodeGenTypes.cpp#L511-L516

I think it would be fine to llvm_unreachable some of the types that aren't 
relevant for our initial target of x86, but they should be explicit "not 
implemented yet" TODOs rather than silently falling back to wrong behavior.

https://github.com/llvm/llvm-project/pull/174634
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to