-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CIR] Upstream Exception EhInflight op #165621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3065,6 +3065,90 @@ mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite( | |
| return mlir::success(); | ||
| } | ||
|
|
||
| static mlir::LLVM::LLVMStructType | ||
| getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter) { | ||
| // Create the landing pad type: struct { ptr, i32 } | ||
| mlir::MLIRContext *ctx = rewriter.getContext(); | ||
| auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx); | ||
| llvm::SmallVector<mlir::Type> structFields = {llvmPtr, rewriter.getI32Type()}; | ||
| return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields); | ||
| } | ||
|
|
||
| mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite( | ||
AmrDeveloper marked this conversation as resolved.
Show resolved
Hide resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need a CIR -> LLVM test here |
||
| cir::EhInflightOp op, OpAdaptor adaptor, | ||
| mlir::ConversionPatternRewriter &rewriter) const { | ||
| auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>(); | ||
| assert(llvmFn && "expected LLVM function parent"); | ||
| mlir::Block *entryBlock = &llvmFn.getRegion().front(); | ||
| assert(entryBlock->isEntryBlock()); | ||
|
|
||
| mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr(); | ||
| mlir::SmallVector<mlir::Value> catchSymAddrs; | ||
|
|
||
| auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); | ||
| mlir::Location loc = op.getLoc(); | ||
|
|
||
| // %landingpad = landingpad { ptr, i32 } | ||
| // Note that since llvm.landingpad has to be the first operation on the | ||
| // block, any needed value for its operands has to be added somewhere else. | ||
| if (catchListAttr) { | ||
| // catch ptr @_ZTIi | ||
| // catch ptr @_ZTIPKc | ||
| for (mlir::Attribute catchAttr : catchListAttr) { | ||
| auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr); | ||
| // Generate `llvm.mlir.addressof` for each symbol, and place those | ||
| // operations in the LLVM function entry basic block. | ||
| mlir::OpBuilder::InsertionGuard guard(rewriter); | ||
| rewriter.setInsertionPointToStart(entryBlock); | ||
| mlir::Value addrOp = mlir::LLVM::AddressOfOp::create( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems a bit strange that the LLVM landingpad op doesn't take flat symbol references. Won't this always be a global object?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if it takes ValueRange to be able to represent a null value 🤔 |
||
| rewriter, loc, llvmPtrTy, symAttr.getValue()); | ||
| catchSymAddrs.push_back(addrOp); | ||
| } | ||
| } else if (!op.getCleanup()) { | ||
AmrDeveloper marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // We need to emit catch-all only if cleanup is not set, because when we | ||
| // have catch-all handler, there is no case when we set would unwind past | ||
| // the handler | ||
| mlir::OpBuilder::InsertionGuard guard(rewriter); | ||
| rewriter.setInsertionPointToStart(entryBlock); | ||
| mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy); | ||
| catchSymAddrs.push_back(nullOp); | ||
| } | ||
|
|
||
| // %slot = extractvalue { ptr, i32 } %x, 0 | ||
| // %selector = extractvalue { ptr, i32 } %x, 1 | ||
| mlir::LLVM::LLVMStructType llvmLandingPadStructTy = | ||
| getLLVMLandingPadStructTy(rewriter); | ||
| auto landingPadOp = mlir::LLVM::LandingpadOp::create( | ||
| rewriter, loc, llvmLandingPadStructTy, catchSymAddrs); | ||
|
|
||
| if (op.getCleanup()) | ||
| landingPadOp.setCleanup(true); | ||
|
|
||
| mlir::Value slot = | ||
| mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0); | ||
| mlir::Value selector = | ||
| mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1); | ||
| rewriter.replaceOp(op, mlir::ValueRange{slot, selector}); | ||
|
|
||
| // Landing pads are required to be in LLVM functions with personality | ||
| // attribute. | ||
| // TODO(cir): for now hardcode personality creation in order to start | ||
| // adding exception tests, once we annotate CIR with such information, | ||
| // change it to be in FuncOp lowering instead. | ||
| mlir::OpBuilder::InsertionGuard guard(rewriter); | ||
| // Insert personality decl before the current function. | ||
| rewriter.setInsertionPoint(llvmFn); | ||
| auto personalityFnTy = | ||
| mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {}, | ||
| /*isVarArg=*/true); | ||
|
|
||
| const StringRef fnName = "__gxx_personality_v0"; | ||
| createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy); | ||
| llvmFn.setPersonality(fnName); | ||
|
|
||
| return mlir::success(); | ||
| } | ||
|
|
||
| mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite( | ||
| cir::TrapOp op, OpAdaptor adaptor, | ||
| mlir::ConversionPatternRewriter &rewriter) const { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // RUN: cir-opt %s --verify-roundtrip | FileCheck %s | ||
|
|
||
| !u8i = !cir.int<u, 8> | ||
|
|
||
| module { | ||
|
|
||
| cir.func dso_local @inflight_exception() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: cir.func dso_local @inflight_exception() { | ||
| // CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception | ||
| // CHECK: cir.return | ||
| // CHECK: } | ||
|
|
||
| cir.func dso_local @inflight_exception_with_cleanup() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception cleanup | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: cir.func dso_local @inflight_exception_with_cleanup() { | ||
| // CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception cleanup | ||
| // CHECK: cir.return | ||
| // CHECK: } | ||
|
|
||
| cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i> | ||
| cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i> | ||
|
|
||
| cir.func dso_local @inflight_exception_with_catch_type_list() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc] | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: cir.func dso_local @inflight_exception_with_catch_type_list() { | ||
| // CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc] | ||
| // CHECK: cir.return | ||
| // CHECK:} | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // RUN: cir-opt %s -cir-to-llvm -o %t.cir | ||
|
|
||
| !u8i = !cir.int<u, 8> | ||
|
|
||
| module { | ||
|
|
||
| // CHECK: llvm.func @__gxx_personality_v0(...) -> i32 | ||
|
|
||
| cir.func @inflight_exception() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: llvm.func @inflight_exception() attributes {personality = @__gxx_personality_v0} { | ||
| // CHECK: %[[CONST_0:.*]] = llvm.mlir.zero : !llvm.ptr | ||
| // CHECK: %[[LP:.*]] = llvm.landingpad (catch %[[CONST_0]] : !llvm.ptr) : !llvm.struct<(ptr, i32)> | ||
| // CHECK: %[[EXCEPTION_PTR:.*]] = llvm.extractvalue %[[LP]][0] : !llvm.struct<(ptr, i32)> | ||
| // CHECK: %[[TYPE_ID:.*]] = llvm.extractvalue %[[LP]][1] : !llvm.struct<(ptr, i32)> | ||
| // CHECK: llvm.return | ||
| // CHECK: } | ||
|
|
||
| cir.func @inflight_exception_with_cleanup() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception cleanup | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: llvm.func @inflight_exception_with_cleanup() attributes {personality = @__gxx_personality_v0} { | ||
| // CHECK: %[[LP:.*]] = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> | ||
| // CHECK: %[[EXCEPTION_PTR:.*]] = llvm.extractvalue %[[LP]][0] : !llvm.struct<(ptr, i32)> | ||
| // CHECK: %[[TYPE_ID:.*]] = llvm.extractvalue %[[LP]][1] : !llvm.struct<(ptr, i32)> | ||
| // CHECK: llvm.return | ||
| // CHECK: } | ||
|
|
||
|
|
||
| cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i> | ||
| cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i> | ||
|
|
||
| cir.func @inflight_exception_with_catch_type_list() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc] | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: llvm.func @inflight_exception_with_catch_type_list() attributes {personality = @__gxx_personality_v0} { | ||
| // CHECK: %[[TI_1_ADDR:.*]] = llvm.mlir.addressof @_ZTIPKc : !llvm.ptr | ||
| // CHECK: %[[TI_2_ADDR:.*]] = llvm.mlir.addressof @_ZTIi : !llvm.ptr | ||
| // CHECK: %[[LP:.*]] = llvm.landingpad (catch %[[TI_2_ADDR]] : !llvm.ptr) (catch %[[TI_1_ADDR]] : !llvm.ptr) : !llvm.struct<(ptr, i32)> | ||
| // CHECK: %[[EXCEPTION_PTR:.*]] = llvm.extractvalue %[[LP]][0] : !llvm.struct<(ptr, i32)> | ||
| // CHECK: %[[TYPE_ID:.*]] = llvm.extractvalue %[[LP]][1] : !llvm.struct<(ptr, i32)> | ||
| // CHECK: llvm.return | ||
| // CHECK: } | ||
|
|
||
|
|
||
| } |
Uh oh!
There was an error while loading. Please reload this page.