[clang] [CIR] Introduce LocalInitOp, & lower static locals (PR #193576)

Henrich Lauko via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 22 23:57:50 PDT 2026


================
@@ -237,10 +238,64 @@ struct LoweringPreparePass
     }
   }
 
+  void emitGlobalGuardedDtorRegion(CIRBaseBuilderTy &builder,
+                                   cir::GlobalOp global,
+                                   mlir::Region &dtorRegion,
+                                   mlir::Block &entryBB) {
+    // Create a variable that binds the atexit to this shared object.
+    builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
+    cir::GlobalOp handle = getOrCreateRuntimeVariable(
+        builder, "__dso_handle", global.getLoc(), builder.getI8Type(),
+        cir::GlobalLinkageKind::ExternalLinkage, cir::VisibilityKind::Hidden);
+
+    // If this is a simple call to a destructor, get the called function.
+    // Otherwise, create a helper function for the entire dtor region,
+    // replacing the current dtor region body with a call to the helper
+    // function.
+    cir::CallOp dtorCall;
+    cir::FuncOp dtorFunc =
+        getOrCreateDtorFunc(builder, global, dtorRegion, dtorCall);
+
+    // Create a runtime helper function:
+    //    extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
+    cir::VoidType voidTy = builder.getVoidTy();
+    auto voidPtrTy = cir::PointerType::get(voidTy);
+    auto voidFnTy = cir::FuncType::get({voidPtrTy}, voidTy);
+    auto voidFnPtrTy = cir::PointerType::get(voidFnTy);
+    auto handlePtrTy = cir::PointerType::get(handle.getSymType());
+    auto fnAtExitType =
+        cir::FuncType::get({voidFnPtrTy, voidPtrTy, handlePtrTy}, voidTy);
----------------
xlauko wrote:

I believe you can leverage more `builder` here. We create similar functions throughout the lowering, so might be worth adding:
```
/// Returns `void (T...)` as a cir::FuncType.
cir::FuncType getVoidFnTy(mlir::TypeRange argTypes = {}) {
  return cir::FuncType::get(llvm::to_vector(argTypes), getVoidTy());
}

/// Returns `void (*)(T...)` as a cir::PointerType.
cir::PointerType getVoidFnPtrTy(mlir::TypeRange argTypes = {}) {
  return getPointerTo(getVoidFnTy(argTypes));
}
```

and then use here:

```
    cir::PointerType voidPtrTy = builder.getVoidPtrTy();
    cir::PointerType voidFnPtrTy = builder.getVoidFnPtrTy({voidPtrTy});
    cir::PointerType handlePtrTy = builder.getPointerTo(handle.getSymType());
    auto fnAtExitType = builder.getVoidFnTy({voidFnPtrTy, voidPtrTy, handlePtrTy});
```
?

https://github.com/llvm/llvm-project/pull/193576


More information about the cfe-commits mailing list