https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/165110
Upstream the CatchParamOp as a prerequisite for implementing exception handlers Issue https://github.com/llvm/llvm-project/issues/154992 >From 533012edfaf7feaaa15f049a7e1e9d24b18eeab5 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Sat, 25 Oct 2025 19:11:37 +0200 Subject: [PATCH] [CIR] Upstream the CatchParamOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 44 +++++++++++++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 17 +++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 29 +++++++++ clang/test/CIR/IR/invalid-catch-param.cir | 65 +++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 clang/test/CIR/IR/invalid-catch-param.cir 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 +} + +} + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
