Skip to content

Commit

Permalink
emit unreachable directly and llvm output
Browse files Browse the repository at this point in the history
  • Loading branch information
bruteforceboy committed Feb 6, 2025
1 parent 75e11ef commit 2b4a28a
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 130 deletions.
32 changes: 1 addition & 31 deletions clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2270,38 +2270,8 @@ void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &CGF, bool isNoReturn) {

if (isNoReturn) {
auto &builder = CGF.getBuilder();

// The idea here is creating a separate block for the rethrow with an
// `UnreachableOp` as the terminator. So, we branch from the current block
// to the rethrow block and create a block for the remaining operations.

auto currentBlock = builder.getInsertionBlock();
auto reg = currentBlock->getParent();

bool branch = false;
if (currentBlock->empty())
currentBlock->erase();
else
branch = true;

auto rethrowBlock = builder.createBlock(reg);
builder.setInsertionPointToStart(rethrowBlock);
builder.createTryCallOp(Fn.getLoc(), Fn, {});
builder.createTryCallOp(loc, Fn, {});
builder.create<cir::UnreachableOp>(loc);

if (branch) {
builder.setInsertionPointToEnd(currentBlock);
builder.create<cir::BrOp>(loc, rethrowBlock);
}

auto remBlock = builder.createBlock(reg);
builder.setInsertionPointToEnd(remBlock);
// This will be erased during codegen, it acts as a placeholder for the
// operations to be inserted (if any)
builder.create<cir::ScopeOp>(Fn.getLoc(), /*scopeBuilder=*/
[&](mlir::OpBuilder &b, mlir::Location loc) {
b.create<cir::YieldOp>(loc);
});
} else {
llvm_unreachable("NYI");
}
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,11 +426,12 @@ class CIRTryOpFlattening : public mlir::OpRewritePattern<cir::TryOp> {
SmallVectorImpl<mlir::Block *> &landingPads) const {
// Replace the tryOp return with a branch that jumps out of the body.
rewriter.setInsertionPointToEnd(afterBody);
auto tryBodyYield = cast<cir::YieldOp>(afterBody->getTerminator());

mlir::Block *beforeCatch = rewriter.getInsertionBlock();
rewriter.setInsertionPointToEnd(beforeCatch);
rewriter.replaceOpWithNewOp<cir::BrOp>(tryBodyYield, afterTry);

if (auto tryBodyYield = dyn_cast<cir::YieldOp>(afterBody->getTerminator()))
rewriter.replaceOpWithNewOp<cir::BrOp>(tryBodyYield, afterTry);

// Start the landing pad by getting the inflight exception information.
mlir::Block *nextDispatcher =
Expand Down
179 changes: 178 additions & 1 deletion clang/test/CIR/CodeGen/throw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,181 @@ double d(int a, int b) {
// LLVM: %[[ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8)
// LLVM: store ptr @.str, ptr %[[ADDR]], align 8
// LLVM: call void @__cxa_throw(ptr %[[ADDR]], ptr @_ZTIPKc, ptr null)
// LLVM: unreachable
// LLVM: unreachable

struct S {
S() {}
};

void refoo1() {
int r = 1;
try {
S s;
throw;
} catch (...) {
++r;
}
}

// CIR-LABEL: @_Z6refoo1v()
// CIR: %[[V0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init] {alignment = 4 : i64}
// CIR: %[[V1:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store %[[V1]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.scope {
// CIR: %[[V2:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
// CIR: cir.try {
// CIR: cir.call exception @_ZN1SC2Ev(%[[V2]]) : (!cir.ptr<!ty_S>) -> ()
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
// CIR: cir.unreachable
// CIR: } catch [type #cir.all {
// CIR: %[[V3:.*]] = cir.catch_param -> !cir.ptr<!void>
// CIR: %[[V4:.*]] = cir.load %[[V0]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V5:.*]] = cir.unary(inc, %[[V4]]) : !s32i, !s32i
// CIR: cir.store %[[V5]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: }]
// CIR: }
// CIR: cir.return
// CIR: }

// LLVM: @__cxa_rethrow()
// LLVM: define dso_local void @_Z6refoo1v()
// LLVM: %[[V1:.*]] = alloca %struct.S, i64 1, align 1
// LLVM: %[[V2:.*]] = alloca i32, i64 1, align 4
// LLVM: store i32 1, ptr %[[V2]], align 4
// LLVM: br label %[[B3:.*]]
// LLVM: [[B3]]:
// LLVM: br label %[[B4:.*]]
// LLVM: [[B4]]:
// LLVM: invoke void @_ZN1SC2Ev(ptr %[[V1]])
// LLVM: to label %[[B5:.*]] unwind label %[[B7:.*]]
// LLVM: [[B5]]:
// LLVM: invoke void @__cxa_rethrow()
// LLVM: to label %[[B6:.*]] unwind label %[[B11:.*]]
// LLVM: [[B6]]:
// LLVM: unreachable
// LLVM: [[B7]]:
// LLVM: %[[V8:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr null
// LLVM: %[[V9:.*]] = extractvalue { ptr, i32 } %[[V8]], 0
// LLVM: %[[V10:.*]] = extractvalue { ptr, i32 } %[[V8]], 1
// LLVM: br label %[[B15:.*]]
// LLVM: [[B11]]:
// LLVM: %[[V12:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr null
// LLVM: %[[V13:.*]] = extractvalue { ptr, i32 } %[[V12]], 0
// LLVM: %[[V14:.*]] = extractvalue { ptr, i32 } %[[V12]], 1
// LLVM: br label %[[B15:.*]]
// LLVM: [[B15]]:
// LLVM: %[[V16:.*]] = phi ptr [ %[[V9]], %[[B7]] ], [ %[[V13]], %[[B11]] ]
// LLVM: %[[V17:.*]] = call ptr @__cxa_begin_catch(ptr %[[V16]])
// LLVM: %[[V18:.*]] = load i32, ptr %[[V2]], align 4
// LLVM: %[[V19:.*]] = add i32 %[[V18]], 1
// LLVM: store i32 %[[V19]], ptr %[[V2]], align 4
// LLVM: call void @__cxa_end_catch()

void refoo2() {
int r = 1;
try {
for (int i = 0; i < 5; i++) {
S s;
throw;
}
S s;
} catch (...) {
++r;
}
}

// CIR-LABEL: @_Z6refoo2v()
// CIR: %[[V0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init] {alignment = 4 : i64}
// CIR: %[[V1:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store %[[V1]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.scope {
// CIR: %[[V2:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
// CIR: cir.try {
// CIR: cir.scope {
// CIR: %[[V3:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
// CIR: %[[V4:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store %[[V4]], %[[V3]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.for : cond {
// CIR: %[[V5:.*]] = cir.load %[[V3]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V6:.*]] = cir.const #cir.int<5> : !s32i
// CIR: %[[V7:.*]] = cir.cmp(lt, %[[V5]], %[[V6]]) : !s32i, !cir.bool
// CIR: cir.condition(%[[V7]])
// CIR: } body {
// CIR: cir.scope {
// CIR: %[[V5:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
// CIR: cir.call exception @_ZN1SC2Ev(%[[V5]]) : (!cir.ptr<!ty_S>) -> ()
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
// CIR: cir.unreachable
// CIR: }
// CIR: cir.yield
// CIR: } step {
// CIR: %[[V5:.*]] = cir.load %[[V3]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V6:.*]] = cir.unary(inc, %[[V5]]) : !s32i, !s32i
// CIR: cir.store %[[V6]], %[[V3]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: }
// CIR: }
// CIR: cir.call exception @_ZN1SC2Ev(%[[V2]]) : (!cir.ptr<!ty_S>) -> ()
// CIR: cir.yield
// CIR: } catch [type #cir.all {
// CIR: %[[V3:.*]] = cir.catch_param -> !cir.ptr<!void>
// CIR: %[[V4:.*]] = cir.load %[[V0]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V5:.*]] = cir.unary(inc, %[[V4]]) : !s32i, !s32i
// CIR: cir.store %[[V5]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: }]
// CIR: }
// CIR: cir.return
// CIR: }

// LLVM: {{.*}}:
// LLVM: invoke void @_ZN1SC2Ev(ptr %[[V3:.*]])
// LLVM: to label %[[B13:.*]] unwind label %[[B22:.*]]
// LLVM: [[B13]]:
// LLVM: invoke void @__cxa_rethrow()
// LLVM: to label %[[B14:.*]] unwind label %[[B26:.*]]
// LLVM: [[B14]]:
// LLVM: unreachable
// LLVM: [[B15]]:
// LLVM: br label %[[B16:.*]]
// LLVM: [[B16]]:
// LLVM: %[[V17]] = load i32, ptr {{.*}}, align 4
// LLVM: %[[V18]] = add i32 %[[V17]], 1
// LLVM: store i32 %[[V18]], ptr {{.*}}, align 4
// LLVM: br label {{.*}}
// LLVM: %[[B19:.*]]
// LLVM: br label %[[B20:.*]]
// LLVM: [[B20]]:
// LLVM: invoke void @_ZN1SC2Ev(ptr {{.*}})
// LLVM: to label %[[B21:.*]] unwind label %[[B30:.*]]
// LLVM: [[B21]]:
// LLVM: br label {{.*}}
// LLVM: [[B22]]:
// LLVM: %[[V23:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr null
// LLVM: %[[V24:.*]] = extractvalue { ptr, i32 } %[[V23]], 0
// LLVM: %[[V25:.*]] = extractvalue { ptr, i32 } %[[V23]], 1
// LLVM: br label %[[B34:.*]]
// LLVM: [[B26]]:
// LLVM: %[[V27:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr null
// LLVM: %[[V28:.*]] = extractvalue { ptr, i32 } %[[V27]], 0
// LLVM: %[[V29:.*]] = extractvalue { ptr, i32 } %[[V27]], 1
// LLVM: br label %[[B34:.*]]
// LLVM: [[B30]]:
// LLVM: %[[V31:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr null
// LLVM: %[[V32:.*]] = extractvalue { ptr, i32 } %[[V31]], 0
// LLVM: %[[V33:.*]] = extractvalue { ptr, i32 } %[[V31]], 1
// LLVM: br label %[[B34:.*]]
// LLVM: [[B34]]:
// LLVM: %[[V35:.*]] = phi ptr [ %[[V32]], %[[B30]] ], [ %[[V24]], %[[B22]] ], [ %[[V28]], %[[B26]] ]
// LLVM: %[[V36:.*]] = call ptr @__cxa_begin_catch(ptr %[[V35]])
// LLVM: %[[V37:.*]] = load i32, ptr {{.*}}, align 4
// LLVM: %[[V38:.*]] = add i32 %[[V37]], 1
// LLVM: store i32 %[[V38]], ptr {{.*}}, align 4
// LLVM: call void @__cxa_end_catch()
// LLVM: br label {{.*}}
96 changes: 0 additions & 96 deletions clang/test/CIR/CodeGen/try-catch-dtors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,99 +339,3 @@ void bar() {
// CIR: cir.store %[[V3]], %[[V1]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr<!ty_A>) -> () extra(#fn_attr)
// CIR: cir.return

struct S {
S() {}
};

void refoo1() {
int r = 1;
try {
S s;
throw;
} catch (...) {
++r;
}
}

// CIR-LABEL: @_Z6refoo1v()
// CIR: %[[V0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init] {alignment = 4 : i64}
// CIR: %[[V1:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store %[[V1]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.scope {
// CIR: %[[V2:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
// CIR: cir.try {
// CIR: cir.call exception @_ZN1SC2Ev(%[[V2]]) : (!cir.ptr<!ty_S>) -> ()
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
// CIR: cir.unreachable
// CIR: ^bb1: // no predecessors
// CIR: cir.yield
// CIR: } catch [type #cir.all {
// CIR: %[[V3:.*]] = cir.catch_param -> !cir.ptr<!void>
// CIR: %[[V4:.*]] = cir.load %[[V0]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V5:.*]] = cir.unary(inc, %[[V4]]) : !s32i, !s32i
// CIR: cir.store %[[V5]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: }]
// CIR: }
// CIR: cir.return
// CIR: }

void refoo2() {
int r = 1;
try {
for (int i = 0; i < 5; i++) {
S s;
throw;
}
S s;
} catch (...) {
++r;
}
}

// CIR-LABEL: @_Z6refoo2v()
// CIR: %[[V0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["r", init] {alignment = 4 : i64}
// CIR: %[[V1:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store %[[V1]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.scope {
// CIR: %[[V2:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
// CIR: cir.try {
// CIR: cir.scope {
// CIR: %[[V3:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
// CIR: %[[V4:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store %[[V4]], %[[V3]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.for : cond {
// CIR: %[[V5:.*]] = cir.load %[[V3]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V6:.*]] = cir.const #cir.int<5> : !s32i
// CIR: %[[V7:.*]] = cir.cmp(lt, %[[V5]], %[[V6]]) : !s32i, !cir.bool
// CIR: cir.condition(%[[V7]])
// CIR: } body {
// CIR: cir.scope {
// CIR: %[[V5:.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s", init] {alignment = 1 : i64}
// CIR: cir.call exception @_ZN1SC2Ev(%[[V5]]) : (!cir.ptr<!ty_S>) -> ()
// CIR: cir.call exception @__cxa_rethrow() : () -> ()
// CIR: cir.unreachable
// CIR: ^bb1: // no predecessors
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: } step {
// CIR: %[[V5:.*]] = cir.load %[[V3]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V6:.*]] = cir.unary(inc, %[[V5]]) : !s32i, !s32i
// CIR: cir.store %[[V6]], %[[V3]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: }
// CIR: }
// CIR: cir.call exception @_ZN1SC2Ev(%[[V2]]) : (!cir.ptr<!ty_S>) -> ()
// CIR: cir.yield
// CIR: } catch [type #cir.all {
// CIR: %[[V3:.*]] = cir.catch_param -> !cir.ptr<!void>
// CIR: %[[V4:.*]] = cir.load %[[V0]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[V5:.*]] = cir.unary(inc, %[[V4]]) : !s32i, !s32i
// CIR: cir.store %[[V5]], %[[V0]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: }]
// CIR: }
// CIR: cir.return
// CIR: }

0 comments on commit 2b4a28a

Please sign in to comment.