https://github.com/bcardosolopes updated 
https://github.com/llvm/llvm-project/pull/179826

>From 093dce7e02a8d55979812e850e0488709621d51a Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <[email protected]>
Date: Fri, 30 Jan 2026 22:47:52 -0800
Subject: [PATCH] [CIR] Add static_local attribute to GlobalOp and GetGlobalOp

This attribute marks function-local static variables that require
guarded initialization (e.g., C++ static local variables with
non-constant initializers). It is used by CIRGen to communicate
to LoweringPrepare which globals need guard variable emission.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td | 15 ++++++++++++++-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp      |  4 ++++
 clang/test/CIR/IR/invalid-static-local.cir   | 16 ++++++++++++++++
 clang/test/CIR/IR/static-local.cir           | 19 +++++++++++++++++++
 4 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/IR/invalid-static-local.cir
 create mode 100644 clang/test/CIR/IR/static-local.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 20b85dd877d00..c37764ed70202 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2335,6 +2335,10 @@ def CIR_GlobalOp : CIR_Op<"global", [
     The `linkage` tracks C/C++ linkage types, currently very similar to LLVM's.
     Symbol visibility in `sym_visibility` is defined in terms of MLIR's 
visibility
     and verified to be in accordance to `linkage`.
+
+    The `static_local` attribute indicates that this global represents a
+    function-local static variable that requires guarded initialization
+    (e.g., C++ static local variables with non-constant initializers).
   }];
 
   // Note that both sym_name and sym_visibility are tied to Symbol trait.
@@ -2353,6 +2357,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
                        UnitAttr:$comdat,
                        UnitAttr:$constant,
                        UnitAttr:$dso_local,
+                       UnitAttr:$static_local,
                        OptionalAttr<I64Attr>:$alignment);
 
   let regions = (region MaxSizedRegion<1>:$ctorRegion,
@@ -2366,6 +2371,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
     (`comdat` $comdat^)?
     ($tls_model^)?
     (`dso_local` $dso_local^)?
+    (`static_local` $static_local^)?
     $sym_name
     custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value,
                                         $ctorRegion, $dtorRegion)
@@ -2433,19 +2439,26 @@ def CIR_GetGlobalOp : CIR_Op<"get_global", [
     Addresses of thread local globals can only be retrieved if this operation
     is marked `thread_local`, which indicates the address isn't constant.
 
+    The `static_local` attribute indicates that this global is a function-local
+    static variable that requires guarded initialization (e.g., C++ static
+    local variables with non-constant initializers).
+
     Example:
     ```mlir
     %x = cir.get_global @gv : !cir.ptr<i32>
     ...
     %y = cir.get_global thread_local @tls_gv : !cir.ptr<i32>
+    ...
+    %w = cir.get_global static_local @func_static : !cir.ptr<i32>
     ```
   }];
 
-  let arguments = (ins FlatSymbolRefAttr:$name, UnitAttr:$tls);
+  let arguments = (ins FlatSymbolRefAttr:$name, UnitAttr:$tls, 
UnitAttr:$static_local);
   let results = (outs Res<CIR_PointerType, "", []>:$addr);
 
   let assemblyFormat = [{
     (`thread_local` $tls^)?
+    (`static_local` $static_local^)?
     $name `:` qualified(type($addr)) attr-dict
   }];
 }
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 9574851a0ae2c..c32f2c7aa62f9 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1854,6 +1854,10 @@ cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection 
&symbolTable) {
     // be marked with tls bits.
     if (getTls() && !g.getTlsModel())
       return emitOpError("access to global not marked thread local");
+    // Verify that for static local access, the global needs to be marked
+    // static_local.
+    if (getStaticLocal() && !g.getStaticLocal())
+      return emitOpError("access to global not marked static local");
   } else if (auto f = dyn_cast<FuncOp>(op)) {
     symTy = f.getFunctionType();
   } else {
diff --git a/clang/test/CIR/IR/invalid-static-local.cir 
b/clang/test/CIR/IR/invalid-static-local.cir
new file mode 100644
index 0000000000000..cd458731252b7
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-static-local.cir
@@ -0,0 +1,16 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+// Global is not marked static_local, but get_global is
+cir.global "private" internal @_ZZ1fvE1x : !s32i
+
+cir.func @test_static_local_mismatch() {
+  // expected-error @below {{access to global not marked static local}}
+  %0 = cir.get_global static_local @_ZZ1fvE1x : !cir.ptr<!s32i>
+  cir.return
+}
+
+}
diff --git a/clang/test/CIR/IR/static-local.cir 
b/clang/test/CIR/IR/static-local.cir
new file mode 100644
index 0000000000000..d4c5a743358de
--- /dev/null
+++ b/clang/test/CIR/IR/static-local.cir
@@ -0,0 +1,19 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+// Test static_local attribute on global and get_global
+cir.global "private" internal static_local @_ZZ1fvE1x : !s32i
+// CHECK: cir.global "private" internal static_local @_ZZ1fvE1x : !s32i
+
+cir.func @test_static_local() {
+  %0 = cir.get_global static_local @_ZZ1fvE1x : !cir.ptr<!s32i>
+  cir.return
+}
+// CHECK: cir.func @test_static_local()
+// CHECK:   %{{.*}} = cir.get_global static_local @_ZZ1fvE1x : !cir.ptr<!s32i>
+// CHECK:   cir.return
+
+}

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
  • [llvm-branch-commits] [clang] ... Bruno Cardoso Lopes via llvm-branch-commits

Reply via email to