[llvm-branch-commits] [clang] [CIR] Migrate GlobalLinkageKind, CallingConv and SideEffect off IntegerAttr (PR #220887)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Sep 3 04:31:17 PDT 2026


https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/220887

The last of the I32EnumAttr-backed operation enums, apart from the bit enum
handled next. Each sets genSpecializedAttr = 0 and gains a CIR_EnumAttr
wrapper, and cir.global wraps $linkage in `enum()`.

cir.func and cir.call print all three through hand-written code, but they
stream stringifyGlobalLinkageKind(getLinkage()) and friends. Those take the
enum rather than the attribute, so the sites are unchanged. The
DefaultValuedAttr defaults for $linkage, $calling_conv and $side_effect keep
taking the same C++ expressions.

Operation syntax is unchanged, so no test needed updating.

GlobalLinkageKind's wrapper is spelled `#cir.linkage<internal>`, dropping
both the `global_` prefix and the `_kind` suffix that the enum class name
carries for C++ reasons.

---

Stacked on #220885. Based on `users/xlauko/cir-enum-07-assume-atomic-asm`, so the diff shown is this commit alone.


>From cedbf0bd5b5684574cdea851ee7e792fc412fc7f Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Thu, 3 Sep 2026 11:29:23 +0000
Subject: [PATCH] [CIR] Migrate GlobalLinkageKind, CallingConv and SideEffect
 off IntegerAttr

The last of the I32EnumAttr-backed operation enums, apart from the bit enum
handled next. Each sets genSpecializedAttr = 0 and gains a CIR_EnumAttr
wrapper, and cir.global wraps $linkage in `enum()`.

cir.func and cir.call print all three through hand-written code, but they
stream stringifyGlobalLinkageKind(getLinkage()) and friends. Those take the
enum rather than the attribute, so the sites are unchanged. The
DefaultValuedAttr defaults for $linkage, $calling_conv and $side_effect keep
taking the same C++ expressions.

Operation syntax is unchanged, so no test needed updating.

GlobalLinkageKind's wrapper is spelled `#cir.linkage<internal>`, dropping
both the `global_` prefix and the `_kind` suffix that the enum class name
carries for C++ reasons.
---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  |  4 +++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 25 ++++++++++-----
 clang/test/CIR/IR/enum-attrs.cir              | 31 +++++++++++++++++++
 3 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index f88ffa1ff7c0d..2052ddeb577d9 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1840,8 +1840,12 @@ 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">;
+
 //===----------------------------------------------------------------------===//
 // StaticLocalGuardAttr
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index b89ea1dc5950b..ad4e6600cddf1 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3333,7 +3333,12 @@ 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">;
 
 // TODO(CIR): For starters, cir.global has only name and type.  The other
 // properties of a global variable will be added over time as more of ClangIR
@@ -3400,7 +3405,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
                        >:$global_visibility,
                        OptionalAttr<StrAttr>:$sym_visibility,
                        TypeAttr:$sym_type,
-                       CIR_GlobalLinkageKind:$linkage,
+                       CIR_GlobalLinkageKindAttr:$linkage,
                        OptionalAttr<MemorySpaceAttrInterface>:$addr_space,
                        OptionalAttr<CIR_TLSModelAttr>:$tls_model,
                        OptionalAttr<CIR_ThreadLocalGlobalWrapperInitAttr>:$tls_refs,
@@ -3426,7 +3431,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
     ($sym_visibility^)?
     ($global_visibility^)?
     (`constant` $constant^)?
-    $linkage
+    enum($linkage)
     (`comdat` $comdat^)?
     (`tls_model` `=` enum($tls_model)^)?
     (`tls_refs` `=` $tls_refs^)?
@@ -4191,7 +4196,11 @@ 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">;
 
 def CIR_FuncOp : CIR_Op<"func", [
   AutomaticAllocationScope, CallableOpInterface, SymbolName, SymbolVisibility,
@@ -4285,11 +4294,11 @@ def CIR_FuncOp : CIR_Op<"func", [
     UnitAttr:$no_proto,
     UnitAttr:$dso_local,
     DefaultValuedAttr<
-      CIR_GlobalLinkageKind,
+      CIR_GlobalLinkageKindAttr,
       "cir::GlobalLinkageKind::ExternalLinkage"
     >:$linkage,
     DefaultValuedAttr<
-      CIR_CallingConv,
+      CIR_CallingConvAttr,
       "cir::CallingConv::C"
     >:$calling_conv,
     OptionalAttr<StrAttr>:$sym_visibility,
@@ -4297,7 +4306,7 @@ def CIR_FuncOp : CIR_Op<"func", [
     OptionalAttr<DictArrayAttr>:$arg_attrs,
     OptionalAttr<DictArrayAttr>:$res_attrs,
     OptionalAttr<FlatSymbolRefAttr>:$aliasee,
-    OptionalAttr<CIR_SideEffect>:$side_effect,
+    OptionalAttr<CIR_SideEffectAttr>:$side_effect,
     OptionalAttr<FlatSymbolRefAttr>:$personality,
     CIR_OptionalPriorityAttr:$global_ctor_priority,
     CIR_OptionalPriorityAttr:$global_dtor_priority,
@@ -4601,7 +4610,7 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
       UnitAttr:$nothrow,
       OptionalAttr<CIR_InlineKindAttr>:$inline_kind,
       UnitAttr:$musttail,
-      DefaultValuedAttr<CIR_SideEffect, "SideEffect::All">:$side_effect,
+      DefaultValuedAttr<CIR_SideEffectAttr, "SideEffect::All">:$side_effect,
       OptionalAttr<DictArrayAttr>:$arg_attrs,
       OptionalAttr<DictArrayAttr>:$res_attrs
       );
diff --git a/clang/test/CIR/IR/enum-attrs.cir b/clang/test/CIR/IR/enum-attrs.cir
index ca020a8b28030..aafc58e792678 100644
--- a/clang/test/CIR/IR/enum-attrs.cir
+++ b/clang/test/CIR/IR/enum-attrs.cir
@@ -117,6 +117,31 @@ cir.func @asm_flavor_attr() {
 // CHECK: cir.func @asm_flavor_attr() {
 // CHECK:   cir.return {cir.test = [#cir.asm_flavor<x86_att>, #cir.asm_flavor<x86_intel>]}
 
+cir.func @linkage_attr() {
+  cir.return {cir.test = [#cir.linkage<external>,
+                          #cir.linkage<linkonce_odr>,
+                          #cir.linkage<cir_private>]}
+}
+
+// CHECK: cir.func @linkage_attr() {
+// CHECK:   cir.return {cir.test = [#cir.linkage<external>, #cir.linkage<linkonce_odr>, #cir.linkage<cir_private>]}
+
+cir.func @calling_conv_attr() {
+  cir.return {cir.test = [#cir.calling_conv<c>, #cir.calling_conv<ptx_kernel>,
+                          #cir.calling_conv<amdgpu_kernel>]}
+}
+
+// CHECK: cir.func @calling_conv_attr() {
+// CHECK:   cir.return {cir.test = [#cir.calling_conv<c>, #cir.calling_conv<ptx_kernel>, #cir.calling_conv<amdgpu_kernel>]}
+
+cir.func @side_effect_attr() {
+  cir.return {cir.test = [#cir.side_effect<all>, #cir.side_effect<pure>,
+                          #cir.side_effect<const>]}
+}
+
+// CHECK: cir.func @side_effect_attr() {
+// CHECK:   cir.return {cir.test = [#cir.side_effect<all>, #cir.side_effect<pure>, #cir.side_effect<const>]}
+
 // The operations themselves keep printing a bare keyword.
 cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i,
                                          %arg2: !cir.ptr<!s32i>) {
@@ -133,4 +158,10 @@ cir.func @operations_print_bare_keywords(%arg0: !s32i, %arg1: !s32i,
 // CHECK:   %2 = cir.load syncscope(system) atomic(seq_cst) %arg2 : !cir.ptr<!s32i>, !s32i
 // CHECK:   cir.atomic.fence syncscope(system) seq_cst
 
+// cir.global's linkage is the one bare keyword that cannot be checked from
+// inside a function.
+cir.global "private" internal @g = #cir.int<0> : !s32i
+
+// CHECK: cir.global "private" internal @g = #cir.int<0> : !s32i
+
 }



More information about the llvm-branch-commits mailing list