https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/187607

>From 36a76b7565c4f01e63f96a8e5e493cc285b413e3 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Thu, 19 Mar 2026 16:14:41 -0700
Subject: [PATCH 1/3] [CIR][NFC] Use tablegen to create CIRAttrToValue visitor
 declarations

This change introduces TableGen support for indicating CIR attributes
that require a CIRAttrToValue visitor, adds the new flag to all
attributes to which it applies, and replaces the explicit declarations
with the tablegen output.
---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  | 18 ++++++
 .../CIR/Lowering/DirectToLLVM/CMakeLists.txt  |  1 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 27 +--------
 clang/utils/TableGen/CIRLoweringEmitter.cpp   | 55 +++++++++++++++++++
 4 files changed, 77 insertions(+), 24 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index a98987db7b34d..5b00d4f0a352b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -34,6 +34,11 @@ class CIR_Attr<string name, string attrMnemonic, list<Trait> 
traits = []>
   // not be set to 0 if this type has any ability to have a 'record' type,
   // member type, or method type.
   bit canHaveIllegalCXXABIType = 1;
+
+  // When set, clang-tblgen includes this attribute in the DirectToLLVM
+  // `CIRAttrToValue` TypeSwitch and emits a `visitCirAttr` declaration;
+  // a matching definition must exist in LowerToLLVM.cpp.
+  bit hasAttrToValueLowering = 0;
 }
 
 class CIR_TypedAttr<string name, string attrMnemonic, list<Trait> traits = []>
