https://github.com/erichkeane created 
https://github.com/llvm/llvm-project/pull/186887

This patch adds support for arrays of pointer-to-member-data, just like we do 
for pointer-to-member-function. This patch also does a refactor of some basic 
value lowering, which both makes this apply to locals and constants, but also 
unifies them in preperation of future work when it comes to record types.

Other than the otherwise-not-quite-intentional change (the recursion got
    this feature, and I realized it worked while looking at other
    things!), this is NFCI.

>From d16104dc0f86370b75bf0ab6fbab7fc473778122 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Mon, 16 Mar 2026 14:03:29 -0700
Subject: [PATCH] [CIR] Add support for arrays-of-pointer-to-member-data

This patch adds support for arrays of pointer-to-member-data, just like
we do for pointer-to-member-function. This patch also does a refactor of
some basic value lowering, which both makes this apply to locals and
constants, but also unifies them in preperation of future work when it
comes to record types.

Other than the otherwise-not-quite-intentional change (the recursion got
    this feature, and I realized it worked while looking at other
    things!), this is NFCI.
---
 .../CIR/Dialect/Transforms/CXXABILowering.cpp | 101 ++++++++----------
 clang/test/CIR/CodeGen/no-odr-use.cpp         |  25 ++++-
 2 files changed, 71 insertions(+), 55 deletions(-)

diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index d2c7ac37e8a96..35a841f8dbb1a 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -168,30 +168,56 @@ mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
 
   return mlir::failure();
 }
+// Helper function to lower a value for things like an initializer.
+static mlir::TypedAttr lowerValue(const LowerModule *lowerModule,
+                                  const mlir::DataLayout &layout,
+                                  const mlir::TypeConverter &tc, mlir::Type ty,
+                                  mlir::Attribute initVal) {
+  if (mlir::isa<cir::DataMemberType>(ty)) {
+    auto dataMemberVal = mlir::cast_if_present<cir::DataMemberAttr>(initVal);
+    return lowerModule->getCXXABI().lowerDataMemberConstant(dataMemberVal,
+                                                            layout, tc);
+  }
+  if (mlir::isa<cir::MethodType>(ty)) {
+    auto methodVal = mlir::cast_if_present<cir::MethodAttr>(initVal);
+    return lowerModule->getCXXABI().lowerMethodConstant(methodVal, layout, tc);
+  }
 
-mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
-    cir::ConstantOp op, OpAdaptor adaptor,
-    mlir::ConversionPatternRewriter &rewriter) const {
+  if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
+    auto loweredArrTy = mlir::cast<cir::ArrayType>(tc.convertType(arrTy));
+    // TODO(cir): there are other types that can appear here inside of record
+    // members that we should handle. Those will come in a follow-up patch to
+    // minimize changes here.
+    if (!initVal)
+      return {};
+    auto arrayVal = mlir::cast<cir::ConstArrayAttr>(initVal);
+    auto arrayElts = mlir::cast<ArrayAttr>(arrayVal.getElts());
+    SmallVector<mlir::Attribute> loweredElements;
+    loweredElements.reserve(arrTy.getSize());
+    for (const mlir::Attribute &attr : arrayElts) {
+      auto typedAttr = cast<mlir::TypedAttr>(attr);
+      loweredElements.push_back(
+          lowerValue(lowerModule, layout, tc, typedAttr.getType(), typedAttr));
+    }
 
-  if (mlir::isa<cir::DataMemberType>(op.getType())) {
-    auto dataMember = mlir::cast<cir::DataMemberAttr>(op.getValue());
-    mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
-    mlir::TypedAttr abiValue = 
lowerModule->getCXXABI().lowerDataMemberConstant(
-        dataMember, layout, *getTypeConverter());
-    rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
-    return mlir::success();
+    return cir::ConstArrayAttr::get(
+        loweredArrTy, mlir::ArrayAttr::get(ty.getContext(), loweredElements),
+        arrayVal.getTrailingZerosNum());
   }
 
-  if (mlir::isa<cir::MethodType>(op.getType())) {
-    auto method = mlir::cast<cir::MethodAttr>(op.getValue());
-    mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
-    mlir::TypedAttr abiValue = lowerModule->getCXXABI().lowerMethodConstant(
-        method, layout, *getTypeConverter());
-    rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
-    return mlir::success();
-  }
+  llvm_unreachable("inputs to cir.global/constant in ABI lowering must be data 
"
+                   "member or method");
+}
 
-  llvm_unreachable("constant operand is not an CXXABI-dependent type");
+mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
+    cir::ConstantOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+
+  mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
+  mlir::TypedAttr newValue = lowerValue(
+      lowerModule, layout, *getTypeConverter(), op.getType(), op.getValue());
+  rewriter.replaceOpWithNewOp<ConstantOp>(op, newValue);
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
@@ -259,41 +285,8 @@ mlir::LogicalResult 
CIRGlobalOpABILowering::matchAndRewrite(
 
   mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
 
-  mlir::Attribute loweredInit;
-  if (mlir::isa<cir::DataMemberType>(ty)) {
-    cir::DataMemberAttr init =
-        mlir::cast_if_present<cir::DataMemberAttr>(op.getInitialValueAttr());
-    loweredInit = lowerModule->getCXXABI().lowerDataMemberConstant(
-        init, layout, *getTypeConverter());
-  } else if (mlir::isa<cir::MethodType>(ty)) {
-    cir::MethodAttr init =
-        mlir::cast_if_present<cir::MethodAttr>(op.getInitialValueAttr());
-    loweredInit = lowerModule->getCXXABI().lowerMethodConstant(
-        init, layout, *getTypeConverter());
-  } else if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
-    auto init = mlir::cast<cir::ConstArrayAttr>(op.getInitialValueAttr());
-    auto arrayElts = mlir::cast<ArrayAttr>(init.getElts());
-    SmallVector<mlir::Attribute> loweredElements;
-    loweredElements.reserve(arrTy.getSize());
-    for (const mlir::Attribute &attr : arrayElts) {
-      if (auto methodAttr = mlir::dyn_cast<cir::MethodAttr>(attr)) {
-        mlir::Attribute loweredElt =
-            lowerModule->getCXXABI().lowerMethodConstant(methodAttr, layout,
-                                                         *getTypeConverter());
-        loweredElements.push_back(loweredElt);
-      } else {
-        llvm_unreachable("array of data member lowering is NYI");
-      }
-    }
-    auto loweredArrTy =
-        mlir::cast<cir::ArrayType>(getTypeConverter()->convertType(arrTy));
-    loweredInit = cir::ConstArrayAttr::get(
-        loweredArrTy,
-        mlir::ArrayAttr::get(rewriter.getContext(), loweredElements));
-  } else {
-    llvm_unreachable(
-        "inputs to cir.global in ABI lowering must be data member or method");
-  }
+  mlir::Attribute loweredInit = lowerValue(
+      lowerModule, layout, *getTypeConverter(), ty, op.getInitialValueAttr());
 
   auto newOp = mlir::cast<cir::GlobalOp>(rewriter.clone(*op.getOperation()));
   newOp.setInitialValueAttr(loweredInit);
diff --git a/clang/test/CIR/CodeGen/no-odr-use.cpp 
b/clang/test/CIR/CodeGen/no-odr-use.cpp
index bd12c70803fc5..08d75b5e56221 100644
--- a/clang/test/CIR/CodeGen/no-odr-use.cpp
+++ b/clang/test/CIR/CodeGen/no-odr-use.cpp
@@ -15,6 +15,14 @@
 // LLVM-DAG: @[[F_A:.*]] = private constant {{.*}} { i32 1, [2 x i32] [i32 2, 
i32 3], [3 x i32] [i32 4, i32 5, i32 6] }
 // OGCG-DAG: @__const._Z1fi.a = private unnamed_addr constant {{.*}} { i32 1, 
[2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] }
 
+// CIR-CXX11-DAG: cir.global "private" constant cir_private 
@_ZN7PR422765State3dmsE.const = #cir.const_array<[#cir.int<0> : !s64i, 
#cir.int<0> : !s64i]> : !cir.array<!s64i x 2> {alignment = 16 : i64}
+// LLVM-CXX11-DAG :@_ZN7PR422765State3dmsE.const = private constant [2 x i64] 
zeroinitializer, align 16
+// OGCG-CXX11-DAG :@_ZN7PR422765State3dmsE.const = private constant [2 x i64] 
zeroinitializer, align 16
+
+// CIR-CXX20-DAG: cir.global "private" constant cir_private 
@_ZN7PR422765State3dmsE = #cir.const_array<[#cir.int<0> : !s64i, #cir.int<0> : 
!s64i]> : !cir.array<!s64i x 2> {alignment = 16 : i64}
+// LLVM-CXX20-DAG :@_ZN7PR422765State3dmsE = private constant [2 x i64] 
zeroinitializer, align 16
+// OGCG-CXX20-DAG :@_ZN7PR422765State3dmsE = private constant [2 x i64] 
zeroinitializer, align 16
+
 // CIR-CXX11-DAG: cir.global "private" constant cir_private 
