https://github.com/kumarak updated https://github.com/llvm/llvm-project/pull/204185
>From 260c76b7365ac3421c899cddf0beb1fb51992d42 Mon Sep 17 00:00:00 2001 From: AkshayK <[email protected]> Date: Tue, 16 Jun 2026 11:14:06 -0400 Subject: [PATCH 1/3] [CIR] Drive pointer and vptr width from a CIR-native data-layout entry PointerType and VPtrType hardcoded size/alignment to 64/8, aborting record layout on 32-bit-pointer targets such as nvptx/spirv32. Attach a CIR-native cir.ptr data-layout entry at module setup and read the pointer width from it, so the CIR type system needs no LLVM-dialect dependency; the entry is stripped during CIR->LLVM lowering. 64-bit targets are unchanged. --- clang/lib/CIR/CodeGen/CIRGenerator.cpp | 25 ++++++++- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 56 +++++++++++++++++-- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 17 ++++++ .../test/CIR/CodeGen/pointer-width-32bit.cpp | 44 +++++++++++++++ 4 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 clang/test/CIR/CodeGen/pointer-width-32bit.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp index d4fcbb6e42f3e..61efaebad9b82 100644 --- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp @@ -21,6 +21,7 @@ #include "clang/AST/DeclGroup.h" #include "clang/CIR/CIRGenerator.h" #include "clang/CIR/InitAllDialects.h" +#include "clang/CIR/MissingFeatures.h" #include "llvm/IR/DataLayout.h" using namespace cir; @@ -42,7 +43,29 @@ static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) { mlir::MLIRContext *mlirContext = mod.getContext(); mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, mlirContext); - mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec); + + // Add a CIR-native pointer data-layout entry so cir.ptr / cir.vptr size and + // alignment are driven by the data layout rather than hardcoded. + // The value stores {size-in-bits, abi-align-in-bits} keyed on cir.ptr. + // + // TODO(cir): Only the default address space is recorded and + // address-space-dependent pointer sizes are not modeled yet. Emit + // per-address-space entries. + assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); + constexpr unsigned kBitsInByte = 8; + unsigned ptrSizeBits = dl.getPointerSizeInBits(/*AS=*/0); + unsigned ptrAlignBits = + dl.getPointerABIAlignment(/*AS=*/0).value() * kBitsInByte; + auto ptrKey = cir::PointerType::get(cir::VoidType::get(mlirContext)); + auto ptrVal = mlir::DenseI32ArrayAttr::get( + mlirContext, + {static_cast<int32_t>(ptrSizeBits), static_cast<int32_t>(ptrAlignBits)}); + llvm::SmallVector<mlir::DataLayoutEntryInterface> entries( + dlSpec.getEntries().begin(), dlSpec.getEntries().end()); + entries.push_back(mlir::DataLayoutEntryAttr::get(ptrKey, ptrVal)); + + mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, + mlir::DataLayoutSpecAttr::get(mlirContext, entries)); } void CIRGenerator::Initialize(ASTContext &astContext) { diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 9c2a40e3681aa..04da6c85bbbb1 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -580,20 +580,62 @@ void RecordType::removeABIConversionNamePrefix() { // Data Layout information for types //===----------------------------------------------------------------------===// +// A CIR-native pointer data-layout entry stores {size-in-bits, +// abi-align-in-bits} as a dense i32 array keyed on a cir.ptr type (see +// setMLIRDataLayout in CIRGenerator). +namespace { +constexpr static uint64_t kBitsInByte = 8; + +// Defaults used only when the module carries no cir.ptr data-layout entry +// (e.g. CIR parsed from text without a data layout). These mirror the MLIR LLVM +// dialect's pointer defaults. +constexpr static uint64_t kDefaultPointerSizeBits = 64; +constexpr static uint64_t kDefaultPointerAlignment = 8; + +enum class CIRPtrDLPos { Size = 0, AbiAlign = 1 }; + +// Returns the requested field of the cir.ptr data-layout entry. +std::optional<uint64_t> getPointerSpecValue(mlir::DataLayoutEntryListRef params, + CIRPtrDLPos pos) { + for (mlir::DataLayoutEntryInterface entry : params) { + if (!entry.isTypeEntry()) + continue; + auto spec = mlir::dyn_cast<mlir::DenseI32ArrayAttr>(entry.getValue()); + assert(spec && spec.size() == 2 && + "malformed cir.ptr data layout entry: expected a pair of i32 " + "{size-in-bits, abi-align-in-bits}"); + return static_cast<uint64_t>(spec[static_cast<int>(pos)]); + } + return std::nullopt; +} +} // namespace + llvm::TypeSize PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, ::mlir::DataLayoutEntryListRef params) const { + // The pointer width comes from the CIR-native data-layout entry keyed on + // cir.ptr, which records the width for the default address space; fall back + // to 64 bits if the module carries no such entry. // FIXME: improve this in face of address spaces assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); - return llvm::TypeSize::getFixed(64); + if (std::optional<uint64_t> size = + getPointerSpecValue(params, CIRPtrDLPos::Size)) + return llvm::TypeSize::getFixed(*size); + return llvm::TypeSize::getFixed(kDefaultPointerSizeBits); } uint64_t PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout, ::mlir::DataLayoutEntryListRef params) const { + // As with the size, the alignment is taken from the default-address-space + // cir.ptr data-layout entry. Address-space-dependent alignments are not yet + // modeled. // FIXME: improve this in face of address spaces assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); - return 8; + if (std::optional<uint64_t> align = + getPointerSpecValue(params, CIRPtrDLPos::AbiAlign)) + return *align / kBitsInByte; + return kDefaultPointerAlignment; } llvm::TypeSize @@ -1112,14 +1154,16 @@ DataMemberType::getABIAlignment(const ::mlir::DataLayout &dataLayout, llvm::TypeSize VPtrType::getTypeSizeInBits(const mlir::DataLayout &dataLayout, mlir::DataLayoutEntryListRef params) const { - // FIXME: consider size differences under different ABIs - return llvm::TypeSize::getFixed(64); + // The vtable pointer is an ordinary data pointer; route the query through a + // cir.ptr so it picks up the same data-layout-driven width. + return dataLayout.getTypeSizeInBits( + cir::PointerType::get(cir::VoidType::get(getContext()))); } uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout, mlir::DataLayoutEntryListRef params) const { - // FIXME: consider alignment differences under different ABIs - return 8; + return dataLayout.getTypeABIAlignment( + cir::PointerType::get(cir::VoidType::get(getContext()))); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index e0fc9e58ed4b7..00c94b37e1a6c 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3794,6 +3794,23 @@ void ConvertCIRToLLVMPass::runOnOperation() { if (failed(applyPartialConversion(ops, target, std::move(patterns)))) signalPassFailure(); + // The CIR-native pointer data-layout entry (keyed on cir.ptr) drives pointer + // widths during CIR codegen and lowering, but cir.ptr has no meaning once the + // module is translated to LLVM IR. Drop it so the resulting data layout only + // references LLVM types. + if (auto dlSpec = mlir::dyn_cast_or_null<mlir::DataLayoutSpecAttr>( + module->getAttr(mlir::DLTIDialect::kDataLayoutAttrName))) { + llvm::SmallVector<mlir::DataLayoutEntryInterface> kept; + for (mlir::DataLayoutEntryInterface entry : dlSpec.getEntries()) { + if (entry.isTypeEntry() && + mlir::isa<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey()))) + continue; + kept.push_back(entry); + } + module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, + mlir::DataLayoutSpecAttr::get(module.getContext(), kept)); + } + // Emit the llvm.global_ctors array. buildCtorDtorList(module, cir::CIRDialect::getGlobalCtorsAttrName(), "llvm.global_ctors", [](mlir::Attribute attr) { diff --git a/clang/test/CIR/CodeGen/pointer-width-32bit.cpp b/clang/test/CIR/CodeGen/pointer-width-32bit.cpp new file mode 100644 index 0000000000000..15f3ec92d7e16 --- /dev/null +++ b/clang/test/CIR/CodeGen/pointer-width-32bit.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++20 -triple nvptx-nvidia-cuda -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -std=c++20 -triple nvptx-nvidia-cuda -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -std=c++20 -triple nvptx-nvidia-cuda -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +// On a target with 32-bit pointers (e.g. nvptx) both a data pointer (!cir.ptr) +// and the vtable pointer (!cir.vptr) are 4 bytes wide. The pointer width is +// carried by a CIR-native data-layout entry keyed on cir.ptr, so the field +// following a pointer lands at the AST-mandated offset. Sizing pointers as a +// hardcoded 64 bits previously tripped the record layout builder (insertPadding: +// assertion `offset >= size`) on every record containing a pointer. + +struct S { + int *p; + int x; +}; + +S s; + +class A { +public: + virtual void f(); + int x; +}; + +void A::f() {} + +// The module carries a CIR-native pointer data-layout entry ({size, abi-align} +// in bits) that drives both cir.ptr and cir.vptr widths. The 4-byte pointer is +// immediately followed by 'x' at offset 4 with no padding, and each record is +// 4-byte aligned. +// CIR-DAG: !rec_S = !cir.struct<"S" {!cir.ptr<!s32i>, !s32i}> +// CIR-DAG: !rec_A = !cir.struct<class "A" {!cir.vptr, !s32i}> +// CIR-DAG: !cir.ptr<!cir.void> = array<i32: 32, 32> +// CIR: cir.global external @s = #cir.zero : !rec_S {alignment = 4 : i64} +// CIR: cir.global{{.*}}@_ZTV1A = #cir.vtable<{{.*}}{alignment = 4 : i64} + +// LLVM: @s = global %struct.S zeroinitializer, align 4 +// LLVM: @_ZTV1A = global { [3 x ptr] } {{.*}}, align 4 + +// OGCG: @s = global %struct.S zeroinitializer, align 4 +// OGCG: @_ZTV1A = {{.*}}constant { [3 x ptr] } {{.*}}, align 4 >From 8dea96ae346b37230997f80fef60a0fb4c2d98c0 Mon Sep 17 00:00:00 2001 From: AkshayK <[email protected]> Date: Mon, 29 Jun 2026 17:35:07 -0400 Subject: [PATCH 2/3] [CIR] Use #ptr.spec for pointer data-layout entry --- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 3 +- clang/lib/CIR/CMakeLists.txt | 1 + clang/lib/CIR/CodeGen/CIRGenerator.cpp | 25 +++--- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 87 ++++++++++++------- clang/lib/CIR/Dialect/IR/CMakeLists.txt | 1 + clang/lib/CIR/RegisterAllDialects.cpp | 4 +- .../test/CIR/CodeGen/pointer-width-32bit.cpp | 6 +- clang/test/CIR/IR/pointer-data-layout.cir | 16 ++++ 8 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 clang/test/CIR/IR/pointer-data-layout.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 95be236854338..a397a06a7d082 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -239,7 +239,8 @@ def CIR_ComplexType : CIR_Type<"Complex", "complex", [ //===----------------------------------------------------------------------===// def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ - DeclareTypeInterfaceMethods<DataLayoutTypeInterface>, + DeclareTypeInterfaceMethods<DataLayoutTypeInterface, + ["verifyEntries", "areCompatible"]>, DeclareTypeInterfaceMethods<CIR_SizedTypeInterface> ]> { let summary = "CIR pointer type"; diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt index f215c927565de..4ff5b24c21fe8 100644 --- a/clang/lib/CIR/CMakeLists.txt +++ b/clang/lib/CIR/CMakeLists.txt @@ -26,4 +26,5 @@ add_clang_library(CIRRegisterAllDialects CIROpenACCSupport CIROpenMPSupport MLIRDLTIDialect + MLIRPtrDialect ) diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp index 61efaebad9b82..0e133b35a7bc8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp @@ -15,6 +15,8 @@ #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/Dialect/Ptr/IR/PtrAttrs.h" +#include "mlir/Dialect/Ptr/IR/PtrDialect.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Target/LLVMIR/Import.h" @@ -44,25 +46,21 @@ static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) { mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, mlirContext); - // Add a CIR-native pointer data-layout entry so cir.ptr / cir.vptr size and - // alignment are driven by the data layout rather than hardcoded. - // The value stores {size-in-bits, abi-align-in-bits} keyed on cir.ptr. - // - // TODO(cir): Only the default address space is recorded and - // address-space-dependent pointer sizes are not modeled yet. Emit - // per-address-space entries. + // Record cir.ptr size/alignment as a #ptr.spec entry keyed on cir.ptr. + // TODO(cir): only the default address space is recorded. assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); constexpr unsigned kBitsInByte = 8; unsigned ptrSizeBits = dl.getPointerSizeInBits(/*AS=*/0); - unsigned ptrAlignBits = + unsigned ptrAbiBits = dl.getPointerABIAlignment(/*AS=*/0).value() * kBitsInByte; + unsigned ptrPrefBits = + dl.getPointerPrefAlignment(/*AS=*/0).value() * kBitsInByte; auto ptrKey = cir::PointerType::get(cir::VoidType::get(mlirContext)); - auto ptrVal = mlir::DenseI32ArrayAttr::get( - mlirContext, - {static_cast<int32_t>(ptrSizeBits), static_cast<int32_t>(ptrAlignBits)}); + auto ptrSpec = mlir::ptr::SpecAttr::get(mlirContext, ptrSizeBits, ptrAbiBits, + ptrPrefBits); llvm::SmallVector<mlir::DataLayoutEntryInterface> entries( dlSpec.getEntries().begin(), dlSpec.getEntries().end()); - entries.push_back(mlir::DataLayoutEntryAttr::get(ptrKey, ptrVal)); + entries.push_back(mlir::DataLayoutEntryAttr::get(ptrKey, ptrSpec)); mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, mlir::DataLayoutSpecAttr::get(mlirContext, entries)); @@ -75,7 +73,8 @@ void CIRGenerator::Initialize(ASTContext &astContext) { mlirContext = std::make_unique<mlir::MLIRContext>(); cir::registerAllDialects(*mlirContext); - mlirContext->loadDialect<mlir::DLTIDialect, cir::CIRDialect>(); + mlirContext->loadDialect<mlir::DLTIDialect, mlir::ptr::PtrDialect, + cir::CIRDialect>(); mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>(); mlirContext->getOrLoadDialect<mlir::omp::OpenMPDialect>(); diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 04da6c85bbbb1..5d09994e6b047 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -13,6 +13,7 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h" +#include "mlir/Dialect/Ptr/IR/PtrAttrs.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/DialectImplementation.h" #include "mlir/IR/MLIRContext.h" @@ -580,64 +581,92 @@ void RecordType::removeABIConversionNamePrefix() { // Data Layout information for types //===----------------------------------------------------------------------===// -// A CIR-native pointer data-layout entry stores {size-in-bits, -// abi-align-in-bits} as a dense i32 array keyed on a cir.ptr type (see -// setMLIRDataLayout in CIRGenerator). +// The cir.ptr data-layout entry stores its width and alignment as a +// #ptr.spec attribute (see setMLIRDataLayout in CIRGenerator). namespace { constexpr static uint64_t kBitsInByte = 8; -// Defaults used only when the module carries no cir.ptr data-layout entry -// (e.g. CIR parsed from text without a data layout). These mirror the MLIR LLVM -// dialect's pointer defaults. +// Defaults used when the module carries no cir.ptr data-layout entry. constexpr static uint64_t kDefaultPointerSizeBits = 64; constexpr static uint64_t kDefaultPointerAlignment = 8; -enum class CIRPtrDLPos { Size = 0, AbiAlign = 1 }; - -// Returns the requested field of the cir.ptr data-layout entry. -std::optional<uint64_t> getPointerSpecValue(mlir::DataLayoutEntryListRef params, - CIRPtrDLPos pos) { +// Returns the cir.ptr data-layout spec, if the module carries one. +mlir::ptr::SpecAttr getPointerSpec(mlir::DataLayoutEntryListRef params) { for (mlir::DataLayoutEntryInterface entry : params) { if (!entry.isTypeEntry()) continue; - auto spec = mlir::dyn_cast<mlir::DenseI32ArrayAttr>(entry.getValue()); - assert(spec && spec.size() == 2 && - "malformed cir.ptr data layout entry: expected a pair of i32 " - "{size-in-bits, abi-align-in-bits}"); - return static_cast<uint64_t>(spec[static_cast<int>(pos)]); + if (auto spec = mlir::dyn_cast<mlir::ptr::SpecAttr>(entry.getValue())) + return spec; } - return std::nullopt; + return {}; } } // namespace llvm::TypeSize PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, ::mlir::DataLayoutEntryListRef params) const { - // The pointer width comes from the CIR-native data-layout entry keyed on - // cir.ptr, which records the width for the default address space; fall back - // to 64 bits if the module carries no such entry. + // Width comes from the #ptr.spec entry; default to 64 bits if absent. // FIXME: improve this in face of address spaces assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); - if (std::optional<uint64_t> size = - getPointerSpecValue(params, CIRPtrDLPos::Size)) - return llvm::TypeSize::getFixed(*size); + if (mlir::ptr::SpecAttr spec = getPointerSpec(params)) + return llvm::TypeSize::getFixed(spec.getSize()); return llvm::TypeSize::getFixed(kDefaultPointerSizeBits); } uint64_t PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout, ::mlir::DataLayoutEntryListRef params) const { - // As with the size, the alignment is taken from the default-address-space - // cir.ptr data-layout entry. Address-space-dependent alignments are not yet - // modeled. + // Alignment comes from the #ptr.spec entry; default to 8 bytes if absent. // FIXME: improve this in face of address spaces assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); - if (std::optional<uint64_t> align = - getPointerSpecValue(params, CIRPtrDLPos::AbiAlign)) - return *align / kBitsInByte; + if (mlir::ptr::SpecAttr spec = getPointerSpec(params)) + return spec.getAbi() / kBitsInByte; return kDefaultPointerAlignment; } +llvm::LogicalResult +PointerType::verifyEntries(mlir::DataLayoutEntryListRef entries, + mlir::Location loc) const { + // Every cir.ptr data-layout entry must carry a #ptr.spec value. The key is + // not matched here: only the default address space is modeled, so a single + // entry is expected (see the TODO in areCompatible). + for (mlir::DataLayoutEntryInterface entry : entries) { + if (!entry.isTypeEntry()) + continue; + if (!mlir::isa<mlir::ptr::SpecAttr>(entry.getValue())) { + auto key = mlir::cast<mlir::Type>(entry.getKey()); + return mlir::emitError(loc) << "expected layout attribute for " << key + << " to be a #ptr.spec attribute"; + } + } + return mlir::success(); +} + +bool PointerType::areCompatible( + mlir::DataLayoutEntryListRef oldLayout, + mlir::DataLayoutEntryListRef newLayout, mlir::DataLayoutSpecInterface, + const mlir::DataLayoutIdentifiedEntryMap &) const { + // A nested spec may override only if it keeps the same size and a + // compatible ABI alignment. + // TODO(cir): assumes a single default-AS entry; match by address space + // once per-AS pointer specs are emitted. + uint64_t size = kDefaultPointerSizeBits; + uint64_t abi = kDefaultPointerAlignment * kBitsInByte; + if (mlir::ptr::SpecAttr oldSpec = getPointerSpec(oldLayout)) { + size = oldSpec.getSize(); + abi = oldSpec.getAbi(); + } + for (mlir::DataLayoutEntryInterface newEntry : newLayout) { + if (!newEntry.isTypeEntry()) + continue; + auto newSpec = mlir::cast<mlir::ptr::SpecAttr>(newEntry.getValue()); + if (size != newSpec.getSize() || abi < newSpec.getAbi() || + abi % newSpec.getAbi() != 0) + return false; + } + return true; +} + llvm::TypeSize StructType::getTypeSizeInBits(const mlir::DataLayout &dataLayout, mlir::DataLayoutEntryListRef params) const { diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt index c8205ebeabf6c..eaf43401f41b7 100644 --- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt @@ -18,6 +18,7 @@ add_clang_library(MLIRCIR MLIRCIRInterfaces MLIRDLTIDialect MLIRDataLayoutInterfaces + MLIRPtrDialect MLIRFuncDialect MLIRLoopLikeInterface MLIRCIRInterfaces diff --git a/clang/lib/CIR/RegisterAllDialects.cpp b/clang/lib/CIR/RegisterAllDialects.cpp index 8c2961bdebbaa..7a3ecb6ce30ef 100644 --- a/clang/lib/CIR/RegisterAllDialects.cpp +++ b/clang/lib/CIR/RegisterAllDialects.cpp @@ -11,6 +11,7 @@ #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/Dialect/Ptr/IR/PtrDialect.h" #include "mlir/IR/BuiltinDialect.h" #include "mlir/IR/MLIRContext.h" @@ -22,7 +23,8 @@ namespace cir { void registerAllDialects(mlir::DialectRegistry ®istry) { registry.insert<mlir::BuiltinDialect, cir::CIRDialect, mlir::DLTIDialect, - mlir::omp::OpenMPDialect, mlir::acc::OpenACCDialect>(); + mlir::ptr::PtrDialect, mlir::omp::OpenMPDialect, + mlir::acc::OpenACCDialect>(); // Register extensions to integrate CIR types with OpenACC and OpenMP. cir::omp::registerOpenMPExtensions(registry); cir::acc::registerOpenACCExtensions(registry); diff --git a/clang/test/CIR/CodeGen/pointer-width-32bit.cpp b/clang/test/CIR/CodeGen/pointer-width-32bit.cpp index 15f3ec92d7e16..826fe5e6fcee1 100644 --- a/clang/test/CIR/CodeGen/pointer-width-32bit.cpp +++ b/clang/test/CIR/CodeGen/pointer-width-32bit.cpp @@ -7,7 +7,7 @@ // On a target with 32-bit pointers (e.g. nvptx) both a data pointer (!cir.ptr) // and the vtable pointer (!cir.vptr) are 4 bytes wide. The pointer width is -// carried by a CIR-native data-layout entry keyed on cir.ptr, so the field +// carried by a #ptr.spec data-layout entry keyed on cir.ptr, so the field // following a pointer lands at the AST-mandated offset. Sizing pointers as a // hardcoded 64 bits previously tripped the record layout builder (insertPadding: // assertion `offset >= size`) on every record containing a pointer. @@ -27,13 +27,13 @@ class A { void A::f() {} -// The module carries a CIR-native pointer data-layout entry ({size, abi-align} +// The module carries a #ptr.spec pointer data-layout entry (size/abi/preferred // in bits) that drives both cir.ptr and cir.vptr widths. The 4-byte pointer is // immediately followed by 'x' at offset 4 with no padding, and each record is // 4-byte aligned. // CIR-DAG: !rec_S = !cir.struct<"S" {!cir.ptr<!s32i>, !s32i}> // CIR-DAG: !rec_A = !cir.struct<class "A" {!cir.vptr, !s32i}> -// CIR-DAG: !cir.ptr<!cir.void> = array<i32: 32, 32> +// CIR-DAG: !cir.ptr<!cir.void> = #ptr.spec<size = 32, abi = 32, preferred = 32> // CIR: cir.global external @s = #cir.zero : !rec_S {alignment = 4 : i64} // CIR: cir.global{{.*}}@_ZTV1A = #cir.vtable<{{.*}}{alignment = 4 : i64} diff --git a/clang/test/CIR/IR/pointer-data-layout.cir b/clang/test/CIR/IR/pointer-data-layout.cir new file mode 100644 index 0000000000000..207445d389284 --- /dev/null +++ b/clang/test/CIR/IR/pointer-data-layout.cir @@ -0,0 +1,16 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +// The cir.ptr data-layout entry carries an mlir::ptr::SpecAttr (#ptr.spec). +// A well-formed entry round-trips without diagnostics. +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void> = #ptr.spec<size = 32, abi = 32, preferred = 32>>} { +} + +// ----- + +// PointerType::verifyEntries rejects a cir.ptr entry whose value is not a +// #ptr.spec attribute. +// expected-error @below {{expected layout attribute for '!cir.ptr<!cir.void>' to be a #ptr.spec attribute}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void> = dense<32> : vector<2xi64>>} { +} >From 0e445773dce0e7b678e53f55e722b1b0ce05cc82 Mon Sep 17 00:00:00 2001 From: AkshayK <[email protected]> Date: Thu, 2 Jul 2026 23:49:33 -0400 Subject: [PATCH 3/3] [CIR] Use a CIR-native #cir.ptr_spec for the pointer data-layout entry Replace #ptr.spec with a CIR-owned #cir.ptr_spec attribute as the value of the cir.ptr data-layout entry, so the CIR dialect no longer registers or parses the MLIR ptr dialect. The verifier requires a !cir.void pointee and gates address-space-specific entries; pointer queries gain preferred-alignment and index-bitwidth support with a 64-bit fallback when no entry is present. --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 51 +++++++++++ .../include/clang/CIR/Dialect/IR/CIRTypes.td | 3 +- clang/lib/CIR/CodeGen/CIRGenerator.cpp | 12 ++- clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 22 +++++ clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 86 ++++++++++++------- clang/lib/CIR/RegisterAllDialects.cpp | 3 +- .../test/CIR/CodeGen/pointer-width-32bit.cpp | 6 +- clang/test/CIR/IR/pointer-data-layout.cir | 52 ++++++++++- 8 files changed, 185 insertions(+), 50 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index f5f4f28f8993c..07c26b42fca01 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -1041,6 +1041,57 @@ def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace", let canHaveIllegalCXXABIType = 0; } +//===----------------------------------------------------------------------===// +// PtrSpecAttr +//===----------------------------------------------------------------------===// + +def CIR_PtrSpecAttr : CIR_Attr<"PtrSpec", "ptr_spec"> { + let summary = "!cir.ptr data layout spec"; + let description = [{ + Defines the data layout of `!cir.ptr`, mirroring `#ptr.spec`. Entries are + currently limited to the default address space; per-address-space entries + will follow. This attribute has 4 fields: + - [Required] size: size of the pointer in bits. + - [Required] abi: ABI-required alignment for the pointer in bits. + - [Required] preferred: preferred alignment for the pointer in bits. + - [Optional] index: bitwidth that should be used when performing index + computations for the type. Setting the field to `kOptionalSpecValue` + means the index bitwidth follows `size`. + + The attribute verifies that all present values are divisible by 8 (number + of bits in a byte), and that `preferred` >= `abi`. + + It is used as the value of a `#dlti.dl_entry` whose key is the canonical + `!cir.ptr<!cir.void>` type of the address space it describes, e.g.: + + ```mlir + #dlti.dl_entry<!cir.ptr<!cir.void>, + #cir.ptr_spec<size = 64, abi = 64, preferred = 64>> + ``` + }]; + let parameters = (ins + "uint32_t":$size, + "uint32_t":$abi, + "uint32_t":$preferred, + DefaultValuedParameter<"uint32_t", "kOptionalSpecValue">:$index + ); + let skipDefaultBuilders = 1; + let builders = [ + AttrBuilder<(ins "uint32_t":$size, "uint32_t":$abi, "uint32_t":$preferred, + CArg<"uint32_t", "kOptionalSpecValue">:$index), [{ + return $_get($_ctxt, size, abi, preferred, index); + }]> + ]; + let assemblyFormat = "`<` struct(params) `>`"; + let extraClassDeclaration = [{ + /// Constant for specifying a spec entry is optional. + static constexpr uint32_t kOptionalSpecValue = + std::numeric_limits<uint32_t>::max(); + }]; + let genVerifyDecl = 1; + let canHaveIllegalCXXABIType = 0; +} + //===----------------------------------------------------------------------===// // ConstComplexAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index a397a06a7d082..480ff975cb45b 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -240,7 +240,8 @@ def CIR_ComplexType : CIR_Type<"Complex", "complex", [ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ DeclareTypeInterfaceMethods<DataLayoutTypeInterface, - ["verifyEntries", "areCompatible"]>, + ["getPreferredAlignment", "getIndexBitwidth", "areCompatible", + "verifyEntries"]>, DeclareTypeInterfaceMethods<CIR_SizedTypeInterface> ]> { let summary = "CIR pointer type"; diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp index 0e133b35a7bc8..3f3056930476d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp @@ -15,8 +15,6 @@ #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" -#include "mlir/Dialect/Ptr/IR/PtrAttrs.h" -#include "mlir/Dialect/Ptr/IR/PtrDialect.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Target/LLVMIR/Import.h" @@ -46,7 +44,7 @@ static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) { mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, mlirContext); - // Record cir.ptr size/alignment as a #ptr.spec entry keyed on cir.ptr. + // Record cir.ptr size/alignment as a #cir.ptr_spec entry keyed on cir.ptr. // TODO(cir): only the default address space is recorded. assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); constexpr unsigned kBitsInByte = 8; @@ -55,9 +53,10 @@ static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) { dl.getPointerABIAlignment(/*AS=*/0).value() * kBitsInByte; unsigned ptrPrefBits = dl.getPointerPrefAlignment(/*AS=*/0).value() * kBitsInByte; + unsigned ptrIndexBits = dl.getIndexSizeInBits(/*AS=*/0); auto ptrKey = cir::PointerType::get(cir::VoidType::get(mlirContext)); - auto ptrSpec = mlir::ptr::SpecAttr::get(mlirContext, ptrSizeBits, ptrAbiBits, - ptrPrefBits); + auto ptrSpec = cir::PtrSpecAttr::get(mlirContext, ptrSizeBits, ptrAbiBits, + ptrPrefBits, ptrIndexBits); llvm::SmallVector<mlir::DataLayoutEntryInterface> entries( dlSpec.getEntries().begin(), dlSpec.getEntries().end()); entries.push_back(mlir::DataLayoutEntryAttr::get(ptrKey, ptrSpec)); @@ -73,8 +72,7 @@ void CIRGenerator::Initialize(ASTContext &astContext) { mlirContext = std::make_unique<mlir::MLIRContext>(); cir::registerAllDialects(*mlirContext); - mlirContext->loadDialect<mlir::DLTIDialect, mlir::ptr::PtrDialect, - cir::CIRDialect>(); + mlirContext->loadDialect<mlir::DLTIDialect, cir::CIRDialect>(); mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>(); mlirContext->getOrLoadDialect<mlir::omp::OpenMPDialect>(); diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 8f235311dc5d9..a02298be0a8a2 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -172,6 +172,28 @@ bool TargetAddressSpaceAttr::isValidPtrIntCast( llvm_unreachable("isValidPtrIntCast for TargetAddressSpaceAttr NYI"); } +//===----------------------------------------------------------------------===// +// PtrSpecAttr definitions +//===----------------------------------------------------------------------===// + +LogicalResult PtrSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError, + uint32_t size, uint32_t abi, + uint32_t preferred, uint32_t index) { + constexpr unsigned kBitsInByte = 8; + if (size % kBitsInByte != 0) + return emitError() << "size entry must be divisible by 8"; + if (abi % kBitsInByte != 0) + return emitError() << "abi entry must be divisible by 8"; + if (preferred % kBitsInByte != 0) + return emitError() << "preferred entry must be divisible by 8"; + if (index != kOptionalSpecValue && index % kBitsInByte != 0) + return emitError() << "index entry must be divisible by 8"; + if (abi > preferred) + return emitError() << "preferred alignment is expected to be at least " + "as large as ABI alignment"; + return success(); +} + //===----------------------------------------------------------------------===// // General CIR parsing / printing //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 5d09994e6b047..8317bced170b7 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -13,7 +13,6 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h" -#include "mlir/Dialect/Ptr/IR/PtrAttrs.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/DialectImplementation.h" #include "mlir/IR/MLIRContext.h" @@ -582,7 +581,7 @@ void RecordType::removeABIConversionNamePrefix() { //===----------------------------------------------------------------------===// // The cir.ptr data-layout entry stores its width and alignment as a -// #ptr.spec attribute (see setMLIRDataLayout in CIRGenerator). +// #cir.ptr_spec attribute (see setMLIRDataLayout in CIRGenerator). namespace { constexpr static uint64_t kBitsInByte = 8; @@ -590,54 +589,78 @@ constexpr static uint64_t kBitsInByte = 8; constexpr static uint64_t kDefaultPointerSizeBits = 64; constexpr static uint64_t kDefaultPointerAlignment = 8; -// Returns the cir.ptr data-layout spec, if the module carries one. -mlir::ptr::SpecAttr getPointerSpec(mlir::DataLayoutEntryListRef params) { +/// Find the #cir.ptr_spec entry describing `type`. Only the default address +/// space is supported for now: every pointer, whatever its address space, +/// resolves to the default-address-space entry (null addrSpace key), or to a +/// synthesized default 64-bit spec when the data layout carries no !cir.ptr +/// entries at all. +cir::PtrSpecAttr getPointerSpec(mlir::DataLayoutEntryListRef params, + cir::PointerType type) { + // FIXME: improve this in face of address spaces + assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); for (mlir::DataLayoutEntryInterface entry : params) { if (!entry.isTypeEntry()) continue; - if (auto spec = mlir::dyn_cast<mlir::ptr::SpecAttr>(entry.getValue())) + auto key = + mlir::cast<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey())); + if (key.getAddrSpace()) + continue; + if (auto spec = mlir::dyn_cast<cir::PtrSpecAttr>(entry.getValue())) return spec; } - return {}; + return cir::PtrSpecAttr::get( + type.getContext(), kDefaultPointerSizeBits, + kDefaultPointerAlignment * kBitsInByte, + kDefaultPointerAlignment * kBitsInByte, kDefaultPointerSizeBits); } } // namespace llvm::TypeSize PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, ::mlir::DataLayoutEntryListRef params) const { - // Width comes from the #ptr.spec entry; default to 64 bits if absent. - // FIXME: improve this in face of address spaces - assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); - if (mlir::ptr::SpecAttr spec = getPointerSpec(params)) - return llvm::TypeSize::getFixed(spec.getSize()); - return llvm::TypeSize::getFixed(kDefaultPointerSizeBits); + return llvm::TypeSize::getFixed(getPointerSpec(params, *this).getSize()); } uint64_t PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout, ::mlir::DataLayoutEntryListRef params) const { - // Alignment comes from the #ptr.spec entry; default to 8 bytes if absent. - // FIXME: improve this in face of address spaces - assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS()); - if (mlir::ptr::SpecAttr spec = getPointerSpec(params)) - return spec.getAbi() / kBitsInByte; - return kDefaultPointerAlignment; + return getPointerSpec(params, *this).getAbi() / kBitsInByte; +} + +uint64_t PointerType::getPreferredAlignment( + const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + return getPointerSpec(params, *this).getPreferred() / kBitsInByte; +} + +std::optional<uint64_t> +PointerType::getIndexBitwidth(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + cir::PtrSpecAttr spec = getPointerSpec(params, *this); + if (spec.getIndex() == cir::PtrSpecAttr::kOptionalSpecValue) + return spec.getSize(); + return spec.getIndex(); } llvm::LogicalResult PointerType::verifyEntries(mlir::DataLayoutEntryListRef entries, mlir::Location loc) const { - // Every cir.ptr data-layout entry must carry a #ptr.spec value. The key is - // not matched here: only the default address space is modeled, so a single - // entry is expected (see the TODO in areCompatible). for (mlir::DataLayoutEntryInterface entry : entries) { if (!entry.isTypeEntry()) continue; - if (!mlir::isa<mlir::ptr::SpecAttr>(entry.getValue())) { - auto key = mlir::cast<mlir::Type>(entry.getKey()); - return mlir::emitError(loc) << "expected layout attribute for " << key - << " to be a #ptr.spec attribute"; - } + auto key = mlir::cast<PointerType>(mlir::cast<mlir::Type>(entry.getKey())); + if (!mlir::isa<cir::PtrSpecAttr>(entry.getValue())) + return mlir::emitError(loc) + << "expected layout attribute for " << key + << " to be a #cir.ptr_spec attribute"; + if (!mlir::isa<cir::VoidType>(key.getPointee())) + return mlir::emitError(loc) << "expected !cir.ptr data layout entry for " + << key << " to use !cir.void as pointee"; + // Gate: per-address-space pointer layouts are not supported yet. + if (key.getAddrSpace()) + return mlir::emitError(loc) + << "!cir.ptr data layout entries are currently limited to the " + "default address space"; } return mlir::success(); } @@ -650,16 +673,13 @@ bool PointerType::areCompatible( // compatible ABI alignment. // TODO(cir): assumes a single default-AS entry; match by address space // once per-AS pointer specs are emitted. - uint64_t size = kDefaultPointerSizeBits; - uint64_t abi = kDefaultPointerAlignment * kBitsInByte; - if (mlir::ptr::SpecAttr oldSpec = getPointerSpec(oldLayout)) { - size = oldSpec.getSize(); - abi = oldSpec.getAbi(); - } + cir::PtrSpecAttr oldSpec = getPointerSpec(oldLayout, *this); + uint64_t size = oldSpec.getSize(); + uint64_t abi = oldSpec.getAbi(); for (mlir::DataLayoutEntryInterface newEntry : newLayout) { if (!newEntry.isTypeEntry()) continue; - auto newSpec = mlir::cast<mlir::ptr::SpecAttr>(newEntry.getValue()); + auto newSpec = mlir::cast<cir::PtrSpecAttr>(newEntry.getValue()); if (size != newSpec.getSize() || abi < newSpec.getAbi() || abi % newSpec.getAbi() != 0) return false; diff --git a/clang/lib/CIR/RegisterAllDialects.cpp b/clang/lib/CIR/RegisterAllDialects.cpp index 7a3ecb6ce30ef..d0130d607c466 100644 --- a/clang/lib/CIR/RegisterAllDialects.cpp +++ b/clang/lib/CIR/RegisterAllDialects.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" -#include "mlir/Dialect/Ptr/IR/PtrDialect.h" #include "mlir/IR/BuiltinDialect.h" #include "mlir/IR/MLIRContext.h" @@ -23,7 +22,7 @@ namespace cir { void registerAllDialects(mlir::DialectRegistry ®istry) { registry.insert<mlir::BuiltinDialect, cir::CIRDialect, mlir::DLTIDialect, - mlir::ptr::PtrDialect, mlir::omp::OpenMPDialect, + mlir::omp::OpenMPDialect, mlir::acc::OpenACCDialect>(); // Register extensions to integrate CIR types with OpenACC and OpenMP. cir::omp::registerOpenMPExtensions(registry); diff --git a/clang/test/CIR/CodeGen/pointer-width-32bit.cpp b/clang/test/CIR/CodeGen/pointer-width-32bit.cpp index 826fe5e6fcee1..6038a5ca303ce 100644 --- a/clang/test/CIR/CodeGen/pointer-width-32bit.cpp +++ b/clang/test/CIR/CodeGen/pointer-width-32bit.cpp @@ -7,7 +7,7 @@ // On a target with 32-bit pointers (e.g. nvptx) both a data pointer (!cir.ptr) // and the vtable pointer (!cir.vptr) are 4 bytes wide. The pointer width is -// carried by a #ptr.spec data-layout entry keyed on cir.ptr, so the field +// carried by a #cir.ptr_spec data-layout entry keyed on cir.ptr, so the field // following a pointer lands at the AST-mandated offset. Sizing pointers as a // hardcoded 64 bits previously tripped the record layout builder (insertPadding: // assertion `offset >= size`) on every record containing a pointer. @@ -27,13 +27,13 @@ class A { void A::f() {} -// The module carries a #ptr.spec pointer data-layout entry (size/abi/preferred +// The module carries a #cir.ptr_spec pointer data-layout entry (size/abi/preferred // in bits) that drives both cir.ptr and cir.vptr widths. The 4-byte pointer is // immediately followed by 'x' at offset 4 with no padding, and each record is // 4-byte aligned. // CIR-DAG: !rec_S = !cir.struct<"S" {!cir.ptr<!s32i>, !s32i}> // CIR-DAG: !rec_A = !cir.struct<class "A" {!cir.vptr, !s32i}> -// CIR-DAG: !cir.ptr<!cir.void> = #ptr.spec<size = 32, abi = 32, preferred = 32> +// CIR-DAG: !cir.ptr<!cir.void> = #cir.ptr_spec<size = 32, abi = 32, preferred = 32, index = 32> // CIR: cir.global external @s = #cir.zero : !rec_S {alignment = 4 : i64} // CIR: cir.global{{.*}}@_ZTV1A = #cir.vtable<{{.*}}{alignment = 4 : i64} diff --git a/clang/test/CIR/IR/pointer-data-layout.cir b/clang/test/CIR/IR/pointer-data-layout.cir index 207445d389284..933bda64d4e8d 100644 --- a/clang/test/CIR/IR/pointer-data-layout.cir +++ b/clang/test/CIR/IR/pointer-data-layout.cir @@ -1,16 +1,60 @@ // RUN: cir-opt %s -verify-diagnostics -split-input-file -// The cir.ptr data-layout entry carries an mlir::ptr::SpecAttr (#ptr.spec). +// The cir.ptr data-layout entry carries a #cir.ptr_spec attribute. // A well-formed entry round-trips without diagnostics. module attributes {dlti.dl_spec = #dlti.dl_spec< - !cir.ptr<!cir.void> = #ptr.spec<size = 32, abi = 32, preferred = 32>>} { + !cir.ptr<!cir.void> = #cir.ptr_spec<size = 32, abi = 32, preferred = 32>>} { } // ----- // PointerType::verifyEntries rejects a cir.ptr entry whose value is not a -// #ptr.spec attribute. -// expected-error @below {{expected layout attribute for '!cir.ptr<!cir.void>' to be a #ptr.spec attribute}} +// #cir.ptr_spec attribute. +// expected-error @below {{expected layout attribute for '!cir.ptr<!cir.void>' to be a #cir.ptr_spec attribute}} module attributes {dlti.dl_spec = #dlti.dl_spec< !cir.ptr<!cir.void> = dense<32> : vector<2xi64>>} { } + +// ----- + +// The entry key must use !cir.void as pointee. +// expected-error @below {{expected !cir.ptr data layout entry for '!cir.ptr<!cir.int<s, 32>>' to use !cir.void as pointee}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.int<s, 32>> = #cir.ptr_spec<size = 32, abi = 32, preferred = 32>>} { +} + +// ----- + +// Gate: per-address-space pointer layouts are not supported yet. +// expected-error @below {{!cir.ptr data layout entries are currently limited to the default address space}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void, target_address_space(5)> = #cir.ptr_spec<size = 32, abi = 32, preferred = 32>>} { +} + +// ----- + +// expected-error @+2 {{size entry must be divisible by 8}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void> = #cir.ptr_spec<size = 33, abi = 32, preferred = 32>>} { +} + +// ----- + +// expected-error @+2 {{abi entry must be divisible by 8}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void> = #cir.ptr_spec<size = 32, abi = 33, preferred = 64>>} { +} + +// ----- + +// expected-error @+2 {{index entry must be divisible by 8}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void> = #cir.ptr_spec<size = 32, abi = 32, preferred = 32, index = 33>>} { +} + +// ----- + +// expected-error @+2 {{preferred alignment is expected to be at least as large as ABI alignment}} +module attributes {dlti.dl_spec = #dlti.dl_spec< + !cir.ptr<!cir.void> = #cir.ptr_spec<size = 64, abi = 64, preferred = 32>>} { +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
