Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,32 @@ def CIR_AnyIntOrFloatAttr : AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyFPAttr],
string cppType = "::mlir::TypedAttr";
}

//===----------------------------------------------------------------------===//
// Exceptions constraints
//===----------------------------------------------------------------------===//

def CIR_AnyCatchAllAttr
: CIR_AttrConstraint<"::cir::CatchAllAttr", "catch all attribute">;

def CIR_AnyUnwindAttr
: CIR_AttrConstraint<"::cir::UnwindAttr", "unwind attribute">;

//===----------------------------------------------------------------------===//
// GlobalViewAttr constraints
//===----------------------------------------------------------------------===//

def CIR_AnyGlobalViewAttr : CIR_AttrConstraint<"::cir::GlobalViewAttr", "GlobalView attribute">;
def CIR_AnyGlobalViewAttr
: CIR_AttrConstraint<"::cir::GlobalViewAttr", "GlobalView attribute">;

def CIR_AnyIntOrGlobalViewAttr : AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyGlobalViewAttr],
"integer or global view attribute"> {
def CIR_AnyIntOrGlobalViewAttr
: AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyGlobalViewAttr],
"integer or global view attribute"> {
string cppType = "::mlir::TypedAttr";
}

def CIR_AnyGlobalViewOrCatchAllOrUnwindAttr
: AnyAttrOf<[CIR_AnyGlobalViewAttr, CIR_AnyCatchAllAttr, CIR_AnyUnwindAttr],
"catch all or unwind or global view attribute"> {
string cppType = "::mlir::TypedAttr";
}

Expand All @@ -61,4 +79,8 @@ def CIR_IntOrGlobalViewArrayAttr : TypedArrayAttrBase<CIR_AnyIntOrGlobalViewAttr
string cppType = "::mlir::ArrayAttr";
}

#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
def CIR_GlobalViewOrCatchAllOrUnwindArrayAttr
: TypedArrayAttrBase<CIR_AnyGlobalViewOrCatchAllOrUnwindAttr,
"catch all or unwind or global view array attribute">;

#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
15 changes: 15 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -960,4 +960,19 @@ def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
}];
}

//===----------------------------------------------------------------------===//
// CatchAllAttr & UnwindAttr
//===----------------------------------------------------------------------===//

// Represents the catch_all region.
def CIR_CatchAllAttr : CIR_UnitAttr<"CatchAll", "all"> {
let storageType = [{ CatchAllAttr }];
}

// Represents the unwind region where unwind continues or
// the program std::terminate's.
def CIR_UnwindAttr : CIR_UnitAttr<"Unwind", "unwind"> {
let storageType = [{ CatchUnwind }];
}

#endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD
86 changes: 84 additions & 2 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ def CIR_StoreOp : CIR_Op<"store", [

defvar CIR_ReturnableScopes = [
"FuncOp", "ScopeOp", "IfOp", "SwitchOp", "CaseOp",
"DoWhileOp", "WhileOp", "ForOp"
"DoWhileOp", "WhileOp", "ForOp", "TryOp"
];

def CIR_ReturnOp : CIR_Op<"return", [
Expand Down Expand Up @@ -778,7 +778,7 @@ def CIR_ConditionOp : CIR_Op<"condition", [

defvar CIR_YieldableScopes = [
"ArrayCtor", "ArrayDtor", "CaseOp", "DoWhileOp", "ForOp", "GlobalOp", "IfOp",
"ScopeOp", "SwitchOp", "TernaryOp", "WhileOp"
"ScopeOp", "SwitchOp", "TernaryOp", "WhileOp", "TryOp"
];

def CIR_YieldOp : CIR_Op<"yield", [
Expand Down Expand Up @@ -4296,6 +4296,88 @@ def CIR_AllocExceptionOp : CIR_Op<"alloc.exception"> {
}];
}

//===----------------------------------------------------------------------===//
// TryOp
//===----------------------------------------------------------------------===//

def CIR_TryOp : CIR_Op<"try",[
DeclareOpInterfaceMethods<RegionBranchOpInterface>,
RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments
]> {
let summary = "C++ try block";
let description = [{
Holds the lexical scope of `try {}`. Note that resources used on catch
clauses are usually allocated in the same parent as `cir.try`.

`synthetic`: use `cir.try` to represent try/catches not originally
present in the source code. For example, a synthetic `cir.try` region
is created around the constructor call when `operator new` is used
so that the memory allocated will be freed if the constructor throws
an exception.

`cleanup`: indicates that there are cleanups that must be performed
when exiting the try region via exception, even if the exception is not
caught.

Example:

```mlir
cir.try {
cir.call exception @function() : () -> ()
cir.yield
} catch [type #cir.global_view<@_ZTIPf> : !cir.ptr<!u8i>] {
...
cir.yield
} unwind {
cir.resume
}
```
}];

let arguments = (ins
UnitAttr:$synthetic,
UnitAttr:$cleanup,
CIR_GlobalViewOrCatchAllOrUnwindArrayAttr:$catch_types
);

let regions = (region
AnyRegion:$try_region,
VariadicRegion<MinSizedRegion<1>>:$catch_regions
);

let assemblyFormat = [{
(`synthetic` $synthetic^)?
(`cleanup` $cleanup^)?
$try_region
custom<CatchRegions>($catch_regions, $catch_types)
attr-dict
}];

let builders = [
OpBuilder<(ins
"llvm::function_ref<void(mlir::OpBuilder &, "
"mlir::Location)>":$tryBuilder,
"llvm::function_ref<void(mlir::OpBuilder &, mlir::Location, "
"mlir::OperationState &)>":$catchBuilder),
[{
assert(tryBuilder && "expected builder callback for 'cir.try' body");
assert(catchBuilder && "expected builder callback for 'catch' body");

OpBuilder::InsertionGuard guard($_builder);

// Try body region
mlir::Region *tryBodyRegion = $_state.addRegion();

// Create try body region and set insertion point
$_builder.createBlock(tryBodyRegion);
tryBuilder($_builder, $_state.location);
catchBuilder($_builder, $_state.location, $_state);
}]>
];

let hasLLVMLowering = false;
}

//===----------------------------------------------------------------------===//
// Atomic operations
//===----------------------------------------------------------------------===//
Expand Down
118 changes: 118 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2878,6 +2878,124 @@ LogicalResult cir::TypeInfoAttr::verify(
return success();
}

//===----------------------------------------------------------------------===//
// TryOp
//===----------------------------------------------------------------------===//

void cir::TryOp::getSuccessorRegions(
mlir::RegionBranchPoint point,
llvm::SmallVectorImpl<mlir::RegionSuccessor> &regions) {
// The `try` and the `catchers` region branch back to the parent operation.
if (!point.isParent()) {
regions.push_back(mlir::RegionSuccessor());
return;
}

regions.push_back(mlir::RegionSuccessor(&getTryRegion()));

// TODO(CIR): If we know a target function never throws a specific type, we
// can remove the catch handler.
for (mlir::Region &region : this->getCatchRegions())
regions.push_back(mlir::RegionSuccessor(&region));
}

static void printCatchRegions(mlir::OpAsmPrinter &printer, cir::TryOp op,
mlir::MutableArrayRef<mlir::Region> regions,
mlir::ArrayAttr catchersAttr) {
if (!catchersAttr)
return;

for (const auto [catcherIdx, catcherAttr] : llvm::enumerate(catchersAttr)) {
if (catcherIdx)
printer << " ";

if (mlir::isa<cir::CatchAllAttr>(catcherAttr)) {
printer << "catch all ";
} else if (mlir::isa<cir::UnwindAttr>(catcherAttr)) {
printer << "unwind ";
} else {
printer << "catch [type ";
printer.printAttribute(catcherAttr);
printer << "] ";
}

printer.printRegion(regions[catcherIdx], /*printEntryBLockArgs=*/false,
/*printBlockTerminators=*/true);
}
}

static mlir::ParseResult
parseCatchRegions(mlir::OpAsmParser &parser,
llvm::SmallVectorImpl<std::unique_ptr<mlir::Region>> &regions,
mlir::ArrayAttr &catchersAttr) {

auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
regions.emplace_back(new mlir::Region);

mlir::Region &currRegion = *regions.back();
mlir::SMLoc regionLoc = parser.getCurrentLocation();
if (parser.parseRegion(currRegion)) {
regions.clear();
return failure();
}

if (!currRegion.empty() && !(currRegion.back().mightHaveTerminator() &&
currRegion.back().getTerminator()))
return parser.emitError(
regionLoc, "blocks are expected to be explicitly terminated");

return success();
};

bool hasCatchAll = false;
llvm::SmallVector<mlir::Attribute, 4> catcherAttrs;
while (parser.parseOptionalKeyword("catch").succeeded()) {
bool hasLSquare = parser.parseOptionalLSquare().succeeded();

llvm::StringRef attrStr;
if (parser.parseOptionalKeyword(&attrStr, {"all", "type"}).failed())
return parser.emitError(parser.getCurrentLocation(),
"expected 'all' or 'type' keyword");

bool isCatchAll = attrStr == "all";
if (isCatchAll) {
if (hasCatchAll)
return parser.emitError(parser.getCurrentLocation(),
"can't have more than one catch all");
hasCatchAll = true;
}

mlir::Attribute exceptionRTTIAttr;
if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
return parser.emitError(parser.getCurrentLocation(),
"expected valid RTTI info attribute");

catcherAttrs.push_back(isCatchAll
? cir::CatchAllAttr::get(parser.getContext())
: exceptionRTTIAttr);

if (hasLSquare && isCatchAll)
return parser.emitError(parser.getCurrentLocation(),
"catch all dosen't need RTTI info attribute");

if (hasLSquare && parser.parseRSquare().failed())
return parser.emitError(parser.getCurrentLocation(),
"expected `]` after RTTI info attribute");

if (parseCheckedCatcherRegion().failed())
return mlir::failure();
}

if (parser.parseOptionalKeyword("unwind").succeeded()) {
catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
if (parseCheckedCatcherRegion().failed())
return mlir::failure();
}

catchersAttr = parser.getBuilder().getArrayAttr(catcherAttrs);
return mlir::success();
}

//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
Expand Down
Loading