Skip to content

Commit e2b4540

Browse files
bruteforceboylanza
authored andcommitted
[CIR][CIRGen] Add more support for __cxa_rethrow (#1343)
This is the second part of [PR#1290](#1290), adding initial support for `__cxa_rethrow`. So, the last PR did not support statements that come after the `UnreachableOp` from the `rethrow`, we just ignored them, e.g: ``` struct S { S() {} }; void foo() { int r = 1; try { throw; S s; } catch (...) { ++r; } } ``` This PR fixes this. A few changes: - `rethrow` statements split their block into multiple blocks. - Tests with statements that come after the `rethrow` were added and old ones were modified. Concern: - The `ScopeOp` workaround still exists which I guess was one of the main concerns when we tried in the last PR. As usual, I am open to discussions on this and how to approach it better -:)
1 parent 4ff53b6 commit e2b4540

File tree

2 files changed

+126
-3
lines changed

2 files changed

+126
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,9 +2266,37 @@ void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &CGF, bool isNoReturn) {
22662266
auto &builder = CGF.getBuilder();
22672267
assert(CGF.currSrcLoc && "expected source location");
22682268
auto loc = *CGF.currSrcLoc;
2269-
builder.create<cir::ThrowOp>(loc, mlir::Value{}, mlir::FlatSymbolRefAttr{},
2270-
mlir::FlatSymbolRefAttr{});
2271-
builder.create<cir::UnreachableOp>(loc);
2269+
2270+
// The idea here is creating a separate block for the rethrow with an
2271+
// `UnreachableOp` as the terminator. So, we branch from the current block
2272+
// to the rethrow block and create a block for the remaining operations.
2273+
2274+
mlir::Block *currentBlock = builder.getInsertionBlock();
2275+
mlir::Region *region = currentBlock->getParent();
2276+
2277+
if (currentBlock->empty()) {
2278+
builder.create<cir::ThrowOp>(loc, mlir::Value{},
2279+
mlir::FlatSymbolRefAttr{},
2280+
mlir::FlatSymbolRefAttr{});
2281+
builder.create<cir::UnreachableOp>(loc);
2282+
} else {
2283+
mlir::Block *rethrowBlock = builder.createBlock(region);
2284+
builder.create<cir::ThrowOp>(loc, mlir::Value{},
2285+
mlir::FlatSymbolRefAttr{},
2286+
mlir::FlatSymbolRefAttr{});
2287+
builder.create<cir::UnreachableOp>(loc);
2288+
2289+
builder.setInsertionPointToEnd(currentBlock);
2290+
builder.create<cir::BrOp>(loc, rethrowBlock);
2291+
}
2292+
2293+
mlir::Block *remBlock = builder.createBlock(region);
2294+
// This will be erased during codegen, it acts as a placeholder for the
2295+
// operations to be inserted (if any)
2296+
builder.create<cir::ScopeOp>(loc, /*scopeBuilder=*/
2297+
[&](mlir::OpBuilder &b, mlir::Location loc) {
2298+
b.create<cir::YieldOp>(loc);
2299+
});
22722300
} else {
22732301
llvm_unreachable("NYI");
22742302
}

clang/test/CIR/CodeGen/throw.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ void refoo1() {
4747
// CIR: cir.call exception @_ZN1SC2Ev(%[[V2]]) : (!cir.ptr<!ty_S>) -> ()
4848
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
4949
// CIR: cir.unreachable
50+
// CIR: ^bb1: // no predecessors
51+
// CIR: cir.yield
5052
// CIR: } catch [type #cir.all {
5153
// CIR: %[[V3:.*]] = cir.catch_param -> !cir.ptr<!void>
5254
// CIR: %[[V4:.*]] = cir.load %[[V0]] : !cir.ptr<!s32i>, !s32i
@@ -128,6 +130,8 @@ void refoo2() {
128130
// CIR: cir.call exception @_ZN1SC2Ev(%[[V5]]) : (!cir.ptr<!ty_S>) -> ()
129131
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
130132
// CIR: cir.unreachable
133+
// CIR: ^bb1: // no predecessors
134+
// CIR: cir.yield
131135
// CIR: }
132136
// CIR: cir.yield
133137
// CIR: } step {
@@ -198,3 +202,94 @@ void refoo2() {
198202
// LLVM: store i32 %[[V38]], ptr {{.*}}, align 4
199203
// LLVM: call void @__cxa_end_catch()
200204
// LLVM: br label {{.*}}
205+
206+
void refoo3() {
207+
int r = 1;
208+
try {
209+
throw;
210+
S s;
211+
} catch (...) {
212+
++r;
213+
}
214+
}
215+
216+
// CIR-LABEL: @_Z6refoo3v()
217+
// CIR: %[[V0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init] {alignment = 4 : i64}
218+
// CIR: %[[V1:.*]] = cir.const #cir.int<1> : !s32i
219+
// CIR: cir.store %[[V1]], %[[V0]] : !s32i, !cir.ptr<!s32i>
220+
// CIR: cir.scope {
221+
// CIR: %[[V2:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
222+
// CIR: cir.try {
223+
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
224+
// CIR: cir.unreachable
225+
// CIR: ^bb1: // no predecessors
226+
// CIR: cir.call exception @_ZN1SC2Ev(%[[V2]]) : (!cir.ptr<!ty_S>) -> ()
227+
// CIR: cir.yield
228+
// CIR: } catch [type #cir.all {
229+
// CIR: %[[V3:.*]] = cir.catch_param -> !cir.ptr<!void>
230+
// CIR: %[[V4:.*]] = cir.load %[[V0]] : !cir.ptr<!s32i>, !s32i
231+
// CIR: %[[V5:.*]] = cir.unary(inc, %[[V4]]) : !s32i, !s32i
232+
// CIR: cir.store %[[V5]], %[[V0]] : !s32i, !cir.ptr<!s32i>
233+
// CIR: cir.yield
234+
// CIR: }]
235+
// CIR: }
236+
// CIR: cir.return
237+
// CIR: }
238+
239+
// LLVM: invoke void @__cxa_rethrow()
240+
// LLVM: to label %[[B5:.*]] unwind label %[[B8:.*]]
241+
// LLVM: [[B5]]:
242+
// LLVM: unreachable
243+
// LLVM: [[B6]]:
244+
// LLVM: invoke void @_ZN1SC2Ev(ptr {{.*}})
245+
// LLVM: to label %[[B7:.*]] unwind label %[[B12:.*]]
246+
// LLVM: [[B7]]:
247+
// LLVM: br label %[[B21:.*]]
248+
// LLVM: [[B8]]:
249+
// LLVM: %[[V9:.*]] = landingpad { ptr, i32 }
250+
// LLVM: catch ptr null
251+
// LLVM: %[[V10:.*]] = extractvalue { ptr, i32 } %[[V9]], 0
252+
// LLVM: %[[V11:.*]] = extractvalue { ptr, i32 } %[[V9]], 1
253+
// LLVM: br label %[[B16:.*]]
254+
// LLVM: [[B12]]:
255+
// LLVM: %[[V13:.*]] = landingpad { ptr, i32 }
256+
// LLVM: catch ptr null
257+
// LLVM: %[[V14:.*]] = extractvalue { ptr, i32 } %[[V13]], 0
258+
// LLVM: %[[V15:.*]] = extractvalue { ptr, i32 } %[[V13]], 1
259+
// LLVM: br label %[[B16]]
260+
// LLVM: [[B16]]:
261+
// LLVM: %[[V17:.*]] = phi ptr [ %[[V14]], %[[B12]] ], [ %[[V10]], %[[B8]] ]
262+
// LLVM: %[[V18:.*]] = call ptr @__cxa_begin_catch(ptr %[[V17]])
263+
// LLVM: %[[V19:.*]] = load i32, ptr {{.*}}, align 4
264+
// LLVM: %[[V20:.*]] = add i32 %[[V19]], 1
265+
// LLVM: store i32 %[[V20]], ptr {{.*}}, align 4
266+
// LLVM: call void @__cxa_end_catch()
267+
// LLVM: br label %[[B21]]
268+
// LLVM: [[B21]]:
269+
// LLVM: br label {{.*}}
270+
271+
void refoo4() {
272+
try {
273+
for (int i = 0; i < 5; i++) {
274+
throw;
275+
throw;
276+
S s;
277+
i++;
278+
}
279+
} catch (...) {
280+
int r = 1;
281+
}
282+
}
283+
284+
// CIR-LABEL: @_Z6refoo4v
285+
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
286+
// CIR-NEXT: unreachable
287+
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
288+
// CIR-NEXT: unreachable
289+
// CIR: cir.call exception @_ZN1SC2Ev
290+
291+
// LLVM: invoke void @__cxa_rethrow
292+
// LLVM: unreachable
293+
// LLVM: invoke void @__cxa_rethrow
294+
// LLVM: unreachable
295+
// LLVM: invoke void @_ZN1SC2Ev

0 commit comments

Comments
 (0)