-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[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
base: main
Are you sure you want to change the base?
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 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4490,6 +4490,35 @@ def CIR_TryOp : CIR_Op<"try",[ | |||||||||||
| let hasLLVMLowering = false; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| //===----------------------------------------------------------------------===// | ||||||||||||
| // Exception related: EhInflightOp | ||||||||||||
| //===----------------------------------------------------------------------===// | ||||||||||||
|
|
||||||||||||
| def CIR_EhInflightOp : CIR_Op<"eh.inflight_exception"> { | ||||||||||||
| let summary = "Materialize the catch clause formal parameter"; | ||||||||||||
| let description = [{ | ||||||||||||
| `cir.eh.inflight_exception` returns two values: | ||||||||||||
| - `exception_ptr`: The exception pointer for the inflight exception | ||||||||||||
| - `type_id`: pointer to the exception object | ||||||||||||
| This operation is expected to be the first one basic blocks on the | ||||||||||||
| exception path out of `cir.try_call` operations. | ||||||||||||
|
Comment on lines
+4503
to
+4504
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.
Suggested change
|
||||||||||||
|
|
||||||||||||
| The `cleanup` attribute indicates that clean up code might run before the | ||||||||||||
| values produced by this operation are used to gather exception information. | ||||||||||||
|
Comment on lines
+4506
to
+4507
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.
Suggested change
|
||||||||||||
| This helps CIR to pass down more accurate information for LLVM lowering | ||||||||||||
| to landingpads. | ||||||||||||
| }]; | ||||||||||||
|
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. Add examples of operation. |
||||||||||||
|
|
||||||||||||
| let arguments = (ins UnitAttr:$cleanup, | ||||||||||||
| OptionalAttr<FlatSymbolRefArrayAttr>:$sym_type_list); | ||||||||||||
|
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.
Suggested change
|
||||||||||||
| let results = (outs CIR_VoidPtrType:$exception_ptr, CIR_UInt32:$type_id); | ||||||||||||
| let assemblyFormat = [{ | ||||||||||||
| (`cleanup` $cleanup^)? | ||||||||||||
| ($sym_type_list^)? | ||||||||||||
| attr-dict | ||||||||||||
| }]; | ||||||||||||
|
Comment on lines
+4515
to
+4519
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. Add tests covering presence of cleanup and sym_type_list |
||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| //===----------------------------------------------------------------------===// | ||||||||||||
| // Atomic operations | ||||||||||||
| //===----------------------------------------------------------------------===// | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3002,6 +3002,88 @@ 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( | ||
|
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. Again, either defer the lowering to a future PR or add a test.
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 symListAttr = op.getSymTypeListAttr(); | ||
| mlir::SmallVector<mlir::Value, 4> symAddrs; | ||
|
|
||
| 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 (symListAttr) { | ||
| // catch ptr @_ZTIi | ||
| // catch ptr @_ZTIPKc | ||
| for (mlir::Attribute attr : symListAttr) { | ||
| auto symAttr = cast<mlir::FlatSymbolRefAttr>(attr); | ||
| // 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? |
||
| rewriter, loc, llvmPtrTy, symAttr.getValue()); | ||
| symAddrs.push_back(addrOp); | ||
| } | ||
| } else if (!op.getCleanup()) { | ||
|
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 would be useful to have a comment here explaining why we will never need to emit the catch-all handler if |
||
| // catch ptr null | ||
| mlir::OpBuilder::InsertionGuard guard(rewriter); | ||
| rewriter.setInsertionPointToStart(entryBlock); | ||
| mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy); | ||
| symAddrs.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, symAddrs); | ||
|
|
||
| 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); | ||
| // Get or create `__gxx_personality_v0` | ||
| 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,15 @@ | ||
| // RUN: cir-opt %s --verify-roundtrip | FileCheck %s | ||
|
|
||
| module { | ||
|
|
||
| cir.func dso_local @function_with_inflight_exception() { | ||
| %exception_ptr, %type_id = cir.eh.inflight_exception | ||
| cir.return | ||
| } | ||
|
|
||
| // CHECK: cir.func dso_local @function_with_inflight_exception() { | ||
| // CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception | ||
| // CHECK: cir.return | ||
| // CHECK: } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.