[clang] 2b5eb2d - [CIR][docs] Add cir.catch_param to ClangIR cleanup and EH design doc (#181284)

via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 13 09:22:41 PST 2026


Author: Andy Kaylor
Date: 2026-02-13T09:22:36-08:00
New Revision: 2b5eb2dde2cdc98b4265d3b9940f235b51d38638

URL: https://github.com/llvm/llvm-project/commit/2b5eb2dde2cdc98b4265d3b9940f235b51d38638
DIFF: https://github.com/llvm/llvm-project/commit/2b5eb2dde2cdc98b4265d3b9940f235b51d38638.diff

LOG: [CIR][docs] Add cir.catch_param to ClangIR cleanup and EH design doc (#181284)

This updates the ClangIR cleanup and exception handling design document
to describe the requirement to use cir.catch_param operations to begin
the catch regions of a cir.try operation in the structured form of CIR.

This also includes minor changes to the descriptions in the CIROps.td
definitions of cir.try and cir.catch_param

Added: 
    

Modified: 
    clang/docs/ClangIRCleanupAndEHDesign.md
    clang/include/clang/CIR/Dialect/IR/CIROps.td

Removed: 
    


################################################################################
diff  --git a/clang/docs/ClangIRCleanupAndEHDesign.md b/clang/docs/ClangIRCleanupAndEHDesign.md
index 324cf51aa526b..84c9dbc4e897d 100644
--- a/clang/docs/ClangIRCleanupAndEHDesign.md
+++ b/clang/docs/ClangIRCleanupAndEHDesign.md
@@ -350,11 +350,22 @@ the destructor. Therefore, this cleanup handler is marked as eh_only.
 Try-catch blocks will be represented, as they are in the ClangIR
 incubator project, using a `cir.try` operation.
 
+The `cir.catch_param` operation is used to represent the capturing of the
+exception object in an ABI-independent way. When the catch handler includes
+a source variable representing the exception object, the result of the
+`cir.catch_param` operation will be stored to an alloca object for the
+source variable.  If the handler is a catch-all, the `cir.catch_param` operation
+will return a pointer to void, but this cannot be captured by a source variable.
+
+The first operation in a catch handler region must be a `cir.catch_param`
+operation.
+
 ```
 cir.try {
   cir.call exception @function() : () -> ()
   cir.yield
 } catch [type #cir.global_view<@_ZTIPf> : !cir.ptr<!u8i>] {
+  %1 = cir.catch_param : !cir.ptr<!cir.float>
   ...
   cir.yield
 } unwind {
@@ -385,11 +396,15 @@ void someFunc() {
 
 ```
 cir.func @someFunc(){
+  %0 = cir.alloca !cir.ptr<!rec_std3A3Aexception>, !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>, ["e"]
   cir.scope {
     cir.try {
       cir.call exception @_Z1fv() : () -> ()
       cir.yield
     } catch [type #cir.global_view<@_ZTISt9exception> : !cir.ptr<!u8i>] {
+      %1 = cir.catch_param : !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>
+      %2 = cir.load align(8) %1 : !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>, !cir.ptr<!rec_std3A3Aexception>
+      cir.store align(8) %2, %0 : !cir.ptr<!rec_std3A3Aexception>, !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>
       cir.yield
     } unwind {
       cir.resume
@@ -429,13 +444,18 @@ void someFunc() {
 
 ```
 cir.func @someFunc(){
+  %0 = cir.alloca !cir.ptr<!rec_std3A3Aexception>, !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>, ["e"]
   cir.scope {
     cir.try {
       cir.call exception @_Z1fv() : () -> ()
       cir.yield
     } catch [type #cir.global_view<@_ZTISt9exception> : !cir.ptr<!u8i>] {
+      %1 = cir.catch_param : !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>
+      %2 = cir.load align(8) %1 : !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>, !cir.ptr<!rec_std3A3Aexception>
+      cir.store align(8) %2, %0 : !cir.ptr<!rec_std3A3Aexception>, !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>
       cir.yield
     } catch all {
+      %3 = cir.catch_param : !cir.ptr<!void>
       cir.yield
     }
   }
@@ -484,6 +504,7 @@ cir.func @someFunc(){
         cir.yield
       }
     } catch all {
+      %1 = cir.catch_param : !cir.ptr<!void>
       cir.yield
     }
   }
@@ -516,12 +537,17 @@ void someFunc() {
 ```
 cir.func @someFunc(){
   %0 = cir.alloca !rec_SomeClass, !cir.ptr<!rec_SomeClass>, ["c", init]
+  %1 = cir.alloca !cir.ptr<!rec_std3A3Aexception>, !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>, ["e"]
   cir.call @_ZN9SomeClassC1Ev(%0) : (!cir.ptr<!rec_SomeClass>) -> ()
   cir.cleanup.scope {
     cir.scope {
       cir.try {
         cir.call @_ZN9SomeClass11doSomethingEv(%0) : (!cir.ptr<!rec_SomeClass>) -> ()
+        cir.yield
       } catch [type #cir.global_view<@_ZTISt9exception> : !cir.ptr<!u8i>] {
+        %2 = cir.catch_param : !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>
+        %3 = cir.load align(8) %2 : !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>, !cir.ptr<!rec_std3A3Aexception>
+        cir.store align(8) %3, %1 : !cir.ptr<!rec_std3A3Aexception>, !cir.ptr<!cir.ptr<!rec_std3A3Aexception>>
         cir.yield
       } unwind {
         cir.resume
@@ -731,7 +757,11 @@ of the catch handling block must be a `cir.begin_catch` operation.
 The `cir.begin_catch` operation returns two values: a new token that
 uniquely identify this catch handler, and a pointer to the exception
 object. All paths through the catch handler must converge on a single
-`cir.end_catch` operation, which marks the end of the handler.
+`cir.end_catch` operation, which marks the end of the handler. The
+`cir.begin_catch` replaces the `cir.catch_param` in the structured
+form, and the exception object extracted from its return value should
+be stored to the same alloca location as the return value of
+`cir.catch_param` was in the structured representation.
 
   `cir.end_catch %catch_token`
 
@@ -769,6 +799,7 @@ cir.func @someFunc(){
         cir.yield
       }
     } catch all {
+      %1 = cir.catch_param : !cir.ptr<!void>
       cir.yield
     }
   }

diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 2ce6d22c654f0..7085580d99718 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6228,6 +6228,7 @@ def CIR_TryOp : CIR_Op<"try",[
       cir.call exception @function() : () -> ()
       cir.yield
     } catch [type #cir.global_view<@_ZTIPf> : !cir.ptr<!u8i>] {
+      %1 = cir.catch_param : !cir.ptr<!cir.float>
       ...
       cir.yield
     } unwind {
@@ -6288,7 +6289,7 @@ def CIR_TryOp : CIR_Op<"try",[
 def CIR_CatchParamOp : CIR_Op<"catch_param", [HasParent<"cir::TryOp">]> {
   let summary = "Represents the catch clause formal parameter";
   let description = [{
-    The `cir.catch_param` is used to retrieves the exception object inside
+    The `cir.catch_param` is used to retrieve the exception object inside
     the handler regions of `cir.try`.
 
     This operation is used only before the CFG flatterning pass.


        


More information about the cfe-commits mailing list