19 llvm::df_iterator_default_set<mlir::Block *, 16> reachable;
20 parent->walk([&](mlir::Region *region) {
23 if (region->empty() || region->hasOneBlock())
35 for (mlir::Block *blk : llvm::depth_first_ext(®ion->front(), reachable))
39 for (mlir::Block &blk : *region) {
40 if (reachable.contains(&blk))
42 for (mlir::Operation &op : blk)
49 mlir::Block *unwindDest,
51 mlir::RewriterBase &rewriter) {
52 mlir::Block *callBlock = callOp->getBlock();
54 assert(!callOp.getNothrow() &&
"call is not expected to throw");
58 mlir::Block *normalDest =
59 rewriter.splitBlock(callBlock, std::next(callOp->getIterator()));
62 rewriter.setInsertionPoint(callOp);
63 cir::TryCallOp tryCallOp;
64 if (callOp.isIndirect()) {
65 mlir::Value indTarget = callOp.getIndirectCall();
66 auto ptrTy = mlir::cast<cir::PointerType>(indTarget.getType());
67 auto resTy = mlir::cast<cir::FuncType>(ptrTy.getPointee());
69 cir::TryCallOp::create(rewriter, loc, indTarget, resTy, normalDest,
70 unwindDest, callOp.getArgOperands());
72 mlir::Type resType = callOp->getNumResults() > 0
73 ? callOp->getResult(0).getType()
76 cir::TryCallOp::create(rewriter, loc, callOp.getCalleeAttr(), resType,
77 normalDest, unwindDest, callOp.getArgOperands());
82 llvm::StringRef excludedAttrs[] = {
83 cir::CIRDialect::getCalleeAttrName(),
84 cir::CIRDialect::getOperandSegmentSizesAttrName(),
86 for (mlir::NamedAttribute attr : callOp->getAttrs()) {
87 if (llvm::is_contained(excludedAttrs, attr.getName()))
89 assert(!llvm::is_contained(
91 cir::CIRDialect::getNoThrowAttrName(),
92 cir::CIRDialect::getNoUnwindAttrName(),
95 "unexpected attribute on converted call");
96 tryCallOp->setAttr(attr.getName(), attr.getValue());
102 if (callOp->getNumResults() > 0)
103 rewriter.replaceAllUsesWith(callOp->getResult(0), tryCallOp.getResult());
105 rewriter.eraseOp(callOp);
110 mlir::Block *unwindDest,
112 mlir::RewriterBase &rewriter) {
117 auto funcOp = throwOp->getParentOfType<cir::FuncOp>();
118 assert(funcOp &&
"throw must be inside a function");
119 mlir::Region &body = funcOp.getBody();
121 mlir::Block *normalDest;
123 mlir::OpBuilder::InsertionGuard guard(rewriter);
124 normalDest = rewriter.createBlock(&body, body.end());
125 cir::UnreachableOp::create(rewriter, loc);
129 rewriter.setInsertionPoint(throwOp);
130 auto tryThrowOp = cir::TryThrowOp::create(
131 rewriter, loc, throwOp.getExceptionPtr(), throwOp.getTypeInfoAttr(),
132 throwOp.getDtorAttr(), normalDest, unwindDest);
136 llvm::StringRef excludedAttrs[] = {
140 for (mlir::NamedAttribute attr : throwOp->getAttrs()) {
141 if (llvm::is_contained(excludedAttrs, attr.getName()))
143 tryThrowOp->setAttr(attr.getName(), attr.getValue());
150 mlir::Block *throwBlock = throwOp->getBlock();
151 while (&throwBlock->back() != tryThrowOp)
152 rewriter.eraseOp(&throwBlock->back());
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
mlir::Block * replaceThrowWithTryThrow(cir::ThrowOp throwOp, mlir::Block *unwindDest, mlir::Location loc, mlir::RewriterBase &rewriter)
Replace a cir::ThrowOp with a cir::TryThrowOp whose unwind destination is unwindDest.
mlir::Block * replaceCallWithTryCall(cir::CallOp callOp, mlir::Block *unwindDest, mlir::Location loc, mlir::RewriterBase &rewriter)
Replace a cir::CallOp with a cir::TryCallOp whose unwind destination is unwindDest.