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
