[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