================
@@ -1068,6 +1069,112 @@ def CIR_ScopeOp : CIR_Op<"scope", [
let hasLLVMLowering = false;
}
+//===----------------------------------------------------------------------===//
+// CleanupScopeOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CleanupKind : CIR_I32EnumAttr<"CleanupKind", "cleanup kind", [
+ I32EnumAttrCase<"Normal", 1, "normal">,
+ I32EnumAttrCase<"EH", 2, "eh">,
+ I32EnumAttrCase<"All", 3, "all">
+]> {
+ let genSpecializedAttr = 0;
+}
+
+def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup_kind"> {
+ let summary = "Cleanup kind attribute";
+ let description = [{
+ Cleanup kind attributes.
+ }];
+
+ let cppClassName = "CleanupKindAttr";
+
+ let skipDefaultBuilders = 1;
+ let builders = [
+ AttrBuilder<(ins CArg<"CleanupKind",
+ "cir::CleanupKind::All">:$value), [{
+ return $_get($_ctxt, value);
+ }]>
+ ];
+
+ let assemblyFormat = [{
+ $value
+ }];
+
+ let extraClassDeclaration = [{
+ bool isNormal() const {
+ return getValue() == CleanupKind::Normal ||
+ getValue() == CleanupKind::All;
+ };
+ bool isEH() const {
+ return getValue() == CleanupKind::EH || getValue() == CleanupKind::All;
+ };
+ bool isNormalAndEH() const { return getValue() == CleanupKind::All; };
+ }];
+}
+
+def CIR_CleanupScopeOp : CIR_Op<"cleanup.scope", [
+ DeclareOpInterfaceMethods<RegionBranchOpInterface, ["getSuccessorInputs"]>,
+ RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments,
+ RecursiveMemoryEffects
+]> {
+ let summary = "Represents a scope with associated cleanup code";
+ let description = [{
+ `cir.cleanup.scope` contains a body region and a cleanup region. The body
+ region is executed first, and the cleanup region is executed when the body
+ region is exited, either normally or due to an exception.
+
+ The cleanup kind attribute specifies when the cleanup region should be
+ executed:
+ - `none`: No cleanup (cleanup region is empty/unused)
+ - `normal`: Cleanup is executed only on normal exit
+ - `eh`: Cleanup is executed only on exception unwinding
+ - `all`: Cleanup is executed on both normal exit and exception unwinding
+
+ Examples:
+
+ ```mlir
+ // Cleanup that runs on both normal and exception paths
+ cir.cleanup.scope {
+ cir.call @mayThrow() : () -> ()
+ cir.yield
+ } cleanup all {
+ cir.call @destructor() : () -> ()
+ cir.yield
+ }
+
+ // EH-only cleanup (destructor only called on exception)
+ cir.cleanup.scope {
+ cir.call @mayThrow() : () -> ()
+ cir.yield
+ } cleanup eh {
+ cir.call @destructor() : () -> ()
+ cir.yield
+ }
+ ```
+
+ Both regions must be terminated. If a region has only one block, the
+ terminator can be left out, and `cir.yield` will be inserted implicitly.
+ }];
+
+ let arguments = (ins CIR_CleanupKindAttr:$cleanupKind);
+ let regions = (region AnyRegion:$bodyRegion, AnyRegion:$cleanupRegion);
+
+ let skipDefaultBuilders = 1;
+
+ let assemblyFormat = [{
+ $bodyRegion `cleanup` $cleanupKind $cleanupRegion attr-dict
----------------
andykaylor wrote:
I see. Thanks for the clearification.
I don't really have a strong preference here. It seems to me that we've been
moving away from parentheses in the assembly format in most cases, but `}
cleanup(all) {` does make it more visible, I think.
@xlauko You've been guiding our assembly style. Do you have a preference here?
https://github.com/llvm/llvm-project/pull/178085
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits