Skip to content

Commit 3462fc6

Browse files
AmrDeveloperPriyanshu3820
authored andcommitted
[CIR] Upstream Exception EhInflight op (llvm#165621)
Upstream Exception EhInflight op as a prerequisite for full catch handlers implementation Issue llvm#154992
1 parent b01a93a commit 3462fc6

File tree

3 files changed

+177
-0
lines changed

3 files changed

+177
-0
lines changed

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,90 @@ mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
31963196
return mlir::success();
31973197
}
31983198

3199+
static mlir::LLVM::LLVMStructType
3200+
getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter) {
3201+
// Create the landing pad type: struct { ptr, i32 }
3202+
mlir::MLIRContext *ctx = rewriter.getContext();
3203+
auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3204+
llvm::SmallVector<mlir::Type> structFields = {llvmPtr, rewriter.getI32Type()};
3205+
return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3206+
}
3207+
3208+
mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3209+
cir::EhInflightOp op, OpAdaptor adaptor,
3210+
mlir::ConversionPatternRewriter &rewriter) const {
3211+
auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3212+
assert(llvmFn && "expected LLVM function parent");
3213+
mlir::Block *entryBlock = &llvmFn.getRegion().front();
3214+
assert(entryBlock->isEntryBlock());
3215+
3216+
mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3217+
mlir::SmallVector<mlir::Value> catchSymAddrs;
3218+
3219+
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3220+
mlir::Location loc = op.getLoc();
3221+
3222+
// %landingpad = landingpad { ptr, i32 }
3223+
// Note that since llvm.landingpad has to be the first operation on the
3224+
// block, any needed value for its operands has to be added somewhere else.
3225+
if (catchListAttr) {
3226+
// catch ptr @_ZTIi
3227+
// catch ptr @_ZTIPKc
3228+
for (mlir::Attribute catchAttr : catchListAttr) {
3229+
auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3230+
// Generate `llvm.mlir.addressof` for each symbol, and place those
3231+
// operations in the LLVM function entry basic block.
3232+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3233+
rewriter.setInsertionPointToStart(entryBlock);
3234+
mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3235+
rewriter, loc, llvmPtrTy, symAttr.getValue());
3236+
catchSymAddrs.push_back(addrOp);
3237+
}
3238+
} else if (!op.getCleanup()) {
3239+
// We need to emit catch-all only if cleanup is not set, because when we
3240+
// have catch-all handler, there is no case when we set would unwind past
3241+
// the handler
3242+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3243+
rewriter.setInsertionPointToStart(entryBlock);
3244+
mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3245+
catchSymAddrs.push_back(nullOp);
3246+
}
3247+
3248+
// %slot = extractvalue { ptr, i32 } %x, 0
3249+
// %selector = extractvalue { ptr, i32 } %x, 1
3250+
mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3251+
getLLVMLandingPadStructTy(rewriter);
3252+
auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3253+
rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3254+
3255+
if (op.getCleanup())
3256+
landingPadOp.setCleanup(true);
3257+
3258+
mlir::Value slot =
3259+
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3260+
mlir::Value selector =
3261+
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3262+
rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3263+
3264+
// Landing pads are required to be in LLVM functions with personality
3265+
// attribute.
3266+
// TODO(cir): for now hardcode personality creation in order to start
3267+
// adding exception tests, once we annotate CIR with such information,
3268+
// change it to be in FuncOp lowering instead.
3269+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3270+
// Insert personality decl before the current function.
3271+
rewriter.setInsertionPoint(llvmFn);
3272+
auto personalityFnTy =
3273+
mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
3274+
/*isVarArg=*/true);
3275+
3276+
const StringRef fnName = "__gxx_personality_v0";
3277+
createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy);
3278+
llvmFn.setPersonality(fnName);
3279+
3280+
return mlir::success();
3281+
}
3282+
31993283
mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
32003284
cir::TrapOp op, OpAdaptor adaptor,
32013285
mlir::ConversionPatternRewriter &rewriter) const {

clang/test/CIR/IR/eh-inflight.cir

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
2+
3+
!u8i = !cir.int<u, 8>
4+
5+
module {
6+
7+
cir.func dso_local @inflight_exception() {
8+
%exception_ptr, %type_id = cir.eh.inflight_exception
9+
cir.return
10+
}
11+
12+
// CHECK: cir.func dso_local @inflight_exception() {
13+
// CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception
14+
// CHECK: cir.return
15+
// CHECK: }
16+
17+
cir.func dso_local @inflight_exception_with_cleanup() {
18+
%exception_ptr, %type_id = cir.eh.inflight_exception cleanup
19+
cir.return
20+
}
21+
22+
// CHECK: cir.func dso_local @inflight_exception_with_cleanup() {
23+
// CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception cleanup
24+
// CHECK: cir.return
25+
// CHECK: }
26+
27+
cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i>
28+
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>
29+
30+
cir.func dso_local @inflight_exception_with_catch_type_list() {
31+
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
32+
cir.return
33+
}
34+
35+
// CHECK: cir.func dso_local @inflight_exception_with_catch_type_list() {
36+
// CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
37+
// CHECK: cir.return
38+
// CHECK:}
39+
40+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: cir-opt %s -cir-to-llvm -o %t.cir
2+
3+
!u8i = !cir.int<u, 8>
4+
5+
module {
6+
7+
// CHECK: llvm.func @__gxx_personality_v0(...) -> i32
8+
9+
cir.func @inflight_exception() {
10+
%exception_ptr, %type_id = cir.eh.inflight_exception
11+
cir.return
12+
}
13+
14+
// CHECK: llvm.func @inflight_exception() attributes {personality = @__gxx_personality_v0} {
15+
// CHECK: %[[CONST_0:.*]] = llvm.mlir.zero : !llvm.ptr
16+
// CHECK: %[[LP:.*]] = llvm.landingpad (catch %[[CONST_0]] : !llvm.ptr) : !llvm.struct<(ptr, i32)>
17+
// CHECK: %[[EXCEPTION_PTR:.*]] = llvm.extractvalue %[[LP]][0] : !llvm.struct<(ptr, i32)>
18+
// CHECK: %[[TYPE_ID:.*]] = llvm.extractvalue %[[LP]][1] : !llvm.struct<(ptr, i32)>
19+
// CHECK: llvm.return
20+
// CHECK: }
21+
22+
cir.func @inflight_exception_with_cleanup() {
23+
%exception_ptr, %type_id = cir.eh.inflight_exception cleanup
24+
cir.return
25+
}
26+
27+
// CHECK: llvm.func @inflight_exception_with_cleanup() attributes {personality = @__gxx_personality_v0} {
28+
// CHECK: %[[LP:.*]] = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)>
29+
// CHECK: %[[EXCEPTION_PTR:.*]] = llvm.extractvalue %[[LP]][0] : !llvm.struct<(ptr, i32)>
30+
// CHECK: %[[TYPE_ID:.*]] = llvm.extractvalue %[[LP]][1] : !llvm.struct<(ptr, i32)>
31+
// CHECK: llvm.return
32+
// CHECK: }
33+
34+
35+
cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i>
36+
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>
37+
38+
cir.func @inflight_exception_with_catch_type_list() {
39+
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
40+
cir.return
41+
}
42+
43+
// CHECK: llvm.func @inflight_exception_with_catch_type_list() attributes {personality = @__gxx_personality_v0} {
44+
// CHECK: %[[TI_1_ADDR:.*]] = llvm.mlir.addressof @_ZTIPKc : !llvm.ptr
45+
// CHECK: %[[TI_2_ADDR:.*]] = llvm.mlir.addressof @_ZTIi : !llvm.ptr
46+
// CHECK: %[[LP:.*]] = llvm.landingpad (catch %[[TI_2_ADDR]] : !llvm.ptr) (catch %[[TI_1_ADDR]] : !llvm.ptr) : !llvm.struct<(ptr, i32)>
47+
// CHECK: %[[EXCEPTION_PTR:.*]] = llvm.extractvalue %[[LP]][0] : !llvm.struct<(ptr, i32)>
48+
// CHECK: %[[TYPE_ID:.*]] = llvm.extractvalue %[[LP]][1] : !llvm.struct<(ptr, i32)>
49+
// CHECK: llvm.return
50+
// CHECK: }
51+
52+
53+
}

0 commit comments

Comments
 (0)