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 &registry) {
   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 &registry) {
   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

Reply via email to