[clang] [CIR] Upstream CIR Dialect TryOp with Catch Attrs (PR #162897)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 15 09:57:22 PDT 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/162897
>From 7837cc397473399ad1221f267b7d413c43718d4d Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Fri, 10 Oct 2025 19:09:16 +0200
Subject: [PATCH 1/7] [CIR] Upstream CIR Dialect TryOp with Catch Attrs
---
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 15 ++
clang/include/clang/CIR/Dialect/IR/CIROps.td | 63 ++++++++-
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 132 ++++++++++++++++++
clang/test/CIR/IR/try-catch.cir | 84 +++++++++++
4 files changed, 292 insertions(+), 2 deletions(-)
create mode 100644 clang/test/CIR/IR/try-catch.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 610e349717e12..e739378e3969c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -968,4 +968,19 @@ def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
}];
}
+//===----------------------------------------------------------------------===//
+// CatchAllAttr & CatchUnwindAttr
+//===----------------------------------------------------------------------===//
+
+// Represents the unwind region where unwind continues or
+// the program std::terminate's.
+def CIR_CatchUnwindAttr : CIR_UnitAttr<"CatchUnwind", "unwind"> {
+ let storageType = [{ CatchUnwind }];
+}
+
+// Represents the catch_all region.
+def CIR_CatchAllAttr : CIR_UnitAttr<"CatchAll", "all"> {
+ let storageType = [{ CatchAllAttr }];
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index baab156726a2b..44e8363ee3f45 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -644,7 +644,7 @@ def CIR_StoreOp : CIR_Op<"store", [
defvar CIR_ReturnableScopes = [
"FuncOp", "ScopeOp", "IfOp", "SwitchOp", "CaseOp",
- "DoWhileOp", "WhileOp", "ForOp"
+ "DoWhileOp", "WhileOp", "ForOp", "TryOp"
];
def CIR_ReturnOp : CIR_Op<"return", [
@@ -791,7 +791,7 @@ def CIR_ConditionOp : CIR_Op<"condition", [
defvar CIR_YieldableScopes = [
"ArrayCtor", "ArrayDtor", "CaseOp", "DoWhileOp", "ForOp", "GlobalOp", "IfOp",
- "ScopeOp", "SwitchOp", "TernaryOp", "WhileOp"
+ "ScopeOp", "SwitchOp", "TernaryOp", "WhileOp", "TryOp"
];
def CIR_YieldOp : CIR_Op<"yield", [
@@ -4325,6 +4325,65 @@ def CIR_AllocExceptionOp : CIR_Op<"alloc.exception"> {
}];
}
+//===----------------------------------------------------------------------===//
+// TryOp
+//===----------------------------------------------------------------------===//
+
+def CIR_TryOp : CIR_Op<"try",[
+ DeclareOpInterfaceMethods<RegionBranchOpInterface>,
+ RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments
+]> {
+ let summary = "C++ try block";
+ let description = [{
+ Holds the lexical scope of `try {}`. Note that resources used on catch
+ clauses are usually allocated in the same parent as `cir.try`.
+
+ `synthetic`: use `cir.try` to represent try/catches not originally
+ present in the source code (e.g. `g = new Class` under `-fexceptions`).
+
+ `cleanup`: signal to targets (LLVM for now) that this try/catch, needs
+ to specially tag their landing pads as needing "cleanup".
+
+ Example:
+
+ ```mlir
+ %0 = cir.alloc.exception 16 -> !cir.ptr<!some_record>
+ %1 = cir.get_global @d2 : !cir.ptr<!some_record>
+ cir.try synthetic cleanup {
+ cir.call exception @_ZN7test2_DC1ERKS_(%0, %1)
+ : (!cir.ptr<!some_record>, !cir.ptr<!some_record>) -> () cleanup {
+ %2 = cir.cast bitcast %0 : !cir.ptr<!some_record> -> !cir.ptr<!void>
+ cir.free.exception %2
+ cir.yield
+ }
+ ...
+ }
+ ```
+ }];
+
+ let arguments = (ins UnitAttr:$synthetic, UnitAttr:$cleanup,
+ OptionalAttr<ArrayAttr>:$catch_types);
+ let regions = (region AnyRegion:$try_region,
+ VariadicRegion<AnyRegion>:$catch_regions);
+
+ let assemblyFormat = [{
+ (`synthetic` $synthetic^)?
+ (`cleanup` $cleanup^)?
+ $try_region
+ custom<CatchRegions>($catch_regions, $catch_types)
+ attr-dict
+ }];
+
+ // Everything already covered elsewhere.
+ let builders = [OpBuilder<(ins
+ "llvm::function_ref<void(mlir::OpBuilder &, "
+ "mlir::Location)>":$tryBuilder,
+ "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location, "
+ "mlir::OperationState &)>":$catchBuilder)>];
+
+ let hasLLVMLowering = false;
+}
+
//===----------------------------------------------------------------------===//
// Atomic operations
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 7af3dc1f84955..2f5a93450ab88 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2914,6 +2914,138 @@ LogicalResult cir::TypeInfoAttr::verify(
return success();
}
+//===----------------------------------------------------------------------===//
+// TryOp
+//===----------------------------------------------------------------------===//
+
+void cir::TryOp::build(
+ OpBuilder &builder, OperationState &result,
+ function_ref<void(OpBuilder &, Location)> tryBuilder,
+ function_ref<void(OpBuilder &, Location, OperationState &)> catchBuilder) {
+ assert(tryBuilder && "expected builder callback for 'cir.try' body");
+ assert(catchBuilder && "expected builder callback for 'catch' body");
+
+ OpBuilder::InsertionGuard guard(builder);
+
+ // Try body region
+ Region *tryBodyRegion = result.addRegion();
+
+ // Create try body region and set insertion point
+ builder.createBlock(tryBodyRegion);
+ tryBuilder(builder, result.location);
+ catchBuilder(builder, result.location, result);
+}
+
+void cir::TryOp::getSuccessorRegions(
+ mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
+ // If any index all the underlying regions branch back to the parent
+ // operation.
+ if (!point.isParent()) {
+ regions.push_back(RegionSuccessor());
+ return;
+ }
+
+ // If the condition isn't constant, both regions may be executed.
+ regions.push_back(RegionSuccessor(&getTryRegion()));
+
+ // FIXME: optimize, ideas include:
+ // - If we know a target function never throws a specific type, we can
+ // remove the catch handler.
+ for (mlir::Region &r : this->getCatchRegions())
+ regions.push_back(RegionSuccessor(&r));
+}
+
+static void printCatchRegions(OpAsmPrinter &printer, cir::TryOp op,
+ mlir::MutableArrayRef<::mlir::Region> regions,
+ mlir::ArrayAttr catchersAttr) {
+ if (!catchersAttr)
+ return;
+
+ int currCatchIdx = 0;
+ printer << "catch [";
+ llvm::interleaveComma(catchersAttr, printer, [&](const Attribute &a) {
+ if (mlir::isa<cir::CatchUnwindAttr>(a)) {
+ printer.printAttribute(a);
+ printer << " ";
+ } else if (!a) {
+ printer << "all";
+ } else {
+ printer << "type ";
+ printer.printAttribute(a);
+ printer << " ";
+ }
+ printer.printRegion(regions[currCatchIdx], /*printEntryBLockArgs=*/false,
+ /*printBlockTerminators=*/true);
+ currCatchIdx++;
+ });
+
+ printer << "]";
+}
+
+static ParseResult parseCatchRegions(
+ OpAsmParser &parser,
+ llvm::SmallVectorImpl<std::unique_ptr<::mlir::Region>> ®ions,
+ ::mlir::ArrayAttr &catchersAttr) {
+ if (parser.parseKeyword("catch").failed())
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected 'catch' keyword here");
+
+ auto parseAndCheckRegion = [&]() -> ParseResult {
+ // Parse region attached to catch
+ regions.emplace_back(new Region);
+ Region &currRegion = *regions.back();
+ SMLoc parserLoc = parser.getCurrentLocation();
+ if (parser.parseRegion(currRegion)) {
+ regions.clear();
+ return failure();
+ }
+
+ if (currRegion.empty()) {
+ return parser.emitError(parser.getCurrentLocation(),
+ "catch region shall not be empty");
+ }
+
+ if (!(currRegion.back().mightHaveTerminator() &&
+ currRegion.back().getTerminator()))
+ return parser.emitError(
+ parserLoc, "blocks are expected to be explicitly terminated");
+
+ return success();
+ };
+
+ llvm::SmallVector<mlir::Attribute, 4> catchList;
+ auto parseCatchEntry = [&]() -> ParseResult {
+ mlir::Attribute exceptionTypeInfo;
+
+ if (parser.parseOptionalAttribute(exceptionTypeInfo).has_value()) {
+ catchList.push_back(exceptionTypeInfo);
+ } else {
+ ::llvm::StringRef attrStr;
+ if (parser.parseOptionalKeyword(&attrStr, {"all"}).succeeded()) {
+ // "all" keyword found, exceptionTypeInfo remains null
+ } else if (parser.parseOptionalKeyword("type").succeeded()) {
+ if (parser.parseAttribute(exceptionTypeInfo).failed())
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected valid RTTI info attribute");
+ } else {
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected attribute, 'all', or 'type' keyword");
+ }
+ catchList.push_back(exceptionTypeInfo);
+ }
+ return parseAndCheckRegion();
+ };
+
+ if (parser
+ .parseCommaSeparatedList(OpAsmParser::Delimiter::Square,
+ parseCatchEntry, " in catch list")
+ .failed())
+ return failure();
+
+ catchersAttr = parser.getBuilder().getArrayAttr(catchList);
+ return ::mlir::success();
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/IR/try-catch.cir b/clang/test/CIR/IR/try-catch.cir
new file mode 100644
index 0000000000000..7bc71ff84d4ae
--- /dev/null
+++ b/clang/test/CIR/IR/try-catch.cir
@@ -0,0 +1,84 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!u8i = !cir.int<u, 8>
+
+module {
+
+cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i>
+cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>
+
+cir.func dso_local @empty_try_block_with_catch_all() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ } catch [type #cir.all {
+ cir.yield
+ }]
+ }
+ cir.return
+}
+
+// CHECK: cir.func dso_local @empty_try_block_with_catch_all() {
+// CHECK: cir.scope {
+// CHECK: cir.try {
+// CHECK: cir.yield
+// CHECK: } catch [type #cir.all {
+// CHECK: cir.yield
+// CHECK: }]
+// CHECK: }
+// CHECK: cir.return
+// CHECK: }
+
+cir.func dso_local @empty_try_block_with_catch_unwind() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ } catch [#cir.unwind {
+ cir.yield
+ }]
+ }
+ cir.return
+}
+
+// CHECK: cir.func dso_local @empty_try_block_with_catch_unwind() {
+// CHECK: cir.scope {
+// CHECK: cir.try {
+// CHECK: cir.yield
+// CHECK: } catch [#cir.unwind {
+// CHECK: cir.yield
+// CHECK: }]
+// CHECK: }
+// CHECK: cir.return
+// CHECK: }
+
+cir.func dso_local @empty_try_block_with_catch_ist() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i> {
+ cir.yield
+ }, type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i> {
+ cir.yield
+ }, #cir.unwind {
+ cir.yield
+ }]
+ }
+ cir.return
+}
+
+// CHECK: cir.func dso_local @empty_try_block_with_catch_ist() {
+// CHECK: cir.scope {
+// CHECK: cir.try {
+// CHECK: cir.yield
+// CHECK: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i> {
+// CHECK: cir.yield
+// CHECK: }, type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i> {
+// CHECK: cir.yield
+// CHECK: }, #cir.unwind {
+// CHECK: cir.yield
+// CHECK: }]
+// CHECK: }
+// CHECK: cir.return
+// CHECK: }
+
+}
>From 05e1171d8553f1e810d9d60ca413144e1e13026b Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Fri, 10 Oct 2025 21:14:15 +0200
Subject: [PATCH 2/7] Address code review comments
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 20 +++++-
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 18 -----
clang/test/CIR/IR/invalid-try-catch.cir | 75 ++++++++++++++++++++
3 files changed, 93 insertions(+), 20 deletions(-)
create mode 100644 clang/test/CIR/IR/invalid-try-catch.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 44e8363ee3f45..11097299212d8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4375,11 +4375,27 @@ def CIR_TryOp : CIR_Op<"try",[
}];
// Everything already covered elsewhere.
- let builders = [OpBuilder<(ins
+ let builders = [
+ OpBuilder<(ins
"llvm::function_ref<void(mlir::OpBuilder &, "
"mlir::Location)>":$tryBuilder,
"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location, "
- "mlir::OperationState &)>":$catchBuilder)>];
+ "mlir::OperationState &)>":$catchBuilder),
+ [{
+ assert(tryBuilder && "expected builder callback for 'cir.try' body");
+ assert(catchBuilder && "expected builder callback for 'catch' body");
+
+ OpBuilder::InsertionGuard guard($_builder);
+
+ // Try body region
+ Region *tryBodyRegion = $_state.addRegion();
+
+ // Create try body region and set insertion point
+ $_builder.createBlock(tryBodyRegion);
+ tryBuilder($_builder, $_state.location);
+ catchBuilder($_builder, $_state.location, $_state);
+ }]>
+ ];
let hasLLVMLowering = false;
}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 2f5a93450ab88..40587fef47f7b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2918,24 +2918,6 @@ LogicalResult cir::TypeInfoAttr::verify(
// TryOp
//===----------------------------------------------------------------------===//
-void cir::TryOp::build(
- OpBuilder &builder, OperationState &result,
- function_ref<void(OpBuilder &, Location)> tryBuilder,
- function_ref<void(OpBuilder &, Location, OperationState &)> catchBuilder) {
- assert(tryBuilder && "expected builder callback for 'cir.try' body");
- assert(catchBuilder && "expected builder callback for 'catch' body");
-
- OpBuilder::InsertionGuard guard(builder);
-
- // Try body region
- Region *tryBodyRegion = result.addRegion();
-
- // Create try body region and set insertion point
- builder.createBlock(tryBodyRegion);
- tryBuilder(builder, result.location);
- catchBuilder(builder, result.location, result);
-}
-
void cir::TryOp::getSuccessorRegions(
mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
// If any index all the underlying regions branch back to the parent
diff --git a/clang/test/CIR/IR/invalid-try-catch.cir b/clang/test/CIR/IR/invalid-try-catch.cir
new file mode 100644
index 0000000000000..57863af13d20b
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-try-catch.cir
@@ -0,0 +1,75 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+module {
+
+cir.func dso_local @invalid_catch_without_all_or_type() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ // expected-error @below {{'cir.try' expected attribute, 'all', or 'type' keyword}}
+ } catch [invalid_keyword {
+ cir.yield
+ }]
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+module {
+
+cir.func dso_local @invalid_catch_rtti_type() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ // expected-error @below {{expected attribute value}}
+ // expected-error @below {{'cir.try' expected valid RTTI info attribute}}
+ } catch [type invalid_type {
+ cir.yield
+ }]
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+module {
+
+cir.func dso_local @invalid_catch_empty_block() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ } catch [type #cir.all {
+ // expected-error @below {{'cir.try' catch region shall not be empty}}
+ }]
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+cir.func dso_local @invalid_catch_not_terminated() {
+ %a = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
+ cir.scope {
+ cir.try {
+ cir.yield
+ }
+ // expected-error @below {{'cir.try' blocks are expected to be explicitly terminated}}
+ catch [type #cir.all {
+ %tmp_a = cir.load %a : !cir.ptr<!s32i>, !s32i
+ }]
+ }
+ cir.return
+}
+
+}
>From 77397f86a820186d9675a3ebcd1ec947b610acf5 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sat, 11 Oct 2025 00:05:22 +0200
Subject: [PATCH 3/7] Address code review comments
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 26 +++++++++++---------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 11097299212d8..d4b335d023c02 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4339,24 +4339,26 @@ def CIR_TryOp : CIR_Op<"try",[
clauses are usually allocated in the same parent as `cir.try`.
`synthetic`: use `cir.try` to represent try/catches not originally
- present in the source code (e.g. `g = new Class` under `-fexceptions`).
+ present in the source code. For example, a synthetic `cir.try` region
+ is created around the constructor call when `operator new` is used
+ so that the memory allocated will be freed if the constructor throws
+ an exception.
- `cleanup`: signal to targets (LLVM for now) that this try/catch, needs
- to specially tag their landing pads as needing "cleanup".
+ `cleanup`: indicates that there are cleanups that must be performed
+ when exiting the try region via exception, even if the exception is not
+ caught.
Example:
```mlir
- %0 = cir.alloc.exception 16 -> !cir.ptr<!some_record>
- %1 = cir.get_global @d2 : !cir.ptr<!some_record>
- cir.try synthetic cleanup {
- cir.call exception @_ZN7test2_DC1ERKS_(%0, %1)
- : (!cir.ptr<!some_record>, !cir.ptr<!some_record>) -> () cleanup {
- %2 = cir.cast bitcast %0 : !cir.ptr<!some_record> -> !cir.ptr<!void>
- cir.free.exception %2
- cir.yield
- }
+ cir.try {
+ cir.call exception @function() : () -> ()
+ cir.yield
+ } catch [type #cir.global_view<@_ZTIPf> : !cir.ptr<!u8i>] {
...
+ cir.yield
+ } unwind {
+ cir.resume
}
```
}];
>From 4cdea3f26bab4f3b0ddede1e4c5d0086f418c050 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sat, 11 Oct 2025 13:25:55 +0200
Subject: [PATCH 4/7] TryOp & Catchers Parsers and printers
---
.../CIR/Dialect/IR/CIRAttrConstraints.td | 30 +++-
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 14 +-
clang/include/clang/CIR/Dialect/IR/CIROps.td | 17 +-
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 152 +++++++++---------
clang/test/CIR/IR/invalid-try-catch.cir | 82 ++++++++--
clang/test/CIR/IR/try-catch.cir | 60 +++----
6 files changed, 223 insertions(+), 132 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
index 8f72ff4d754ad..bab847ef621bf 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
@@ -38,14 +38,32 @@ def CIR_AnyIntOrFloatAttr : AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyFPAttr],
string cppType = "::mlir::TypedAttr";
}
+//===----------------------------------------------------------------------===//
+// Exceptions constraints
+//===----------------------------------------------------------------------===//
+
+def CIR_AnyCatchAllAttr
+ : CIR_AttrConstraint<"::cir::CatchAllAttr", "catch all attribute">;
+
+def CIR_AnyUnwindAttr
+ : CIR_AttrConstraint<"::cir::UnwindAttr", "unwind attribute">;
+
//===----------------------------------------------------------------------===//
// GlobalViewAttr constraints
//===----------------------------------------------------------------------===//
-def CIR_AnyGlobalViewAttr : CIR_AttrConstraint<"::cir::GlobalViewAttr", "GlobalView attribute">;
+def CIR_AnyGlobalViewAttr
+ : CIR_AttrConstraint<"::cir::GlobalViewAttr", "GlobalView attribute">;
-def CIR_AnyIntOrGlobalViewAttr : AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyGlobalViewAttr],
- "integer or global view attribute"> {
+def CIR_AnyIntOrGlobalViewAttr
+ : AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyGlobalViewAttr],
+ "integer or global view attribute"> {
+ string cppType = "::mlir::TypedAttr";
+}
+
+def CIR_AnyGlobalViewOrCatchAllOrUnwindAttr
+ : AnyAttrOf<[CIR_AnyGlobalViewAttr, CIR_AnyCatchAllAttr, CIR_AnyUnwindAttr],
+ "catch all or unwind or global view attribute"> {
string cppType = "::mlir::TypedAttr";
}
@@ -61,4 +79,8 @@ def CIR_IntOrGlobalViewArrayAttr : TypedArrayAttrBase<CIR_AnyIntOrGlobalViewAttr
string cppType = "::mlir::ArrayAttr";
}
-#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
\ No newline at end of file
+def CIR_GlobalViewOrCatchAllOrUnwindArrayAttr
+ : TypedArrayAttrBase<CIR_AnyGlobalViewOrCatchAllOrUnwindAttr,
+ "catch all or unwind or global view array attribute">;
+
+#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index e739378e3969c..69dbad3ba1cde 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -969,18 +969,18 @@ def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
}
//===----------------------------------------------------------------------===//
-// CatchAllAttr & CatchUnwindAttr
+// CatchAllAttr & UnwindAttr
//===----------------------------------------------------------------------===//
-// Represents the unwind region where unwind continues or
-// the program std::terminate's.
-def CIR_CatchUnwindAttr : CIR_UnitAttr<"CatchUnwind", "unwind"> {
- let storageType = [{ CatchUnwind }];
-}
-
// Represents the catch_all region.
def CIR_CatchAllAttr : CIR_UnitAttr<"CatchAll", "all"> {
let storageType = [{ CatchAllAttr }];
}
+// Represents the unwind region where unwind continues or
+// the program std::terminate's.
+def CIR_UnwindAttr : CIR_UnitAttr<"Unwind", "unwind"> {
+ let storageType = [{ CatchUnwind }];
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d4b335d023c02..a321ef2ceb41d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4363,10 +4363,16 @@ def CIR_TryOp : CIR_Op<"try",[
```
}];
- let arguments = (ins UnitAttr:$synthetic, UnitAttr:$cleanup,
- OptionalAttr<ArrayAttr>:$catch_types);
- let regions = (region AnyRegion:$try_region,
- VariadicRegion<AnyRegion>:$catch_regions);
+ let arguments = (ins
+ UnitAttr:$synthetic,
+ UnitAttr:$cleanup,
+ CIR_GlobalViewOrCatchAllOrUnwindArrayAttr:$catch_types
+ );
+
+ let regions = (region
+ AnyRegion:$try_region,
+ VariadicRegion<MinSizedRegion<1>>:$catch_regions
+ );
let assemblyFormat = [{
(`synthetic` $synthetic^)?
@@ -4376,7 +4382,6 @@ def CIR_TryOp : CIR_Op<"try",[
attr-dict
}];
- // Everything already covered elsewhere.
let builders = [
OpBuilder<(ins
"llvm::function_ref<void(mlir::OpBuilder &, "
@@ -4390,7 +4395,7 @@ def CIR_TryOp : CIR_Op<"try",[
OpBuilder::InsertionGuard guard($_builder);
// Try body region
- Region *tryBodyRegion = $_state.addRegion();
+ mlir::Region *tryBodyRegion = $_state.addRegion();
// Create try body region and set insertion point
$_builder.createBlock(tryBodyRegion);
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 40587fef47f7b..1ff0a784e4eda 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2919,113 +2919,117 @@ LogicalResult cir::TypeInfoAttr::verify(
//===----------------------------------------------------------------------===//
void cir::TryOp::getSuccessorRegions(
- mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
- // If any index all the underlying regions branch back to the parent
- // operation.
+ mlir::RegionBranchPoint point,
+ llvm::SmallVectorImpl<mlir::RegionSuccessor> ®ions) {
+ // The `try` and the `catchers` region branch back to the parent operation.
if (!point.isParent()) {
- regions.push_back(RegionSuccessor());
+ regions.push_back(mlir::RegionSuccessor());
return;
}
- // If the condition isn't constant, both regions may be executed.
- regions.push_back(RegionSuccessor(&getTryRegion()));
+ regions.push_back(mlir::RegionSuccessor(&getTryRegion()));
- // FIXME: optimize, ideas include:
- // - If we know a target function never throws a specific type, we can
- // remove the catch handler.
- for (mlir::Region &r : this->getCatchRegions())
- regions.push_back(RegionSuccessor(&r));
+ // TODO(CIR): If we know a target function never throws a specific type, we
+ // can remove the catch handler.
+ for (mlir::Region ®ion : this->getCatchRegions())
+ regions.push_back(mlir::RegionSuccessor(®ion));
}
-static void printCatchRegions(OpAsmPrinter &printer, cir::TryOp op,
- mlir::MutableArrayRef<::mlir::Region> regions,
+static void printCatchRegions(mlir::OpAsmPrinter &printer, cir::TryOp op,
+ mlir::MutableArrayRef<mlir::Region> regions,
mlir::ArrayAttr catchersAttr) {
if (!catchersAttr)
return;
- int currCatchIdx = 0;
- printer << "catch [";
- llvm::interleaveComma(catchersAttr, printer, [&](const Attribute &a) {
- if (mlir::isa<cir::CatchUnwindAttr>(a)) {
- printer.printAttribute(a);
+ for (const auto [catcherIdx, catcherAttr] : llvm::enumerate(catchersAttr)) {
+ if (catcherIdx)
printer << " ";
- } else if (!a) {
- printer << "all";
+
+ if (mlir::isa<cir::CatchAllAttr>(catcherAttr)) {
+ printer << "catch all ";
+ } else if (mlir::isa<cir::UnwindAttr>(catcherAttr)) {
+ printer << "unwind ";
} else {
- printer << "type ";
- printer.printAttribute(a);
- printer << " ";
+ printer << "catch [type ";
+ printer.printAttribute(catcherAttr);
+ printer << "] ";
}
- printer.printRegion(regions[currCatchIdx], /*printEntryBLockArgs=*/false,
- /*printBlockTerminators=*/true);
- currCatchIdx++;
- });
- printer << "]";
+ printer.printRegion(regions[catcherIdx], /*printEntryBLockArgs=*/false,
+ /*printBlockTerminators=*/true);
+ }
}
-static ParseResult parseCatchRegions(
- OpAsmParser &parser,
- llvm::SmallVectorImpl<std::unique_ptr<::mlir::Region>> ®ions,
- ::mlir::ArrayAttr &catchersAttr) {
- if (parser.parseKeyword("catch").failed())
- return parser.emitError(parser.getCurrentLocation(),
- "expected 'catch' keyword here");
+static mlir::ParseResult
+parseCatchRegions(mlir::OpAsmParser &parser,
+ llvm::SmallVectorImpl<std::unique_ptr<mlir::Region>> ®ions,
+ mlir::ArrayAttr &catchersAttr) {
- auto parseAndCheckRegion = [&]() -> ParseResult {
- // Parse region attached to catch
- regions.emplace_back(new Region);
- Region &currRegion = *regions.back();
- SMLoc parserLoc = parser.getCurrentLocation();
+ auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
+ regions.emplace_back(new mlir::Region);
+
+ mlir::Region &currRegion = *regions.back();
+ mlir::SMLoc regionLoc = parser.getCurrentLocation();
if (parser.parseRegion(currRegion)) {
regions.clear();
return failure();
}
- if (currRegion.empty()) {
- return parser.emitError(parser.getCurrentLocation(),
- "catch region shall not be empty");
- }
-
- if (!(currRegion.back().mightHaveTerminator() &&
- currRegion.back().getTerminator()))
+ if (!currRegion.empty() && !(currRegion.back().mightHaveTerminator() &&
+ currRegion.back().getTerminator()))
return parser.emitError(
- parserLoc, "blocks are expected to be explicitly terminated");
+ regionLoc, "blocks are expected to be explicitly terminated");
return success();
};
- llvm::SmallVector<mlir::Attribute, 4> catchList;
- auto parseCatchEntry = [&]() -> ParseResult {
- mlir::Attribute exceptionTypeInfo;
+ bool hasCatchAll = false;
+ llvm::SmallVector<mlir::Attribute, 4> catcherAttrs;
+ while (parser.parseOptionalKeyword("catch").succeeded()) {
+ bool hasLSquare = parser.parseOptionalLSquare().succeeded();
- if (parser.parseOptionalAttribute(exceptionTypeInfo).has_value()) {
- catchList.push_back(exceptionTypeInfo);
- } else {
- ::llvm::StringRef attrStr;
- if (parser.parseOptionalKeyword(&attrStr, {"all"}).succeeded()) {
- // "all" keyword found, exceptionTypeInfo remains null
- } else if (parser.parseOptionalKeyword("type").succeeded()) {
- if (parser.parseAttribute(exceptionTypeInfo).failed())
- return parser.emitError(parser.getCurrentLocation(),
- "expected valid RTTI info attribute");
- } else {
+ llvm::StringRef attrStr;
+ if (parser.parseOptionalKeyword(&attrStr, {"all", "type"}).failed())
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected 'all' or 'type' keyword");
+
+ bool isCatchAll = attrStr == "all";
+ if (isCatchAll) {
+ if (hasCatchAll)
return parser.emitError(parser.getCurrentLocation(),
- "expected attribute, 'all', or 'type' keyword");
- }
- catchList.push_back(exceptionTypeInfo);
+ "can't have more than one catch all");
+ hasCatchAll = true;
}
- return parseAndCheckRegion();
- };
- if (parser
- .parseCommaSeparatedList(OpAsmParser::Delimiter::Square,
- parseCatchEntry, " in catch list")
- .failed())
- return failure();
+ mlir::Attribute exceptionRTTIAttr;
+ if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected valid RTTI info attribute");
- catchersAttr = parser.getBuilder().getArrayAttr(catchList);
- return ::mlir::success();
+ catcherAttrs.push_back(isCatchAll
+ ? cir::CatchAllAttr::get(parser.getContext())
+ : exceptionRTTIAttr);
+
+ if (hasLSquare && isCatchAll)
+ return parser.emitError(parser.getCurrentLocation(),
+ "catch all dosen't need RTTI info attribute");
+
+ if (hasLSquare && parser.parseRSquare().failed())
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected `]` after RTTI info attribute");
+
+ if (parseCheckedCatcherRegion().failed())
+ return mlir::failure();
+ }
+
+ if (parser.parseOptionalKeyword("unwind").succeeded()) {
+ catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
+ if (parseCheckedCatcherRegion().failed())
+ return mlir::failure();
+ }
+
+ catchersAttr = parser.getBuilder().getArrayAttr(catcherAttrs);
+ return mlir::success();
}
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/IR/invalid-try-catch.cir b/clang/test/CIR/IR/invalid-try-catch.cir
index 57863af13d20b..40eaa7b06e3c3 100644
--- a/clang/test/CIR/IR/invalid-try-catch.cir
+++ b/clang/test/CIR/IR/invalid-try-catch.cir
@@ -6,10 +6,10 @@ cir.func dso_local @invalid_catch_without_all_or_type() {
cir.scope {
cir.try {
cir.yield
- // expected-error @below {{'cir.try' expected attribute, 'all', or 'type' keyword}}
+ // expected-error @below {{'cir.try' expected 'all' or 'type' keyword}}
} catch [invalid_keyword {
cir.yield
- }]
+ }
}
cir.return
}
@@ -22,13 +22,12 @@ module {
cir.func dso_local @invalid_catch_rtti_type() {
cir.scope {
+ // expected-error @below {{'cir.try' op attribute 'catch_types' failed to satisfy constraint: catch all or unwind or global view array attribute}}
cir.try {
cir.yield
- // expected-error @below {{expected attribute value}}
- // expected-error @below {{'cir.try' expected valid RTTI info attribute}}
- } catch [type invalid_type {
+ } catch [type #cir.undef] {
cir.yield
- }]
+ }
}
cir.return
}
@@ -41,11 +40,11 @@ module {
cir.func dso_local @invalid_catch_empty_block() {
cir.scope {
+ // expected-error @below {{'cir.try' op region #1 ('catch_regions') failed to verify constraint: region with at least 1 blocks}}
cir.try {
cir.yield
- } catch [type #cir.all {
- // expected-error @below {{'cir.try' catch region shall not be empty}}
- }]
+ } catch all {
+ }
}
cir.return
}
@@ -65,11 +64,72 @@ cir.func dso_local @invalid_catch_not_terminated() {
cir.yield
}
// expected-error @below {{'cir.try' blocks are expected to be explicitly terminated}}
- catch [type #cir.all {
+ catch all {
%tmp_a = cir.load %a : !cir.ptr<!s32i>, !s32i
- }]
+ }
}
cir.return
}
}
+
+// -----
+
+module {
+
+cir.func dso_local @invalid_catch_multiple_catch_all() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ } catch all {
+ cir.yield
+ }
+ // expected-error @below {{op 'cir.try' can't have more than one catch all}}
+ catch all {
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+module {
+
+cir.func dso_local @invalid_catch_without_type_info() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ }
+ // expected-error @below {{expected attribute value}}
+ // expected-error @below {{op 'cir.try' expected valid RTTI info attribute}}
+ catch [type] {
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+module {
+
+cir.func dso_local @invalid_catch_all_with_type_info() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ }
+ // expected-error @below {{op 'cir.try' catch all dosen't need RTTI info attribute}}
+ catch [all] {
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
diff --git a/clang/test/CIR/IR/try-catch.cir b/clang/test/CIR/IR/try-catch.cir
index 7bc71ff84d4ae..7becd0b559f5e 100644
--- a/clang/test/CIR/IR/try-catch.cir
+++ b/clang/test/CIR/IR/try-catch.cir
@@ -11,57 +11,57 @@ cir.func dso_local @empty_try_block_with_catch_all() {
cir.scope {
cir.try {
cir.yield
- } catch [type #cir.all {
+ } catch all {
cir.yield
- }]
+ }
}
cir.return
}
-// CHECK: cir.func dso_local @empty_try_block_with_catch_all() {
-// CHECK: cir.scope {
-// CHECK: cir.try {
-// CHECK: cir.yield
-// CHECK: } catch [type #cir.all {
-// CHECK: cir.yield
-// CHECK: }]
-// CHECK: }
-// CHECK: cir.return
-// CHECK: }
+// CHECK: cir.func dso_local @empty_try_block_with_catch_all() {
+// CHECK: cir.scope {
+// CHECK: cir.try {
+// CHECK: cir.yield
+// CHECK: } catch all {
+// CHECK: cir.yield
+// CHECK: }
+// CHECK: }
+// CHECK: cir.return
+// CHECK: }
cir.func dso_local @empty_try_block_with_catch_unwind() {
cir.scope {
cir.try {
cir.yield
- } catch [#cir.unwind {
+ } unwind {
cir.yield
- }]
+ }
}
cir.return
}
// CHECK: cir.func dso_local @empty_try_block_with_catch_unwind() {
-// CHECK: cir.scope {
-// CHECK: cir.try {
-// CHECK: cir.yield
-// CHECK: } catch [#cir.unwind {
-// CHECK: cir.yield
-// CHECK: }]
-// CHECK: }
-// CHECK: cir.return
+// CHECK: cir.scope {
+// CHECK: cir.try {
+// CHECK: cir.yield
+// CHECK: } unwind {
+// CHECK: cir.yield
+// CHECK: }
+// CHECK: }
+// CHECK: cir.return
// CHECK: }
cir.func dso_local @empty_try_block_with_catch_ist() {
cir.scope {
cir.try {
cir.yield
- } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i> {
+ } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] {
cir.yield
- }, type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i> {
+ } catch [type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>] {
cir.yield
- }, #cir.unwind {
+ } unwind {
cir.yield
- }]
+ }
}
cir.return
}
@@ -70,13 +70,13 @@ cir.func dso_local @empty_try_block_with_catch_ist() {
// CHECK: cir.scope {
// CHECK: cir.try {
// CHECK: cir.yield
-// CHECK: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i> {
+// CHECK: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] {
// CHECK: cir.yield
-// CHECK: }, type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i> {
+// CHECK: } catch [type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>] {
// CHECK: cir.yield
-// CHECK: }, #cir.unwind {
+// CHECK: } unwind {
// CHECK: cir.yield
-// CHECK: }]
+// CHECK: }
// CHECK: }
// CHECK: cir.return
// CHECK: }
>From 53690902122b9e1d69dc579e5e5eaf6a8a69800f Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sun, 12 Oct 2025 17:44:44 +0200
Subject: [PATCH 5/7] Add error message for using unwind with catch all
---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 ++++
clang/test/CIR/IR/invalid-try-catch.cir | 23 ++++++++++++++++++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 1ff0a784e4eda..3733ca1cbd777 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -3023,6 +3023,10 @@ parseCatchRegions(mlir::OpAsmParser &parser,
}
if (parser.parseOptionalKeyword("unwind").succeeded()) {
+ if (hasCatchAll)
+ return parser.emitError(parser.getCurrentLocation(),
+ "unwind can't be used with catch all");
+
catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
if (parseCheckedCatcherRegion().failed())
return mlir::failure();
diff --git a/clang/test/CIR/IR/invalid-try-catch.cir b/clang/test/CIR/IR/invalid-try-catch.cir
index 40eaa7b06e3c3..4c4187d346846 100644
--- a/clang/test/CIR/IR/invalid-try-catch.cir
+++ b/clang/test/CIR/IR/invalid-try-catch.cir
@@ -122,7 +122,7 @@ cir.func dso_local @invalid_catch_all_with_type_info() {
cir.scope {
cir.try {
cir.yield
- }
+ }
// expected-error @below {{op 'cir.try' catch all dosen't need RTTI info attribute}}
catch [all] {
cir.yield
@@ -133,3 +133,24 @@ cir.func dso_local @invalid_catch_all_with_type_info() {
}
+// -----
+
+module {
+
+cir.func dso_local @invalid_unwind_with_catch_all() {
+ cir.scope {
+ cir.try {
+ cir.yield
+ }
+ catch all {
+ cir.yield
+ }
+ // expected-error @below {{op 'cir.try' unwind can't be used with catch all}}
+ unwind {
+
+ }
+ }
+ cir.return
+}
+
+}
>From 01e63fb8456a669f972ce571d6934c2077bb7b90 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Mon, 13 Oct 2025 19:55:58 +0200
Subject: [PATCH 6/7] Rename catch_regions to handlers to act as general eh
regions
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 4 ++--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index a321ef2ceb41d..28cf3292c083d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4371,14 +4371,14 @@ def CIR_TryOp : CIR_Op<"try",[
let regions = (region
AnyRegion:$try_region,
- VariadicRegion<MinSizedRegion<1>>:$catch_regions
+ VariadicRegion<MinSizedRegion<1>>:$handlers
);
let assemblyFormat = [{
(`synthetic` $synthetic^)?
(`cleanup` $cleanup^)?
$try_region
- custom<CatchRegions>($catch_regions, $catch_types)
+ custom<CatchRegions>($handlers, $catch_types)
attr-dict
}];
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 3733ca1cbd777..ab2a1156c9f22 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2931,8 +2931,8 @@ void cir::TryOp::getSuccessorRegions(
// TODO(CIR): If we know a target function never throws a specific type, we
// can remove the catch handler.
- for (mlir::Region ®ion : this->getCatchRegions())
- regions.push_back(mlir::RegionSuccessor(®ion));
+ for (mlir::Region &handler : this->getHandlers())
+ regions.push_back(mlir::RegionSuccessor(&handler));
}
static void printCatchRegions(mlir::OpAsmPrinter &printer, cir::TryOp op,
>From 905b0dbc8e71f6ee07690ca61b64f1d49401f060 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Wed, 15 Oct 2025 18:55:47 +0200
Subject: [PATCH 7/7] Address code review comments
---
.../CIR/Dialect/IR/CIRAttrConstraints.td | 5 +--
clang/include/clang/CIR/Dialect/IR/CIROps.td | 13 +++---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 42 ++++++++++---------
clang/test/CIR/IR/invalid-try-catch.cir | 4 +-
4 files changed, 33 insertions(+), 31 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
index bab847ef621bf..2548d464fb07f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
@@ -61,7 +61,7 @@ def CIR_AnyIntOrGlobalViewAttr
string cppType = "::mlir::TypedAttr";
}
-def CIR_AnyGlobalViewOrCatchAllOrUnwindAttr
+def CIR_TryHandlerAttr
: AnyAttrOf<[CIR_AnyGlobalViewAttr, CIR_AnyCatchAllAttr, CIR_AnyUnwindAttr],
"catch all or unwind or global view attribute"> {
string cppType = "::mlir::TypedAttr";
@@ -79,8 +79,7 @@ def CIR_IntOrGlobalViewArrayAttr : TypedArrayAttrBase<CIR_AnyIntOrGlobalViewAttr
string cppType = "::mlir::ArrayAttr";
}
-def CIR_GlobalViewOrCatchAllOrUnwindArrayAttr
- : TypedArrayAttrBase<CIR_AnyGlobalViewOrCatchAllOrUnwindAttr,
+def CIR_TryHandlerArrayAttr : TypedArrayAttrBase<CIR_TryHandlerAttr,
"catch all or unwind or global view array attribute">;
#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 28cf3292c083d..4b26f814cbbe9 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4366,19 +4366,19 @@ def CIR_TryOp : CIR_Op<"try",[
let arguments = (ins
UnitAttr:$synthetic,
UnitAttr:$cleanup,
- CIR_GlobalViewOrCatchAllOrUnwindArrayAttr:$catch_types
+ CIR_TryHandlerArrayAttr:$handler_types
);
let regions = (region
AnyRegion:$try_region,
- VariadicRegion<MinSizedRegion<1>>:$handlers
+ VariadicRegion<MinSizedRegion<1>>:$handler_regions
);
let assemblyFormat = [{
(`synthetic` $synthetic^)?
(`cleanup` $cleanup^)?
$try_region
- custom<CatchRegions>($handlers, $catch_types)
+ custom<TryHandlerRegions>($handler_regions, $handler_types)
attr-dict
}];
@@ -4387,10 +4387,11 @@ def CIR_TryOp : CIR_Op<"try",[
"llvm::function_ref<void(mlir::OpBuilder &, "
"mlir::Location)>":$tryBuilder,
"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location, "
- "mlir::OperationState &)>":$catchBuilder),
+ "mlir::OperationState &)>":$handlersBuilder),
[{
assert(tryBuilder && "expected builder callback for 'cir.try' body");
- assert(catchBuilder && "expected builder callback for 'catch' body");
+ assert(handlersBuilder
+ && "expected builder callback for 'handlers' body");
OpBuilder::InsertionGuard guard($_builder);
@@ -4400,7 +4401,7 @@ def CIR_TryOp : CIR_Op<"try",[
// Create try body region and set insertion point
$_builder.createBlock(tryBodyRegion);
tryBuilder($_builder, $_state.location);
- catchBuilder($_builder, $_state.location, $_state);
+ handlersBuilder($_builder, $_state.location, $_state);
}]>
];
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index ab2a1156c9f22..0712de2d2f182 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2931,47 +2931,49 @@ void cir::TryOp::getSuccessorRegions(
// TODO(CIR): If we know a target function never throws a specific type, we
// can remove the catch handler.
- for (mlir::Region &handler : this->getHandlers())
- regions.push_back(mlir::RegionSuccessor(&handler));
+ for (mlir::Region &handlerRegion : this->getHandlerRegions())
+ regions.push_back(mlir::RegionSuccessor(&handlerRegion));
}
-static void printCatchRegions(mlir::OpAsmPrinter &printer, cir::TryOp op,
- mlir::MutableArrayRef<mlir::Region> regions,
- mlir::ArrayAttr catchersAttr) {
- if (!catchersAttr)
+static void
+printTryHandlerRegions(mlir::OpAsmPrinter &printer, cir::TryOp op,
+ mlir::MutableArrayRef<mlir::Region> handlerRegions,
+ mlir::ArrayAttr handlerTypes) {
+ if (!handlerTypes)
return;
- for (const auto [catcherIdx, catcherAttr] : llvm::enumerate(catchersAttr)) {
- if (catcherIdx)
+ for (const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
+ if (typeIdx)
printer << " ";
- if (mlir::isa<cir::CatchAllAttr>(catcherAttr)) {
+ if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
printer << "catch all ";
- } else if (mlir::isa<cir::UnwindAttr>(catcherAttr)) {
+ } else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
printer << "unwind ";
} else {
printer << "catch [type ";
- printer.printAttribute(catcherAttr);
+ printer.printAttribute(typeAttr);
printer << "] ";
}
- printer.printRegion(regions[catcherIdx], /*printEntryBLockArgs=*/false,
+ printer.printRegion(handlerRegions[typeIdx],
+ /*printEntryBLockArgs=*/false,
/*printBlockTerminators=*/true);
}
}
-static mlir::ParseResult
-parseCatchRegions(mlir::OpAsmParser &parser,
- llvm::SmallVectorImpl<std::unique_ptr<mlir::Region>> ®ions,
- mlir::ArrayAttr &catchersAttr) {
+static mlir::ParseResult parseTryHandlerRegions(
+ mlir::OpAsmParser &parser,
+ llvm::SmallVectorImpl<std::unique_ptr<mlir::Region>> &handlerRegions,
+ mlir::ArrayAttr &handlerTypes) {
auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
- regions.emplace_back(new mlir::Region);
+ handlerRegions.emplace_back(new mlir::Region);
- mlir::Region &currRegion = *regions.back();
+ mlir::Region &currRegion = *handlerRegions.back();
mlir::SMLoc regionLoc = parser.getCurrentLocation();
if (parser.parseRegion(currRegion)) {
- regions.clear();
+ handlerRegions.clear();
return failure();
}
@@ -3032,7 +3034,7 @@ parseCatchRegions(mlir::OpAsmParser &parser,
return mlir::failure();
}
- catchersAttr = parser.getBuilder().getArrayAttr(catcherAttrs);
+ handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
return mlir::success();
}
diff --git a/clang/test/CIR/IR/invalid-try-catch.cir b/clang/test/CIR/IR/invalid-try-catch.cir
index 4c4187d346846..04a4d2543b8e1 100644
--- a/clang/test/CIR/IR/invalid-try-catch.cir
+++ b/clang/test/CIR/IR/invalid-try-catch.cir
@@ -22,7 +22,7 @@ module {
cir.func dso_local @invalid_catch_rtti_type() {
cir.scope {
- // expected-error @below {{'cir.try' op attribute 'catch_types' failed to satisfy constraint: catch all or unwind or global view array attribute}}
+ // expected-error @below {{'cir.try' op attribute 'handler_types' failed to satisfy constraint: catch all or unwind or global view array attribute}}
cir.try {
cir.yield
} catch [type #cir.undef] {
@@ -40,7 +40,7 @@ module {
cir.func dso_local @invalid_catch_empty_block() {
cir.scope {
- // expected-error @below {{'cir.try' op region #1 ('catch_regions') failed to verify constraint: region with at least 1 blocks}}
+ // expected-error @below {{'cir.try' op region #1 ('handler_regions') failed to verify constraint: region with at least 1 blocks}}
cir.try {
cir.yield
} catch all {
More information about the cfe-commits
mailing list