https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/220889
>From 7236dc508634759704be45fb47cae04e2f75fcb2 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Thu, 3 Sep 2026 12:44:31 +0000 Subject: [PATCH] [CIR] Move the CIR enums off the legacy EnumAttrInfo hierarchy MLIR has two enum hierarchies. `EnumAttrInfo` doubles as an `IntegerAttr` constraint, so every CIR enum had to clear `genSpecializedAttr` to say it did not want one. `EnumInfo` describes a C++ enum and nothing more. Derive the CIR bases from `I32Enum`, `I64Enum` and `I32BitEnum`, and widen `CIR_EnumAttr` to the `EnumInfo` that upstream `EnumAttr` already takes. The flag no longer exists to clear. `FPClassTestEnum` gets unquoted printing from `BitEnumBase` rather than overriding `printBitEnumQuoted`, and `CIR_KnownFuncKind` drops a `parameterPrinter` the generated `operator<<` now covers, still spelling `#cir.func_identity<"std::find">`. AMDGPU wraps an `I32Enum` in an `EnumAttr` with this same bracketed format. Parsing moves to the generated `FieldParser`, whose diagnostic names the accepted spellings, so two `expected-error` lines change. Generated attribute code drops 16 KB as 28 inlined parsers collapse into it. --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 50 +++---------- .../clang/CIR/Dialect/IR/CIRCUDAAttrs.td | 4 +- .../clang/CIR/Dialect/IR/CIREnumAttr.td | 18 +++-- clang/include/clang/CIR/Dialect/IR/CIROps.td | 72 +++++-------------- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 2 - clang/test/CIR/IR/invalid-call.cir | 2 +- clang/test/CIR/IR/invalid-lang-attr.cir | 2 +- 7 files changed, 40 insertions(+), 110 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 2052ddeb577d9..90e1d240e7435 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -82,11 +82,7 @@ def CIR_SourceLanguage : CIR_I32EnumAttr<"SourceLanguage", "source language", [ I32EnumAttrCase<"CXX", 2, "cxx">, I32EnumAttrCase<"OpenCLC", 3, "opencl_c">, I32EnumAttrCase<"OpenCLCXX", 4, "opencl_cxx"> -]> { - // The enum attr class is defined in `CIR_SourceLanguageAttr` below, - // so that it can define extra class methods. - let genSpecializedAttr = 0; -} +]>; def CIR_SourceLanguageAttr : CIR_EnumAttr<CIR_SourceLanguage, "lang"> { @@ -127,9 +123,7 @@ def CIR_ArgPassingKind : CIR_I32EnumAttr< I32EnumAttrCase<"CanPassInRegs", 0, "can_pass_in_regs">, I32EnumAttrCase<"CannotPassInRegs", 1, "cannot_pass_in_regs">, I32EnumAttrCase<"CanNeverPassInRegs", 2, "can_never_pass_in_regs"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_RecordLayoutAttr : CIR_Attr<"RecordLayout", "record_layout", [ // record_align is consumed as an llvm::Align, whose constructor asserts a @@ -736,9 +730,7 @@ def CIR_CmpOrdering : CIR_I32EnumAttr< I32EnumAttrCase<"Strong", 0, "strong">, I32EnumAttrCase<"Weak", 1, "weak">, I32EnumAttrCase<"Partial", 2, "partial"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", "cmp3way_info"> { let summary = "Holds information about a three-way comparison operation"; @@ -829,7 +821,6 @@ def CIR_FPDynamicRoundingMode : CIR_I32EnumAttr< If the actual dynamic rounding mode differs from this value, the behavior is undefined. }]; - let genSpecializedAttr = 0; } def CIR_FPExceptionMode : CIR_I32EnumAttr< @@ -843,7 +834,6 @@ def CIR_FPExceptionMode : CIR_I32EnumAttr< executed. If the actual exception mode differs from this value, the behavior is undefined. }]; - let genSpecializedAttr = 0; } def CIR_FenvAttr : CIR_Attr<"Fenv", "fenv"> { @@ -1296,9 +1286,7 @@ def CIR_VisibilityKind : CIR_I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ I32EnumAttrCase<"Default", 0, "default">, I32EnumAttrCase<"Hidden", 1, "hidden">, I32EnumAttrCase<"Protected", 2, "protected"> -]> { - let genSpecializedAttr = 0; -} +]>; //===----------------------------------------------------------------------===// // GloblCtorAttr @@ -1363,9 +1351,7 @@ def CIR_CtorKind : CIR_I32EnumAttr<"CtorKind", "CXX Constructor Kind", [ I32EnumAttrCase<"Default", 1, "default">, I32EnumAttrCase<"Copy", 2, "copy">, I32EnumAttrCase<"Move", 3, "move">, -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CXXCtorAttr : CIR_Attr<"CXXCtor", "cxx_ctor"> { let summary = "Marks a function as a C++ constructor"; @@ -1429,9 +1415,7 @@ def CIR_CXXDtorAttr : CIR_Attr<"CXXDtor", "cxx_dtor"> { def CIR_AssignKind : CIR_I32EnumAttr<"AssignKind", "CXX Assignment Operator Kind", [ I32EnumAttrCase<"Copy", 0, "copy">, I32EnumAttrCase<"Move", 1, "move">, -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CXXAssignAttr : CIR_Attr<"CXXAssign", "cxx_assign"> { let summary = "Marks a function as a CXX assignment operator"; @@ -1470,13 +1454,7 @@ def CIR_CXXAssignAttr : CIR_Attr<"CXXAssign", "cxx_assign"> { def CIR_KnownFuncKind : CIR_I32EnumAttr<"KnownFuncKind", "known standard library entity", [ I32EnumAttrCase<"StdFind", 1, "std::find">, -]> { - let genSpecializedAttr = 0; - // A name like std::find is not a bare identifier, so print it as a quoted - // string. The enum parser already reads a quoted string back. - let parameterPrinter = - "$_printer.printKeywordOrString(" # symbolToStringFnName # "($_self))"; -} +]>; def CIR_FuncIdentityAttr : CIR_Attr<"FuncIdentity", "func_identity"> { let summary = "Identifies a function as a known standard library entity"; @@ -1701,9 +1679,7 @@ def CIR_InlineKind : CIR_I32EnumAttr<"InlineKind", "inlineKind", [ I32EnumAttrCase<"NoInline", 1, "no_inline">, I32EnumAttrCase<"AlwaysInline", 2, "always_inline">, I32EnumAttrCase<"InlineHint", 3, "inline_hint"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_InlineKindAttr: CIR_EnumAttr<CIR_InlineKind, "inline_kind"> { let summary = "Inline kind attribute"; @@ -1840,8 +1816,6 @@ def CIR_SideEffect : CIR_I32EnumAttr< %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(const) ``` }]; - - let genSpecializedAttr = 0; } def CIR_SideEffectAttr : CIR_EnumAttr<CIR_SideEffect, "side_effect">; @@ -2003,9 +1977,7 @@ def CIR_TLSKind : CIR_I32EnumAttr<"TLSKind", "thread-local storage kind", [ I32EnumAttrCase<"None", 0, "none">, // clang::VarDecl::TLS_None I32EnumAttrCase<"Static", 1, "static">, // clang::VarDecl::TLS_Static I32EnumAttrCase<"Dynamic", 2, "dynamic"> // clang::VarDecl::TLS_Dynamic -]> { - let genSpecializedAttr = 0; -} +]>; // CIR-native template-specialization kind. Cases mirror // clang::TemplateSpecializationKind. @@ -2024,9 +1996,7 @@ def CIR_TemplateSpecializationKind // clang::TSK_ExplicitInstantiationDefinition I32EnumAttrCase<"ExplicitInstantiationDefinition", 4, "explicit_instantiation_definition"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_StaticLocalInfoAttr : CIR_Attr<"StaticLocalInfo", "static_local_info"> { diff --git a/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td index 2d5f70ec9c3ad..3362ff1812e34 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRCUDAAttrs.td @@ -75,9 +75,7 @@ def CIR_CUDADeviceVarKind : CIR_I32EnumAttr<"CUDADeviceVarKind", I32EnumAttrCase<"Variable", 0>, I32EnumAttrCase<"Surface", 1>, // Future I32EnumAttrCase<"Texture", 2>, // Future -]> { - let genSpecializedAttr = 0; -} +]>; // Attribute carrying device variable registration flags def CIR_CUDAVarRegistrationInfoAttr : CIR_Attr<"CUDAVarRegistrationInfo", "cu.var_registration"> { diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td index 966ab85698325..8723ad5051ba0 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td +++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td @@ -16,19 +16,24 @@ include "mlir/IR/EnumAttr.td" include "clang/CIR/Dialect/IR/CIRDialect.td" -class CIR_I32EnumAttr<string name, string summary, list<I32EnumAttrCase> cases> - : I32EnumAttr<name, summary, cases> { +// A CIR enum describes a C++ enum and nothing else. It either gets a +// `CIR_EnumAttr` wrapper below, or it is used as a raw parameter of some other +// attribute, so it derives from `EnumInfo` rather than the older +// `EnumAttrInfo`, which doubles as an `IntegerAttr` constraint and would need +// its `genSpecializedAttr` cleared on every enum. +class CIR_I32EnumAttr<string name, string summary, list<EnumCase> cases> + : I32Enum<name, summary, cases> { let cppNamespace = "::cir"; } -class CIR_I64EnumAttr<string name, string summary, list<I64EnumAttrCase> cases> - : I64EnumAttr<name, summary, cases> { +class CIR_I64EnumAttr<string name, string summary, list<EnumCase> cases> + : I64Enum<name, summary, cases> { let cppNamespace = "::cir"; } class CIR_I32BitEnumAttr<string name, string summary, list<BitEnumCaseBase> cases> - : I32BitEnumAttr<name, summary, cases> { + : I32BitEnum<name, summary, cases> { let cppNamespace = "::cir"; } @@ -37,7 +42,7 @@ class CIR_I32BitEnumAttr<string name, string summary, // delimiters gets the dialect's own `#cir.cleanup<all>` instead. Operations // that want the bare keyword wrap the argument in the `enum` directive, as in // `enum($cleanupKind)`. Naming the argument directly prints `<all>`. -class CIR_EnumAttr<EnumAttrInfo info, string name = "", list<Trait> traits = []> +class CIR_EnumAttr<EnumInfo info, string name = "", list<Trait> traits = []> : EnumAttr<CIR_Dialect, info, name, traits> { let assemblyFormat = "`<` $value `>`"; } @@ -64,7 +69,6 @@ def CIR_LangAddressSpace : CIR_I32EnumAttr< OpenCL `__local`) before target lowering. }]; - let genSpecializedAttr = 0; } #endif // CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4fe1c5a696e1d..20026c90dfb0a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -242,9 +242,7 @@ def CIR_CastKind : CIR_I32EnumAttr<"CastKind", "cast kind", [ // Enums below are specific to CIR and don't have a correspondence to classic // codegen: I32EnumAttrCase<"bool_to_float", 1000>, -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CastKindAttr : CIR_EnumAttr<CIR_CastKind, "cast">; @@ -399,9 +397,7 @@ def CIR_DynamicCastKind : CIR_I32EnumAttr< "DynamicCastKind", "dynamic cast kind", [ I32EnumAttrCase<"Ptr", 0, "ptr">, I32EnumAttrCase<"Ref", 1, "ref"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_DynamicCastKindAttr : CIR_EnumAttr<CIR_DynamicCastKind, "dynamic_cast">; @@ -642,9 +638,7 @@ def CIR_MemOrder : CIR_I32EnumAttr< I32EnumAttrCase<"Release", 3, "release">, I32EnumAttrCase<"AcquireRelease", 4, "acq_rel">, I32EnumAttrCase<"SequentiallyConsistent", 5, "seq_cst"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_MemOrderAttr : CIR_EnumAttr<CIR_MemOrder, "mem_order">; @@ -673,9 +667,7 @@ def CIR_SyncScopeKind : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind", [ I32EnumAttrCase<"OpenCLDevice", 13, "opencl_device">, I32EnumAttrCase<"OpenCLAllSVMDevices", 14, "opencl_all_svm_devices">, I32EnumAttrCase<"OpenCLSubGroup", 15, "opencl_sub_group">, -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_SyncScopeKindAttr : CIR_EnumAttr<CIR_SyncScopeKind, "sync_scope">; @@ -1358,9 +1350,7 @@ def CIR_CleanupKind : CIR_I32EnumAttr<"CleanupKind", "cleanup kind", [ I32EnumAttrCase<"Normal", 1, "normal">, I32EnumAttrCase<"EH", 2, "eh">, I32EnumAttrCase<"All", 3, "all"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup"> { let summary = "Cleanup kind attribute"; @@ -1530,9 +1520,7 @@ def CIR_CaseOpKind : CIR_I32EnumAttr<"CaseOpKind", "case kind", [ I32EnumAttrCase<"Equal", 1, "equal">, I32EnumAttrCase<"Anyof", 2, "anyof">, I32EnumAttrCase<"Range", 3, "range"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CaseOpKindAttr : CIR_EnumAttr<CIR_CaseOpKind, "case">; @@ -2544,9 +2532,7 @@ def CIR_CmpOpKind : CIR_I32EnumAttr<"CmpOpKind", "compare operation kind", [ I32EnumAttrCase<"ne", 5>, I32EnumAttrCase<"one", 6>, I32EnumAttrCase<"uno", 7> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CmpOpKindAttr : CIR_EnumAttr<CIR_CmpOpKind, "cmp">; @@ -3333,9 +3319,7 @@ def CIR_GlobalLinkageKind : CIR_I32EnumAttr< I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">, // Tentative definitions. I32EnumAttrCase<"CommonLinkage", 10, "common"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_GlobalLinkageKindAttr : CIR_EnumAttr<CIR_GlobalLinkageKind, "linkage">; @@ -3349,9 +3333,7 @@ def CIR_TLSModel : CIR_I32EnumAttr<"TLSModel", "TLS model", [ I32EnumAttrCase<"LocalDynamic", 2, "tls_local_dyn">, I32EnumAttrCase<"InitialExec", 3, "tls_init_exec">, I32EnumAttrCase<"LocalExec", 4, "tls_local_exec"> - ]> { - let genSpecializedAttr = 0; -} +]>; def CIR_TLSModelAttr: CIR_EnumAttr<CIR_TLSModel, "tls_model"> { let summary = "TLS Model attribute"; @@ -4196,9 +4178,7 @@ def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", [ I32EnumAttrCase<"SpirFunction", 2, "spir_function">, I32EnumAttrCase<"SpirKernel", 3, "spir_kernel">, I32EnumAttrCase<"AMDGPUKernel", 4, "amdgpu_kernel"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_CallingConvAttr : CIR_EnumAttr<CIR_CallingConv, "calling_conv">; @@ -4753,9 +4733,7 @@ def CIR_AwaitKind : CIR_I32EnumAttr<"AwaitKind", "await kind", [ I32EnumAttrCase<"User", 1, "user">, I32EnumAttrCase<"Yield", 2, "yield">, I32EnumAttrCase<"Final", 3, "final"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_AwaitKindAttr : CIR_EnumAttr<CIR_AwaitKind, "await">; @@ -5423,9 +5401,7 @@ def CIR_LifetimeEndOp : CIR_Op<"lifetime.end"> { def CIR_AsmFlavor : CIR_I32EnumAttr<"AsmFlavor", "ATT or Intel", [I32EnumAttrCase<"x86_att", 0>, - I32EnumAttrCase<"x86_intel", 1>]> { - let genSpecializedAttr = 0; -} + I32EnumAttrCase<"x86_intel", 1>]>; def CIR_AsmFlavorAttr : CIR_EnumAttr<CIR_AsmFlavor, "asm_flavor">; @@ -6545,9 +6521,7 @@ def CIR_ComplexRangeKind : CIR_I32EnumAttr< I32EnumAttrCase<"Improved", 1, "improved">, I32EnumAttrCase<"Promoted", 2, "promoted">, I32EnumAttrCase<"Basic", 3, "basic">, -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_ComplexRangeKindAttr : CIR_EnumAttr<CIR_ComplexRangeKind, "complex_range">; @@ -6955,14 +6929,6 @@ def FPClassTestEnum FPClass_Sub, FPClass_Zero, FPClass_PosFin, FPClass_NegFin, FPClass_Fin, FPClass_Pos, FPClass_Neg, FPClass_All]> { let printBitEnumPrimaryGroups = 1; - - // I32BitEnumAttr turns this on for backwards compatibility, which makes the - // operation printer quote every value that is not a single bit. Turning it - // off, together with the `enum` directive on cir.is_fp_class, gets a - // separator-aware parser and printer that spell every value unquoted. - let printBitEnumQuoted = 0; - - let genSpecializedAttr = 0; } def CIR_FPClassTestAttr : CIR_EnumAttr<FPClassTestEnum, "fp_class">; @@ -7010,9 +6976,7 @@ def CIR_AssumeBundleKind : CIR_I32EnumAttr< I32EnumAttrCase<"Align", 1, "align">, I32EnumAttrCase<"SeparateStorage", 2, "separate_storage">, I32EnumAttrCase<"Dereferenceable", 3, "dereferenceable"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_AssumeBundleKindAttr : CIR_EnumAttr<CIR_AssumeBundleKind, "assume_bundle">; @@ -8766,9 +8730,7 @@ def CIR_InitCatchKind : CIR_I32EnumAttr< I32EnumAttrCase<"Objc", 3, "objc">, I32EnumAttrCase<"TrivialCopy", 4, "trivial_copy">, I32EnumAttrCase<"NonTrivialCopy", 5, "non_trivial_copy">, -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_InitCatchKindAttr : CIR_EnumAttr<CIR_InitCatchKind, "init_catch">; @@ -8902,9 +8864,7 @@ def CIR_AtomicFetchKind : CIR_I32EnumAttr< I32EnumAttrCase<"Minimum", 11, "minimum">, I32EnumAttrCase<"MaximumNum", 12, "maximum_num">, I32EnumAttrCase<"MinimumNum", 13, "minimum_num"> -]> { - let genSpecializedAttr = 0; -} +]>; def CIR_AtomicFetchKindAttr : CIR_EnumAttr<CIR_AtomicFetchKind, "atomic_fetch">; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index b004f3f202987..958785de7beec 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -689,8 +689,6 @@ def CIR_RecordMemberKind : CIR_I32EnumAttr< record whose trailing member is an unnamed bit-field unit keeps that unit in its data size. }]; - - let genSpecializedAttr = 0; } //===----------------------------------------------------------------------===// diff --git a/clang/test/CIR/IR/invalid-call.cir b/clang/test/CIR/IR/invalid-call.cir index e7ac24ea0bae0..c21c32563c70f 100644 --- a/clang/test/CIR/IR/invalid-call.cir +++ b/clang/test/CIR/IR/invalid-call.cir @@ -100,7 +100,7 @@ cir.func @f15() { cir.func private @f16() cir.func @f17() { // expected-error@+2{{failed to parse CIR_InlineKindAttr parameter 'value' which is to be a `::cir::InlineKind`}} - // expected-error@below{{expected ::cir::InlineKind to be one of: no_inline, always_inline, inline_hint}} + // expected-error@below{{expected one of [no_inline, always_inline, inline_hint] for inlineKind}} cir.call @f16() { inline_kind = #cir.inline_kind<nonsense> } : () -> () cir.return } diff --git a/clang/test/CIR/IR/invalid-lang-attr.cir b/clang/test/CIR/IR/invalid-lang-attr.cir index ffe523b1ad401..793f38a2fe743 100644 --- a/clang/test/CIR/IR/invalid-lang-attr.cir +++ b/clang/test/CIR/IR/invalid-lang-attr.cir @@ -1,5 +1,5 @@ // RUN: cir-opt %s -verify-diagnostics -// expected-error@below {{expected ::cir::SourceLanguage to be one of}} +// expected-error@below {{expected one of [c, cxx, opencl_c, opencl_cxx] for source language}} // expected-error@below {{failed to parse CIR_SourceLanguageAttr parameter 'value'}} module attributes {cir.lang = #cir.lang<dummy>} { } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
