-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[CIR] Upstream TryCallOp #165303
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?
[CIR] Upstream TryCallOp #165303
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 |
|---|---|---|
|
|
@@ -2580,7 +2580,7 @@ def CIR_FuncOp : CIR_Op<"func", [ | |
| } | ||
|
|
||
| //===----------------------------------------------------------------------===// | ||
| // CallOp | ||
| // CallOp and TryCallOp | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| def CIR_SideEffect : CIR_I32EnumAttr< | ||
|
|
@@ -2707,6 +2707,98 @@ def CIR_CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { | |
| ]; | ||
| } | ||
|
|
||
| def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ | ||
| DeclareOpInterfaceMethods<BranchOpInterface>, | ||
| Terminator, AttrSizedOperandSegments | ||
| ]> { | ||
| let summary = "try_call operation"; | ||
|
|
||
| let description = [{ | ||
| Mostly similar to cir.call but requires two destination | ||
|
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. The description should mention that this operation is only used after the CFG flattening pass. (That's true, right?) Perhaps describe how a call in a try-block is represented in the initial CIR generated, and then describe how and why it becomes a try_call. |
||
| branches, one for handling exceptions in case its thrown and | ||
| the other one to follow on regular control-flow. | ||
|
|
||
| Example: | ||
|
|
||
| ```mlir | ||
| // Direct call | ||
| %result = cir.try_call @division(%a, %b) ^continue, ^landing_pad | ||
| : (f32, f32) -> f32 | ||
| ``` | ||
| }]; | ||
|
|
||
| let arguments = !con((ins | ||
| Variadic<CIR_AnyType>:$contOperands, | ||
| Variadic<CIR_AnyType>:$landingPadOperands | ||
|
Comment on lines
+2731
to
+2732
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. What are these arguments? Are they operands that are passed to the continue and landing pad blocks or are they the continue and landing pad blocks themselves? If the latter, I don't understand why they are variadic and any type. If the former, are they even used? |
||
| ), commonArgs); | ||
|
|
||
| let results = (outs Optional<CIR_AnyType>:$result); | ||
| let successors = (successor AnySuccessor:$cont, AnySuccessor:$landing_pad); | ||
|
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. The destinations are referred to as the normal destination and the unwind destination in the LLVM invoke instruction. I think it would be helpful to use the same terminology here. |
||
|
|
||
| let skipDefaultBuilders = 1; | ||
|
|
||
| let builders = [ | ||
| OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType, | ||
| "mlir::Block *":$cont, "mlir::Block *":$landing_pad, | ||
| CArg<"mlir::ValueRange", "{}">:$operands, | ||
| CArg<"mlir::ValueRange", "{}">:$contOperands, | ||
| CArg<"mlir::ValueRange", "{}">:$landingPadOperands, | ||
| CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ | ||
| $_state.addOperands(operands); | ||
| if (callee) | ||
| $_state.addAttribute("callee", callee); | ||
| if (resType && !isa<VoidType>(resType)) | ||
| $_state.addTypes(resType); | ||
|
|
||
| $_state.addAttribute("side_effect", | ||
| SideEffectAttr::get($_builder.getContext(), sideEffect)); | ||
|
|
||
| // Handle branches | ||
| $_state.addOperands(contOperands); | ||
| $_state.addOperands(landingPadOperands); | ||
| // The TryCall ODS layout is: cont, landing_pad, operands. | ||
| llvm::copy(::llvm::ArrayRef<int32_t>({ | ||
| static_cast<int32_t>(contOperands.size()), | ||
| static_cast<int32_t>(landingPadOperands.size()), | ||
| static_cast<int32_t>(operands.size()) | ||
| }), | ||
| odsState.getOrAddProperties<Properties>().operandSegmentSizes.begin()); | ||
| $_state.addSuccessors(cont); | ||
| $_state.addSuccessors(landing_pad); | ||
| }]>, | ||
| OpBuilder<(ins "mlir::Value":$ind_target, | ||
| "FuncType":$fn_type, | ||
| "mlir::Block *":$cont, "mlir::Block *":$landing_pad, | ||
| CArg<"mlir::ValueRange", "{}">:$operands, | ||
| CArg<"mlir::ValueRange", "{}">:$contOperands, | ||
| CArg<"mlir::ValueRange", "{}">:$landingPadOperands, | ||
| CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ | ||
| ::llvm::SmallVector<mlir::Value, 4> finalCallOperands({ind_target}); | ||
| finalCallOperands.append(operands.begin(), operands.end()); | ||
| $_state.addOperands(finalCallOperands); | ||
|
|
||
| if (!fn_type.hasVoidReturn()) | ||
| $_state.addTypes(fn_type.getReturnType()); | ||
|
|
||
| $_state.addAttribute("side_effect", | ||
| SideEffectAttr::get($_builder.getContext(), sideEffect)); | ||
|
|
||
| // Handle branches | ||
| $_state.addOperands(contOperands); | ||
| $_state.addOperands(landingPadOperands); | ||
| // The TryCall ODS layout is: cont, landing_pad, operands. | ||
| llvm::copy(::llvm::ArrayRef<int32_t>({ | ||
| static_cast<int32_t>(contOperands.size()), | ||
| static_cast<int32_t>(landingPadOperands.size()), | ||
| static_cast<int32_t>(finalCallOperands.size()) | ||
| }), | ||
| odsState.getOrAddProperties<Properties>().operandSegmentSizes.begin()); | ||
| $_state.addSuccessors(cont); | ||
| $_state.addSuccessors(landing_pad); | ||
| }]> | ||
| ]; | ||
| } | ||
|
|
||
| //===----------------------------------------------------------------------===// | ||
| // CopyOp | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
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.
This should probably have a verifier. The two destinations need to be valid blocks in the same region as the caller, and the landing pad destination needs to be a landing pad (though I'm not sure exactly how to verify that and it probably can't be done yet).