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());
84 callOp->getName().walkInherentAttrs(
85 callOp, [&](llvm::StringRef name, mlir::Attribute &attr) {
86 if (name != cir::CIRDialect::getCalleeAttrName() &&
87 name != cir::CIRDialect::getNoThrowAttrName() &&
88 name != cir::CIRDialect::getOperandSegmentSizesAttrName())
89 tryCallOp->setInherentAttr(
90 mlir::StringAttr::get(callOp->getContext(), name), attr);
92 for (mlir::NamedAttribute attr : callOp->getDiscardableAttrs())
93 tryCallOp->setDiscardableAttr(attr.getName(), attr.getValue());
98 if (callOp->getNumResults() > 0)
99 rewriter.replaceAllUsesWith(callOp->getResult(0), tryCallOp.getResult());
101 rewriter.eraseOp(callOp);
106 mlir::Block *unwindDest,
108 mlir::RewriterBase &rewriter) {
113 auto funcOp = throwOp->getParentOfType<cir::FuncOp>();
114 assert(funcOp &&
"throw must be inside a function");
115 mlir::Region &body = funcOp.getBody();
117 mlir::Block *normalDest;
119 mlir::OpBuilder::InsertionGuard guard(rewriter);
120 normalDest = rewriter.createBlock(&body, body.end());
121 cir::UnreachableOp::create(rewriter, loc);
125 rewriter.setInsertionPoint(throwOp);
126 auto tryThrowOp = cir::TryThrowOp::create(
127 rewriter, loc, throwOp.getExceptionPtr(), throwOp.getTypeInfoAttr(),
128 throwOp.getDtorAttr(), normalDest, unwindDest);
132 for (mlir::NamedAttribute attr : throwOp->getDiscardableAttrs())
133 tryThrowOp->setDiscardableAttr(attr.getName(), attr.getValue());
139 mlir::Block *throwBlock = throwOp->getBlock();
140 while (&throwBlock->back() != tryThrowOp)
141 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.