@@ -151,6 +156,7 @@ def CIR_OptInfoAttr : CIR_Attr<"OptInfo", "opt_info"> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_BoolAttr : CIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
+  let hasAttrToValueLowering = 1;
   let summary = "Represent true/false for !cir.bool types";
   let description = [{
     The BoolAttr represents a 'true' or 'false' value.
@@ -177,6 +183,7 @@ def CIR_BoolAttr : CIR_Attr<"Bool", "bool", 
[TypedAttrInterface]> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_ZeroAttr : CIR_TypedAttr<"Zero", "zero"> {
+  let hasAttrToValueLowering = 1;
   let summary = "Attribute to represent zero initialization";
   let description = [{
     The ZeroAttr is used to indicate zero initialization on structs.
@@ -188,6 +195,7 @@ def CIR_ZeroAttr : CIR_TypedAttr<"Zero", "zero"> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_UndefAttr : CIR_TypedAttr<"Undef", "undef"> {
+  let hasAttrToValueLowering = 1;
   let summary = "Represent an undef constant";
   let description = [{
     The UndefAttr represents an undef constant, corresponding to LLVM's notion
@@ -212,6 +220,7 @@ def CIR_PoisonAttr : CIR_TypedAttr<"Poison", "poison"> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_IntAttr : CIR_Attr<"Int", "int", [TypedAttrInterface]> {
+  let hasAttrToValueLowering = 1;
   let summary = "An attribute containing an integer value";
   let description = [{
     An integer attribute is a literal attribute that represents an integral
@@ -280,6 +289,7 @@ def CIR_IntAttr : CIR_Attr<"Int", "int", 
[TypedAttrInterface]> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_FPAttr : CIR_Attr<"FP", "fp", [TypedAttrInterface]> {
+  let hasAttrToValueLowering = 1;
   let summary = "An attribute containing a floating-point value";
   let description = [{
     An fp attribute is a literal attribute that represents a floating-point
@@ -318,6 +328,7 @@ def CIR_FPAttr : CIR_Attr<"FP", "fp", [TypedAttrInterface]> 
{
 def CIR_ConstArrayAttr : CIR_Attr<"ConstArray", "const_array", [
   TypedAttrInterface
 ]> {
+  let hasAttrToValueLowering = 1;
   let summary = "A constant array from ArrayAttr or StringRefAttr";
   let description = [{
     An CIR array attribute is an array of literals of the specified attr types.
@@ -366,6 +377,7 @@ def CIR_ConstArrayAttr : CIR_Attr<"ConstArray", 
"const_array", [
 def CIR_ConstVectorAttr : CIR_Attr<"ConstVector", "const_vector", [
   TypedAttrInterface
 ]> {
+  let hasAttrToValueLowering = 1;
   let summary = "A constant vector from ArrayAttr";
   let description = [{
     A CIR vector attribute is an array of literals of the specified attribute
@@ -400,6 +412,7 @@ def CIR_ConstVectorAttr : CIR_Attr<"ConstVector", 
"const_vector", [
 def CIR_ConstRecordAttr : CIR_Attr<"ConstRecord", "const_record", [
   TypedAttrInterface
 ]> {
+  let hasAttrToValueLowering = 1;
   let summary = "Represents a constant record";
   let description = [{
     Effectively supports "struct-like" constants. It's must be built from
@@ -436,6 +449,7 @@ def CIR_ConstRecordAttr : CIR_Attr<"ConstRecord", 
"const_record", [
 
//===----------------------------------------------------------------------===//
 
 def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
+  let hasAttrToValueLowering = 1;
   let summary = "Holds a constant pointer value";
   let parameters = (ins
     AttributeSelfTypeParameter<"", "::cir::PointerType">:$type,
@@ -674,6 +688,7 @@ def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", 
"cmp3way_info"> {
 def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
   TypedAttrInterface
 ]> {
+  let hasAttrToValueLowering = 1;
   let summary = "Provides constant access to a global address";
   let description = [{
     Get constant address of global `symbol` and optionally apply offsets to
@@ -760,6 +775,7 @@ def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", 
"global_view", [
 
//===----------------------------------------------------------------------===//
 
 def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> {
+  let hasAttrToValueLowering = 1;
   let summary = "Represents a C++ vtable";
   let description = [{
     Wraps a #cir.const_record containing one or more vtable arrays.
@@ -961,6 +977,7 @@ def CIR_TargetAddressSpaceAttr : CIR_Attr< 
"TargetAddressSpace",
 def CIR_ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex", [
   TypedAttrInterface
 ]> {
+  let hasAttrToValueLowering = 1;
   let summary = "An attribute that contains a constant complex value";
   let description = [{
     The `#cir.const_complex` attribute contains a constant value of complex
@@ -1307,6 +1324,7 @@ def CIR_AddressPointAttr : CIR_Attr<"AddressPoint", 
"address_point"> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
+  let hasAttrToValueLowering = 1;
   let summary = "Represents a typeinfo used for RTTI";
   let description = [{
     The typeinfo data for a given class is stored into an ArrayAttr. The
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt 
b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
index 021397fee992b..e3fb928900978 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangCIRLoweringDirectToLLVM
   LowerToLLVMIR.cpp
 
   DEPENDS
+  CIRLowering
   MLIRCIREnumsGen
   MLIRCIROpsIncGen
   MLIRCIROpInterfacesIncGen
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 1efaf4190b8da..2117dd5903ec4 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -263,30 +263,9 @@ class CIRAttrToValue {
                  const mlir::TypeConverter *converter)
       : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
 
-  mlir::Value visit(mlir::Attribute attr) {
-    return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
-        .Case<cir::BoolAttr, cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
-              cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
-              cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
-              cir::UndefAttr, cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(
-            [&](auto attrT) { return visitCirAttr(attrT); })
-        .Default([&](auto attrT) { return mlir::Value(); });
-  }
-
-  mlir::Value visitCirAttr(cir::BoolAttr boolAttr);
-  mlir::Value visitCirAttr(cir::IntAttr intAttr);
-  mlir::Value visitCirAttr(cir::FPAttr fltAttr);
-  mlir::Value visitCirAttr(cir::ConstComplexAttr complexAttr);
-  mlir::Value visitCirAttr(cir::ConstPtrAttr ptrAttr);
-  mlir::Value visitCirAttr(cir::ConstArrayAttr attr);
-  mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
-  mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
-  mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
-  mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
-  mlir::Value visitCirAttr(cir::UndefAttr attr);
-  mlir::Value visitCirAttr(cir::PoisonAttr attr);
-  mlir::Value visitCirAttr(cir::VTableAttr attr);
-  mlir::Value visitCirAttr(cir::ZeroAttr attr);
+#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
+#include "clang/CIR/Dialect/IR/CIRLowering.inc"
+#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
 
 private:
   mlir::Operation *parentOp;
diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp 
b/clang/utils/TableGen/CIRLoweringEmitter.cpp
index 7051e1fb57044..34ccc62b706af 100644
--- a/clang/utils/TableGen/CIRLoweringEmitter.cpp
+++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp
@@ -254,6 +254,59 @@ void GenerateCIRAttrs(const Record *Record) {
   if (!Record->getValueAsBit("canHaveIllegalCXXABIType"))
     CXXABILoweringAttrAlwaysLegal.push_back("cir::" + OpName);
 }
+
+static std::string getCIRAttrCppClassRef(const Record *AttrRecord) {
+  const Record *DialectRec = AttrRecord->getValueAsDef("dialect");
+  llvm::StringRef Ns = DialectRec->getValueAsString("cppNamespace");
+  Ns.consume_front("::");
+  std::string Result = Ns.str();
+  Result += "::";
+  Result += AttrRecord->getValueAsString("cppClassName");
+  return Result;
+}
+
+static void emitCIRAttrToValueVisitor(const llvm::RecordKeeper &RK,
+                                      llvm::raw_ostream &OS) {
+  std::vector<const Record *> Attrs;
+  for (const Record *R : RK.getAllDerivedDefinitions("CIR_Attr")) {
+    if (!R->getValueAsBit("hasAttrToValueLowering"))
+      continue;
+    Attrs.push_back(R);
+  }
+
+  if (Attrs.empty())
+    PrintFatalError("no CIR attributes with hasAttrToValueLowering");
+
+  llvm::sort(Attrs, [](const Record *A, const Record *B) {
+    return getCIRAttrCppClassRef(A) < getCIRAttrCppClassRef(B);
+  });
+
+  OS << "#ifdef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS\n";
+  OS << "  mlir::Value visit(mlir::Attribute attr) {\n";
+  OS << "    return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)\n";
+  OS << "        .Case<";
+  for (size_t I = 0; I < Attrs.size(); ++I) {
+    if (I != 0)
+      OS << ",";
+    OS << "\n              ";
+    OS << getCIRAttrCppClassRef(Attrs[I]);
+  }
+  OS << ">(\n";
+  OS << "            [&](auto attrT) { return visitCirAttr(attrT); })\n";
+  OS << "        .Default([this](mlir::Attribute attr) {\n";
+  OS << "          mlir::emitError(parentOp->getLoc(), \"unsupported CIR "
+        "attribute in LLVM constant lowering\")\n";
+  OS << "              << attr;\n";
+  OS << "          return mlir::Value();\n";
+  OS << "        });\n";
+  OS << "  }\n\n";
+
+  for (const Record *R : Attrs) {
+    OS << "  mlir::Value visitCirAttr(" << getCIRAttrCppClassRef(R)
+       << " attr);\n";
+  }
+  OS << "#endif // GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS\n\n";
+}
 } // namespace
 
 void clang::EmitCIRLowering(const llvm::RecordKeeper &RK,
@@ -266,6 +319,8 @@ void clang::EmitCIRLowering(const llvm::RecordKeeper &RK,
   for (const auto *OpRecord : RK.getAllDerivedDefinitions("CIR_Attr"))
     GenerateCIRAttrs(OpRecord);
 
+  emitCIRAttrToValueVisitor(RK, OS);
+
   OS << "#ifdef GET_ABI_LOWERING_PATTERNS\n"
      << llvm::join(CXXABILoweringPatterns, "\n") << "#endif\n\n";
   OS << "#ifdef GET_ABI_LOWERING_PATTERNS_LIST\n"

>From 8febf5c4a87b476f23c04ae0ba9e001104ca7287 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Wed, 25 Mar 2026 16:16:28 -0700
Subject: [PATCH 2/3] Add a base attribute class for value-like attributes

This adds a base class, CIR_ValueLikeAttr, that sets
`hasAttrToValueLowering` to to 1 by default. This revealed that we
didn't have a handler for `cir::PoisonAttr`. This could get hit if,
for example, we have a constant array attribute that contains
poison values. We don't currently have any code that does that, but
there's no reason it couldn't be done.

`CIR_DataMemberAttr` and `CIR_MethodAttr` are lowered during CXXABILowering
so they override the default setting of the flag.
---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  | 67 ++++++++-----------
 clang/test/CIR/Lowering/poison.cir            |  4 ++
 2 files changed, 32 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 5b00d4f0a352b..01bac73e441a8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -41,9 +41,17 @@ class CIR_Attr<string name, string attrMnemonic, list<Trait> 
traits = []>
   bit hasAttrToValueLowering = 0;
 }
 
-class CIR_TypedAttr<string name, string attrMnemonic, list<Trait> traits = []>
+class CIR_ValueLikeAttr<string name, string attrMnemonic,
+                        list<Trait> traits = []>
     : CIR_Attr<name, attrMnemonic, !listconcat(traits, [TypedAttrInterface])> {
+  // Most CIR attributes that can be lowered to an LLVM constant will be 
lowered
+  // to that constant during the LowerToLLVM pass. Those that don't should
+  // override this setting.
+  let hasAttrToValueLowering = 1;
+}
 
+class CIR_TypedAttr<string name, string attrMnemonic, list<Trait> traits = []>
+    : CIR_ValueLikeAttr<name, attrMnemonic, traits> {
   let parameters = (ins AttributeSelfTypeParameter<"">:$type);
 
   let builders = [
@@ -155,8 +163,7 @@ def CIR_OptInfoAttr : CIR_Attr<"OptInfo", "opt_info"> {
 // BoolAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_BoolAttr : CIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
-  let hasAttrToValueLowering = 1;
+def CIR_BoolAttr : CIR_ValueLikeAttr<"Bool", "bool", [TypedAttrInterface]> {
   let summary = "Represent true/false for !cir.bool types";
   let description = [{
     The BoolAttr represents a 'true' or 'false' value.
@@ -183,7 +190,6 @@ def CIR_BoolAttr : CIR_Attr<"Bool", "bool", 
[TypedAttrInterface]> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_ZeroAttr : CIR_TypedAttr<"Zero", "zero"> {
-  let hasAttrToValueLowering = 1;
   let summary = "Attribute to represent zero initialization";
   let description = [{
     The ZeroAttr is used to indicate zero initialization on structs.
@@ -195,7 +201,6 @@ def CIR_ZeroAttr : CIR_TypedAttr<"Zero", "zero"> {
 
//===----------------------------------------------------------------------===//
 
 def CIR_UndefAttr : CIR_TypedAttr<"Undef", "undef"> {
-  let hasAttrToValueLowering = 1;
   let summary = "Represent an undef constant";
   let description = [{
     The UndefAttr represents an undef constant, corresponding to LLVM's notion
@@ -219,8 +224,7 @@ def CIR_PoisonAttr : CIR_TypedAttr<"Poison", "poison"> {
 // IntegerAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_IntAttr : CIR_Attr<"Int", "int", [TypedAttrInterface]> {
-  let hasAttrToValueLowering = 1;
+def CIR_IntAttr : CIR_ValueLikeAttr<"Int", "int"> {
   let summary = "An attribute containing an integer value";
   let description = [{
     An integer attribute is a literal attribute that represents an integral
@@ -288,8 +292,7 @@ def CIR_IntAttr : CIR_Attr<"Int", "int", 
[TypedAttrInterface]> {
 // FPAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_FPAttr : CIR_Attr<"FP", "fp", [TypedAttrInterface]> {
-  let hasAttrToValueLowering = 1;
+def CIR_FPAttr : CIR_ValueLikeAttr<"FP", "fp"> {
   let summary = "An attribute containing a floating-point value";
   let description = [{
     An fp attribute is a literal attribute that represents a floating-point
@@ -325,10 +328,7 @@ def CIR_FPAttr : CIR_Attr<"FP", "fp", 
[TypedAttrInterface]> {
 // ConstArrayAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_ConstArrayAttr : CIR_Attr<"ConstArray", "const_array", [
-  TypedAttrInterface
-]> {
-  let hasAttrToValueLowering = 1;
+def CIR_ConstArrayAttr : CIR_ValueLikeAttr<"ConstArray", "const_array"> {
   let summary = "A constant array from ArrayAttr or StringRefAttr";
   let description = [{
     An CIR array attribute is an array of literals of the specified attr types.
@@ -374,10 +374,7 @@ def CIR_ConstArrayAttr : CIR_Attr<"ConstArray", 
"const_array", [
 // ConstVectorAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_ConstVectorAttr : CIR_Attr<"ConstVector", "const_vector", [
-  TypedAttrInterface
-]> {
-  let hasAttrToValueLowering = 1;
+def CIR_ConstVectorAttr : CIR_ValueLikeAttr<"ConstVector", "const_vector"> {
   let summary = "A constant vector from ArrayAttr";
   let description = [{
     A CIR vector attribute is an array of literals of the specified attribute
@@ -409,10 +406,7 @@ def CIR_ConstVectorAttr : CIR_Attr<"ConstVector", 
"const_vector", [
 // ConstRecordAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_ConstRecordAttr : CIR_Attr<"ConstRecord", "const_record", [
-  TypedAttrInterface
-]> {
-  let hasAttrToValueLowering = 1;
+def CIR_ConstRecordAttr : CIR_ValueLikeAttr<"ConstRecord", "const_record"> {
   let summary = "Represents a constant record";
   let description = [{
     Effectively supports "struct-like" constants. It's must be built from
@@ -448,8 +442,7 @@ def CIR_ConstRecordAttr : CIR_Attr<"ConstRecord", 
"const_record", [
 // ConstPtrAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
-  let hasAttrToValueLowering = 1;
+def CIR_ConstPtrAttr : CIR_ValueLikeAttr<"ConstPtr", "ptr"> {
   let summary = "Holds a constant pointer value";
   let parameters = (ins
     AttributeSelfTypeParameter<"", "::cir::PointerType">:$type,
@@ -478,9 +471,7 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", 
[TypedAttrInterface]> {
 // DataMemberAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_DataMemberAttr : CIR_Attr<"DataMember", "data_member", [
-  TypedAttrInterface
-]> {
+def CIR_DataMemberAttr : CIR_ValueLikeAttr<"DataMember", "data_member"> {
   let summary = "Holds a constant data member pointer value";
   let parameters = (ins AttributeSelfTypeParameter<
                             "", "cir::DataMemberType">:$type,
@@ -512,6 +503,9 @@ def CIR_DataMemberAttr : CIR_Attr<"DataMember", 
"data_member", [
     }]>,
   ];
 
+  // This attribute gets lowered during CXXABILowering
+  let hasAttrToValueLowering = 0;
+
   let genVerifyDecl = 1;
 
   let assemblyFormat = [{
@@ -529,7 +523,7 @@ def CIR_DataMemberAttr : CIR_Attr<"DataMember", 
"data_member", [
 // MethodAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_MethodAttr : CIR_Attr<"Method", "method", [TypedAttrInterface]> {
+def CIR_MethodAttr : CIR_ValueLikeAttr<"Method", "method"> {
   let summary = "Holds a constant pointer-to-member-function value";
   let description = [{
     A method attribute is a literal attribute that represents a constant
@@ -582,6 +576,9 @@ def CIR_MethodAttr : CIR_Attr<"Method", "method", 
[TypedAttrInterface]> {
     }]>,
   ];
 
+  // This attribute gets lowered during CXXABILowering
+  let hasAttrToValueLowering = 0;
+
   let hasCustomAssemblyFormat = 1;
 
   let genVerifyDecl = 1;
@@ -685,10 +682,7 @@ def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", 
"cmp3way_info"> {
 // GlobalViewAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
-  TypedAttrInterface
-]> {
-  let hasAttrToValueLowering = 1;
+def CIR_GlobalViewAttr : CIR_ValueLikeAttr<"GlobalView", "global_view"> {
   let summary = "Provides constant access to a global address";
   let description = [{
     Get constant address of global `symbol` and optionally apply offsets to
@@ -774,8 +768,7 @@ def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", 
"global_view", [
 // VTableAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> {
-  let hasAttrToValueLowering = 1;
+def CIR_VTableAttr : CIR_ValueLikeAttr<"VTable", "vtable"> {
   let summary = "Represents a C++ vtable";
   let description = [{
     Wraps a #cir.const_record containing one or more vtable arrays.
@@ -974,10 +967,7 @@ def CIR_TargetAddressSpaceAttr : CIR_Attr< 
"TargetAddressSpace",
 // ConstComplexAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex", [
-  TypedAttrInterface
-]> {
-  let hasAttrToValueLowering = 1;
+def CIR_ConstComplexAttr : CIR_ValueLikeAttr<"ConstComplex", "const_complex"> {
   let summary = "An attribute that contains a constant complex value";
   let description = [{
     The `#cir.const_complex` attribute contains a constant value of complex
@@ -1323,8 +1313,7 @@ def CIR_AddressPointAttr : CIR_Attr<"AddressPoint", 
"address_point"> {
 // TypeInfoAttr
 
//===----------------------------------------------------------------------===//
 
-def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
-  let hasAttrToValueLowering = 1;
+def CIR_TypeInfoAttr : CIR_ValueLikeAttr<"TypeInfo", "typeinfo"> {
   let summary = "Represents a typeinfo used for RTTI";
   let description = [{
     The typeinfo data for a given class is stored into an ArrayAttr. The
diff --git a/clang/test/CIR/Lowering/poison.cir 
b/clang/test/CIR/Lowering/poison.cir
index 6f8b7927e3f8f..a57161890c82a 100644
--- a/clang/test/CIR/Lowering/poison.cir
+++ b/clang/test/CIR/Lowering/poison.cir
@@ -4,6 +4,10 @@
 !s32i = !cir.int<s, 32>
 
 module {
+  cir.global external @poison_array = #cir.const_array<[#cir.poison : !s32i, 
#cir.poison : !s32i, #cir.poison : !s32i]> : !cir.array<!s32i x 3>
+
+  // LLVM: @poison_array = global [3 x i32] poison
+
   cir.func @lower_poison() -> !s32i {
     %0 = cir.const #cir.poison : !s32i
     cir.return %0 : !s32i

>From 2f7d8f430e3fb45371c7115f54bb1061cb66a68b Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Fri, 3 Apr 2026 12:59:45 -0700
Subject: [PATCH 3/3] Refactor the tablegen emitter to match existing code

---
 clang/utils/TableGen/CIRLoweringEmitter.cpp | 95 ++++++++++-----------
 1 file changed, 43 insertions(+), 52 deletions(-)

diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp 
b/clang/utils/TableGen/CIRLoweringEmitter.cpp
index 34ccc62b706af..d7417ee38875e 100644
--- a/clang/utils/TableGen/CIRLoweringEmitter.cpp
+++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp
@@ -27,6 +27,9 @@ std::vector<std::string> CXXABILoweringPatternsList;
 std::vector<std::string> CXXABILoweringAttrAlwaysLegal;
 std::vector<std::string> LLVMLoweringPatterns;
 std::vector<std::string> LLVMLoweringPatternsList;
+std::string CIRAttrToValueVisitFunc;
+std::vector<std::string> CIRAttrToValueVisitorCaseTypes;
+std::vector<std::string> CIRAttrToValueVisitorDecls;
 
 struct CustomLoweringCtor {
   struct Param {
@@ -249,63 +252,47 @@ void GenerateCIREnumAttrs(const Record *Record) {
   // they never have an 'illegal' CXXABI type in them.
   CXXABILoweringAttrAlwaysLegal.push_back("cir::" + OpName);
 }
-void GenerateCIRAttrs(const Record *Record) {
-  std::string OpName = GetOpCppClassName(Record);
-  if (!Record->getValueAsBit("canHaveIllegalCXXABIType"))
-    CXXABILoweringAttrAlwaysLegal.push_back("cir::" + OpName);
-}
 
-static std::string getCIRAttrCppClassRef(const Record *AttrRecord) {
-  const Record *DialectRec = AttrRecord->getValueAsDef("dialect");
+void GenerateAttrToValueVisitor(const Record *Rec) {
+  const Record *DialectRec = Rec->getValueAsDef("dialect");
   llvm::StringRef Ns = DialectRec->getValueAsString("cppNamespace");
   Ns.consume_front("::");
-  std::string Result = Ns.str();
-  Result += "::";
-  Result += AttrRecord->getValueAsString("cppClassName");
-  return Result;
+  std::string CppClassRef = Ns.str();
+  CppClassRef += "::";
+  CppClassRef += Rec->getValueAsString("cppClassName");
+
+  std::string CodeBuffer;
+  llvm::raw_string_ostream Code(CodeBuffer);
+  Code << "  mlir::Value visitCirAttr(" << CppClassRef << " attr);";
+  CIRAttrToValueVisitorDecls.push_back(std::move(CodeBuffer));
+  CIRAttrToValueVisitorCaseTypes.push_back(std::move(CppClassRef));
 }
 
-static void emitCIRAttrToValueVisitor(const llvm::RecordKeeper &RK,
-                                      llvm::raw_ostream &OS) {
-  std::vector<const Record *> Attrs;
-  for (const Record *R : RK.getAllDerivedDefinitions("CIR_Attr")) {
-    if (!R->getValueAsBit("hasAttrToValueLowering"))
-      continue;
-    Attrs.push_back(R);
-  }
+void GenerateAttrToValueVisitFunc() {
+  std::string CodeBuffer;
+  llvm::raw_string_ostream Code(CodeBuffer);
+  Code << "  mlir::Value visit(mlir::Attribute attr) {\n"
+       << "    return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)\n"
+       << "        .Case<\n              "
+       << llvm::join(CIRAttrToValueVisitorCaseTypes, ",\n              ")
+       << ">(\n"
+       << "            [&](auto attrT) { return visitCirAttr(attrT); })\n"
+       << "        .Default([this](mlir::Attribute attr) {\n"
+       << "          mlir::emitError(parentOp->getLoc(), \"unsupported CIR "
+          "attribute in LLVM constant lowering\")\n"
+       << "              << attr;\n"
+       << "          return mlir::Value();\n"
+       << "        });\n"
+       << "  }\n";
+  CIRAttrToValueVisitFunc = std::move(CodeBuffer);
+}
 
-  if (Attrs.empty())
-    PrintFatalError("no CIR attributes with hasAttrToValueLowering");
-
-  llvm::sort(Attrs, [](const Record *A, const Record *B) {
-    return getCIRAttrCppClassRef(A) < getCIRAttrCppClassRef(B);
-  });
-
-  OS << "#ifdef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS\n";
-  OS << "  mlir::Value visit(mlir::Attribute attr) {\n";
-  OS << "    return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)\n";
-  OS << "        .Case<";
-  for (size_t I = 0; I < Attrs.size(); ++I) {
-    if (I != 0)
-      OS << ",";
-    OS << "\n              ";
-    OS << getCIRAttrCppClassRef(Attrs[I]);
-  }
-  OS << ">(\n";
-  OS << "            [&](auto attrT) { return visitCirAttr(attrT); })\n";
-  OS << "        .Default([this](mlir::Attribute attr) {\n";
-  OS << "          mlir::emitError(parentOp->getLoc(), \"unsupported CIR "
-        "attribute in LLVM constant lowering\")\n";
-  OS << "              << attr;\n";
-  OS << "          return mlir::Value();\n";
-  OS << "        });\n";
-  OS << "  }\n\n";
-
-  for (const Record *R : Attrs) {
-    OS << "  mlir::Value visitCirAttr(" << getCIRAttrCppClassRef(R)
-       << " attr);\n";
-  }
-  OS << "#endif // GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS\n\n";
+void GenerateCIRAttrs(const Record *Record) {
+  std::string OpName = GetOpCppClassName(Record);
+  if (!Record->getValueAsBit("canHaveIllegalCXXABIType"))
+    CXXABILoweringAttrAlwaysLegal.push_back("cir::" + OpName);
+  if (Record->getValueAsBit("hasAttrToValueLowering"))
+    GenerateAttrToValueVisitor(Record);
 }
 } // namespace
 
@@ -318,8 +305,12 @@ void clang::EmitCIRLowering(const llvm::RecordKeeper &RK,
     GenerateCIREnumAttrs(OpRecord);
   for (const auto *OpRecord : RK.getAllDerivedDefinitions("CIR_Attr"))
     GenerateCIRAttrs(OpRecord);
+  GenerateAttrToValueVisitFunc();
 
-  emitCIRAttrToValueVisitor(RK, OS);
+  OS << "#ifdef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS\n"
+     << CIRAttrToValueVisitFunc << "\n"
+     << llvm::join(CIRAttrToValueVisitorDecls, "\n") << "\n"
+     << "#endif // GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS\n\n";
 
   OS << "#ifdef GET_ABI_LOWERING_PATTERNS\n"
      << llvm::join(CXXABILoweringPatterns, "\n") << "#endif\n\n";

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

Reply via email to