[clang] [CIR] Upstream the CatchParamOp (PR #165110)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 25 10:15:35 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
Upstream the CatchParamOp as a prerequisite for implementing exception handlers
Issue https://github.com/llvm/llvm-project/issues/154992
---
Full diff: https://github.com/llvm/llvm-project/pull/165110.diff
4 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+44)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+17)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+29)
- (added) clang/test/CIR/IR/invalid-catch-param.cir (+65)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 2b361ed0982c6..57736cd9c93c2 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4490,6 +4490,50 @@ def CIR_TryOp : CIR_Op<"try",[
let hasLLVMLowering = false;
}
+//===----------------------------------------------------------------------===//
+// CatchParamOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CatchParamKind : CIR_I32EnumAttr<
+ "CatchParamKind", "Designate limits for begin/end of catch param handling", [
+ I32EnumAttrCase<"Begin", 0, "begin">,
+ I32EnumAttrCase<"End", 1, "end">
+]>;
+
+def CIR_CatchParamOp : CIR_Op<"catch_param"> {
+ let summary = "Represents catch clause formal parameter";
+ let description = [{
+ The `cir.catch_param` can operate in two modes: within catch regions of
+ `cir.try` or anywhere else with the `begin` or `end` markers. The `begin`
+ version requires an exception pointer of `cir.ptr<!void>`.
+
+ Example:
+
+ ```mlir
+ %exception = cir.catch_param begin %exception_obj -> !cir.ptr<!s32i>
+
+ %exception = cir.catch_param -> !cir.ptr<!void>
+
+ cir.catch_param end
+ ```
+ }];
+
+ let arguments = (ins
+ Optional<CIR_VoidPtrType>:$exception_ptr,
+ OptionalAttr<CIR_CatchParamKind>:$kind
+ );
+
+ let results = (outs Optional<CIR_AnyType>:$param);
+ let assemblyFormat = [{
+ ($kind^)?
+ ($exception_ptr^)?
+ (`->` qualified(type($param))^)?
+ attr-dict
+ }];
+
+ let hasVerifier = 1;
+}
+
//===----------------------------------------------------------------------===//
// Atomic operations
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 2d2ef422bfaef..3531af762fabf 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -3096,6 +3096,23 @@ static mlir::ParseResult parseTryHandlerRegions(
return mlir::success();
}
+//===----------------------------------------------------------------------===//
+// CatchParamOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::CatchParamOp::verify() {
+ std::optional<cir::CatchParamKind> kind = getKind();
+ if (getExceptionPtr()) {
+ if (!kind || *kind != cir::CatchParamKind::Begin)
+ return emitOpError("needs 'begin' to work with exception pointer");
+ return success();
+ }
+
+ if (!kind && !(*this)->getParentOfType<cir::TryOp>())
+ return emitOpError("without 'kind' requires 'cir.try' surrounding scope");
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 5a6193fa8d840..b4c815065b2af 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2981,6 +2981,35 @@ mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMCatchParamOpLowering::matchAndRewrite(
+ cir::CatchParamOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ std::optional<cir::CatchParamKind> kind = op.getKind();
+ if (!kind)
+ llvm_unreachable("only begin/end supposed to make to lowering stage");
+
+ if (kind == cir::CatchParamKind::Begin) {
+ // Get or create `declare ptr @__cxa_begin_catch(ptr)`
+ const llvm::StringRef fnName = "__cxa_begin_catch";
+ auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
+ auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {llvmPtrTy});
+ createLLVMFuncOpIfNotExist(rewriter, op, fnName, fnTy);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
+ op, mlir::TypeRange{llvmPtrTy}, fnName,
+ mlir::ValueRange{adaptor.getExceptionPtr()});
+ return mlir::success();
+ }
+
+ // Get or create `declare void @__cxa_end_catch()`
+ const llvm::StringRef fnName = "__cxa_end_catch";
+ auto voidTy = mlir::LLVM::LLVMVoidType::get(rewriter.getContext());
+ auto fnTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
+ createLLVMFuncOpIfNotExist(rewriter, op, fnName, fnTy);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(op, mlir::TypeRange{}, fnName,
+ mlir::ValueRange{});
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
cir::AllocExceptionOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/IR/invalid-catch-param.cir b/clang/test/CIR/IR/invalid-catch-param.cir
new file mode 100644
index 0000000000000..87e90b983da50
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-catch-param.cir
@@ -0,0 +1,65 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+
+module {
+
+cir.func dso_local @catch_param_without_kind_and_without_try_scope() {
+ // expected-error @below {{'cir.catch_param' op without 'kind' requires 'cir.try' surrounding scope}}
+ %0 = cir.catch_param -> !cir.ptr<!void>
+ cir.return
+}
+
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+
+module {
+
+cir.func private @division() -> !s32i
+cir.func dso_local @catch_param_with_exception_ptr_but_without_kind() {
+ cir.scope {
+ cir.try {
+ %0 = cir.call @division() : () -> !s32i
+ cir.yield
+ } catch all {
+ %0 = cir.const #cir.ptr<null> : !cir.ptr<!void>
+ // expected-error @below {{'cir.catch_param' op needs 'begin' to work with exception pointer}}
+ %1 = cir.catch_param %0 -> !cir.ptr<!void>
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+
+module {
+
+cir.func private @division() -> !s32i
+cir.func dso_local @catch_param_with_exception_ptr_but_with_end_kind() {
+ cir.scope {
+ cir.try {
+ %0 = cir.call @division() : () -> !s32i
+ cir.yield
+ } catch all {
+ %0 = cir.const #cir.ptr<null> : !cir.ptr<!void>
+ // expected-error @below {{'cir.catch_param' op needs 'begin' to work with exception pointer}}
+ %1 = cir.catch_param end %0 -> !cir.ptr<!void>
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/165110
More information about the cfe-commits
mailing list