Skip to content

Commit 7ff2a25

Browse files
bcardosolopeslanza
authored andcommitted
[CIR][CIRGen][NFC] Exceptions: add cleanups to cir.call
Now that the basic is working, start adding cleanups to be attached to cir.call's instead. This is necessary in order to tie the pieces (landing pads and cleanups) more properly, allowing multiple calls inside cir.try op to be connected with the right cleanup. This is the first piece of a series, tests coming next.
1 parent 3f46baa commit 7ff2a25

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3226,7 +3226,7 @@ class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []> :
32263226
);
32273227
}
32283228

3229-
def CallOp : CIR_CallOp<"call"> {
3229+
def CallOp : CIR_CallOp<"call", [NoRegionArguments]> {
32303230
let summary = "call operation";
32313231
let description = [{
32323232
Direct and indirect calls.
@@ -3241,7 +3241,9 @@ def CallOp : CIR_CallOp<"call"> {
32413241
Given the way indirect calls are encoded, avoid using `mlir::Operation`
32423242
methods to walk the operands for this operation, instead use the methods
32433243
provided by `CIRCallOpInterface`.
3244-
``
3244+
3245+
If the `cir.call` has the `exception` keyword, the call can throw. In this
3246+
case, cleanups can be added in the `cleanup` region.
32453247

32463248
Example:
32473249

@@ -3251,13 +3253,19 @@ def CallOp : CIR_CallOp<"call"> {
32513253
...
32523254
// Indirect call
32533255
%20 = cir.call %18(%17)
3256+
...
3257+
// Call that might throw
3258+
cir.call exception @my_div() -> () cleanup {
3259+
// call dtor...
3260+
}
32543261
```
32553262
}];
32563263

32573264
let results = (outs Optional<CIR_AnyType>:$result);
32583265
let arguments = !con((ins
32593266
UnitAttr:$exception
32603267
), commonArgs);
3268+
let regions = (region AnyRegion:$cleanup);
32613269

32623270
let skipDefaultBuilders = 1;
32633271

@@ -3275,6 +3283,8 @@ def CallOp : CIR_CallOp<"call"> {
32753283
$_state.addAttribute("exception", exception);
32763284
if (resType && !isa<VoidType>(resType))
32773285
$_state.addTypes(resType);
3286+
// Create region placeholder for potential cleanups.
3287+
$_state.addRegion();
32783288
}]>,
32793289
OpBuilder<(ins "Value":$ind_target,
32803290
"FuncType":$fn_type,
@@ -3289,6 +3299,8 @@ def CallOp : CIR_CallOp<"call"> {
32893299
CallingConvAttr::get($_builder.getContext(), callingConv));
32903300
if (exception)
32913301
$_state.addAttribute("exception", exception);
3302+
// Create region placeholder for potential cleanups.
3303+
$_state.addRegion();
32923304
}]>
32933305
];
32943306
}

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2822,8 +2822,11 @@ static ::mlir::ParseResult parseCallCommon(::mlir::OpAsmParser &parser,
28222822
llvm::SMLoc landingPadOperandsLoc;
28232823
llvm::SmallVector<mlir::Type, 1> landingPadTypes;
28242824

2825-
if (::mlir::succeeded(parser.parseOptionalKeyword("exception")))
2825+
bool hasExceptions = false;
2826+
if (::mlir::succeeded(parser.parseOptionalKeyword("exception"))) {
28262827
result.addAttribute("exception", parser.getBuilder().getUnitAttr());
2828+
hasExceptions = true;
2829+
}
28272830

28282831
// If we cannot parse a string callee, it means this is an indirect call.
28292832
if (!parser.parseOptionalAttribute(calleeAttr, "callee", result.attributes)
@@ -2910,6 +2913,18 @@ static ::mlir::ParseResult parseCallCommon(::mlir::OpAsmParser &parser,
29102913
builder.getContext(), callingConv));
29112914
}
29122915

2916+
// If exception is present and there are cleanups, this should be latest thing
2917+
// present (after all attributes, etc).
2918+
mlir::Region *cleanupRegion = nullptr;
2919+
if (!hasDestinationBlocks) // Regular cir.call
2920+
cleanupRegion = result.addRegion();
2921+
if (hasExceptions) {
2922+
if (parser.parseOptionalKeyword("cleanup").succeeded()) {
2923+
if (parser.parseRegion(*cleanupRegion, /*arguments=*/{}, /*argTypes=*/{}))
2924+
return failure();
2925+
}
2926+
}
2927+
29132928
return ::mlir::success();
29142929
}
29152930

@@ -2989,6 +3004,17 @@ void printCallCommon(Operation *op, mlir::Value indirectCallee,
29893004
state.printAttributeWithoutType(extraAttrs);
29903005
state << ")";
29913006
}
3007+
3008+
// If exception is present and there are cleanups, this should be latest thing
3009+
// present (after all attributes, etc).
3010+
if (exception) {
3011+
auto call = dyn_cast<mlir::cir::CallOp>(op);
3012+
assert(call && "expected regular call");
3013+
if (!call.getCleanup().empty()) {
3014+
state << "cleanup ";
3015+
state.printRegion(call.getCleanup());
3016+
}
3017+
}
29923018
}
29933019

29943020
LogicalResult

0 commit comments

Comments
 (0)