@_ZN7PR422765State1mE.const = 
#cir.const_array<[#cir.const_record<{#cir.global_view<@_ZN7PR422765State2f1Ev> 
: !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct, 
#cir.const_record<{#cir.global_view<@_ZN7PR422765State2f2Ev> : !s64i, 
#cir.int<0> : !s64i}> : !rec_anon_struct]> : !cir.array<!rec_anon_struct x 2>
 // LLVM-CXX11-DAG: @_ZN7PR422765State1mE.const = private constant [2 x { i64, 
i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} 
@_ZN7PR422765State2f2Ev {{.*}}, i64 0 }]
 // OGCG-CXX11-DAG: @_ZN7PR422765State1mE.const = private unnamed_addr constant 
[2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} 
@_ZN7PR422765State2f2Ev {{.*}}, i64 0 }]
@@ -93,8 +101,12 @@ namespace PR42276 {
   class State {
     void syncDirtyObjects();
     void f1(), f2();
+    int dataMem;
     using l = void (State::*)();
     static constexpr l m[]{&State::f1, &State::f2};
+
+    using dmTy = int State::*;
+    static constexpr dmTy dms[]{&State::dataMem, &State::dataMem};
   };
   // CIR-CXX11-LABEL: cir.func {{.*}} 
@_ZN7PR422765State2f1Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
   // CIR-CXX11-LABEL: cir.func {{.*}} 
@_ZN7PR422765State2f2Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
@@ -111,13 +123,24 @@ namespace PR42276 {
     for (int i = 0; i < sizeof(m) / sizeof(m[0]); ++i)
       // CIR-CXX11: %[[M:.*]] = cir.get_global @_ZN7PR422765State1mE.const : 
!cir.ptr<!cir.array<!rec_anon_struct x 2>>
       // CIR-CXX2A: %[[M:.*]] = cir.get_global @_ZN7PR422765State1mE : 
!cir.ptr<!cir.array<!rec_anon_struct x 2>>
-      // CIR: %[[M_I:.*]] = cir.get_element %[[M]][%{{.*}} : !s32i] : 
!cir.ptr<!cir.array<!rec_anon_struct x 2>> -> !cir.ptr<!rec_anon_struct>
+      // CIR: cir.get_element %[[M]][%{{.*}} : !s32i] : 
!cir.ptr<!cir.array<!rec_anon_struct x 2>> -> !cir.ptr<!rec_anon_struct>
 
       // LLVM-CXX11: getelementptr [2 x { i64, i64 }], ptr 
@_ZN7PR422765State1mE.const, i32 0, i64 %{{.*}}
       // LLVM-CXX2A: getelementptr [2 x { i64, i64 }], ptr 
@_ZN7PR422765State1mE, i32 0, i64 %{{.*}}
       // OGCG-CXX11: getelementptr inbounds [2 x { i64, i64 }], ptr 
@_ZN7PR422765State1mE.const, i64 0, i64 %{{.*}}
       // OGCG-CXX2A: getelementptr inbounds [2 x { i64, i64 }], ptr 
@_ZN7PR422765State1mE, i64 0, i64 %{{.*}}
       (this->*m[i])();
+
+    int sum = 0;
+    for (int i = 0; i< sizeof(dms) / sizeof(dms[0]); ++i)
+      // CIR-CXX11: %[[DMS:.*]] = cir.get_global @_ZN7PR422765State3dmsE.const 
: !cir.ptr<!cir.array<!s64i x 2>>
+      // CIR-CXX2A: %[[DMS:.*]] = cir.get_global @_ZN7PR422765State3dmsE : 
!cir.ptr<!cir.array<!s64i x 2>>
+      // CIR: cir.get_element %[[DMS]][%{{.*}} : !s32i] : 
!cir.ptr<!cir.array<!s64i x 2>> -> !cir.ptr<!s64i>
+      // LLVM-CXX11: getelementptr [2 x i64], ptr 
@_ZN7PR422765State3dmsE.const, i32 0, i64 %{{.*}}
+      // LLVM-CXX2A: getelementptr [2 x i64], ptr @_ZN7PR422765State3dmsE, i32 
0, i64 %{{.*}}
+      // OGCG-CXX11: getelementptr inbounds [2 x i64], ptr 
@_ZN7PR422765State3dmsE.const, i64 0, i64 %{{.*}}
+      // OGCG-CXX2A: getelementptr inbounds [2 x i64], ptr 
@_ZN7PR422765State3dmsE, i64 0, i64 %{{.*}}
+      sum += this->*dms[i];
   }
   // CIR-CXX2A-LABEL: cir.func {{.*}} 
@_ZN7PR422765State2f1Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
   // CIR-CXX2A-LABEL: cir.func {{.*}} 
@_ZN7PR422765State2f2Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})

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

Reply via email to