Skip to content
Merged
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
9 changes: 6 additions & 3 deletions tslang/include/TypeScript/TypeScriptPassContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct TSContext
finallyBlockOf.beginRun();
landingBlockOf.beginRun();
leavesCatch.beginRun();
catchesLeft.beginRun();
catchPadIdOf.beginRun();
finallyPadIdOf.beginRun();
inParentTryFinallyPad.beginRun();
Expand All @@ -155,10 +156,12 @@ struct TSContext
OpSideTable<mlir::Block *> finallyBlockOf{"finallyBlockOf"};
OpSideTable<mlir::Block *> landingBlockOf{"landingBlockOf"};
// Throws that sit inside a catch clause and therefore have to end the active catch before
// they leave it. `return`, `break` and `continue` carry the same meaning in `unwind`, but
// a throw cannot: `unwind` already means its invoke destination, which is a different
// question with a different answer.
// they leave it. It cannot go in `unwind`: for a throw that already means its invoke
// destination, which is a different question with a different answer.
OpSideTable<bool> leavesCatch{"leavesCatch"};
// How many catch clauses a `return`, `break` or `continue` leaves - one end-of-catch each,
// innermost first. More than one for a jump out of a catch nested in another catch clause.
OpSideTable<int> catchesLeft{"catchesLeft"};
// Windows: the id a try's catch landing pad goes by, so that the pads of a try inside that
// catch clause can name it as the funclet they are nested in - see tagPad in TryOpLowering
// and ts.internal.eh_pad in Win32ExceptionPass. Ids are unique within the module.
Expand Down
50 changes: 24 additions & 26 deletions tslang/lib/TypeScript/LowerToAffineLoops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ struct EntryOpLowering : public TsPattern<mlir_ts::EntryOp>
}
};

// end the catch clauses a return, break or continue leaves (TSContext::catchesLeft)
static void endCatches(PatternRewriter &rewriter, Location loc, int count)
{
for (auto i = 0; i < count; i++)
{
rewriter.create<mlir_ts::EndCatchOp>(loc);
}
}

struct ExitOpLowering : public TsPattern<mlir_ts::ExitOp>
{
using TsPattern<mlir_ts::ExitOp>::TsPattern;
Expand Down Expand Up @@ -111,10 +120,7 @@ struct ReturnOpLowering : public TsPattern<mlir_ts::ReturnOp>
assert(tsContext->returnBlock);

auto retBlock = tsContext->returnBlock;
if (auto unwind = tsContext->unwind.lookup(op))
{
rewriter.create<mlir_ts::EndCatchOp>(loc);
}
endCatches(rewriter, loc, tsContext->catchesLeft.lookup(op));

auto *opBlock = rewriter.getInsertionBlock();
auto opPosition = rewriter.getInsertionPoint();
Expand Down Expand Up @@ -152,10 +158,7 @@ struct ReturnValOpLowering : public TsPattern<mlir_ts::ReturnValOp>

// save value into return
rewriter.create<mlir_ts::StoreOp>(op.getLoc(), op.getOperand(), op.getReference());
if (auto unwind = tsContext->unwind.lookup(op))
{
rewriter.create<mlir_ts::EndCatchOp>(loc);
}
endCatches(rewriter, loc, tsContext->catchesLeft.lookup(op));

// Split block at `assert` operation.
auto *opBlock = rewriter.getInsertionBlock();
Expand Down Expand Up @@ -797,10 +800,7 @@ struct BreakOpLowering : public TsPattern<mlir_ts::BreakOp>
auto jump = tsContext->jumps.lookup(breakOp);
assert(jump);

if (auto unwind = tsContext->unwind.lookup(breakOp))
{
rewriter.create<mlir_ts::EndCatchOp>(loc);
}
endCatches(rewriter, loc, tsContext->catchesLeft.lookup(breakOp));

rewriter.replaceOpWithNewOp<mlir::cf::BranchOp>(breakOp, jump);
clh.CutBlock();
Expand All @@ -823,10 +823,7 @@ struct ContinueOpLowering : public TsPattern<mlir_ts::ContinueOp>
auto jump = tsContext->jumps.lookup(continueOp);
assert(jump);

if (auto unwind = tsContext->unwind.lookup(continueOp))
{
rewriter.create<mlir_ts::EndCatchOp>(loc);
}
endCatches(rewriter, loc, tsContext->catchesLeft.lookup(continueOp));

rewriter.replaceOpWithNewOp<mlir::cf::BranchOp>(continueOp, jump);
clh.CutBlock();
Expand Down Expand Up @@ -1564,13 +1561,9 @@ struct TryOpLowering : public TsPattern<mlir_ts::TryOp>

// logic to set Invoke attribute CallOp
auto visitorReturnOpContinue = [&](Operation *op) {
if (auto returnOp = dyn_cast_or_null<mlir_ts::ReturnOp>(op))
{
tsContext->unwind[op] = catchesBlock;
}
else if (auto returnValOp = dyn_cast_or_null<mlir_ts::ReturnValOp>(op))
if (isa<mlir_ts::ReturnOp, mlir_ts::ReturnValOp>(op))
{
tsContext->unwind[op] = catchesBlock;
tsContext->catchesLeft[op] = tsContext->catchesLeft.lookup(op) + 1;
}
else if (auto throwOp = dyn_cast_or_null<mlir_ts::ThrowOp>(op))
{
Expand Down Expand Up @@ -1611,6 +1604,14 @@ struct TryOpLowering : public TsPattern<mlir_ts::TryOp>
continue;
}
} while (false);

// A break/continue out of the try leaves the catch clause just as a return does and
// owes it the same end-of-catch, finally or not. Only the escaping ones: a jump to a
// loop inside the catch clause stays in it.
for (auto op : escapingJumpsCatches)
{
tsContext->catchesLeft[op] = tsContext->catchesLeft.lookup(op) + 1;
}
}
else
{
Expand Down Expand Up @@ -1678,7 +1679,7 @@ struct TryOpLowering : public TsPattern<mlir_ts::TryOp>
// to be ended on the way out, as a catch clause's `return` ends it
for (auto op : escapingOpsFinally)
{
tsContext->unwind[finallyMapping.lookup(op)] = beforeFinallyBlock->getNextNode();
tsContext->catchesLeft[finallyMapping.lookup(op)] = tsContext->catchesLeft.lookup(op) + 1;
}

finallyBlock = beforeFinallyBlock->getNextNode();
Expand Down Expand Up @@ -1858,9 +1859,6 @@ struct TryOpLowering : public TsPattern<mlir_ts::TryOp>
for (auto op : escapingJumpsCatches)
{
routeThroughFinally(op);
// leaving a catch clause abruptly must end the active catch first,
// mirroring the return-from-catch handling
tsContext->unwind[op] = catchesBlock;
}
}

Expand Down
Loading
Loading