diff options
Diffstat (limited to 'src/passes/TranslateEH.cpp')
-rw-r--r-- | src/passes/TranslateEH.cpp | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/passes/TranslateEH.cpp b/src/passes/TranslateEH.cpp index 33fa4689d..f8e059624 100644 --- a/src/passes/TranslateEH.cpp +++ b/src/passes/TranslateEH.cpp @@ -215,7 +215,9 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { // current 'try' into 'try_table' yet; it only adds block, br, and throw_ref // instructions to complete the conversions of inner try~delegates that target // the current try. - void processDelegateTarget(Try* curr, Block* outerBlock) { + void processDelegateTarget(Try* curr, + Block* outerBlock, + bool& outerBlockUsedSoFar) { Builder builder(*getModule()); // Convert @@ -291,10 +293,12 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { Name delegateBrTarget = delegateTargetToBrTarget[curr->name]; Expression* innerBody = nullptr; if (curr->type.isConcrete()) { + outerBlockUsedSoFar = true; auto* brToOuter = builder.makeBreak(outerBlock->name, curr->body); innerBody = builder.blockifyWithName( brToOuter, delegateBrTarget, nullptr, Type(HeapType::exn, Nullable)); } else { + outerBlockUsedSoFar = curr->body->type != Type::unreachable; auto* brToOuter = curr->body->type == Type::unreachable ? nullptr : builder.makeBreak(outerBlock->name); @@ -304,7 +308,7 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { curr->body = builder.makeThrowRef(innerBody); } - void processDelegate(Try* curr, Block* outerBlock) { + void processDelegate(Try* curr, Block* outerBlock, bool outerBlockUsedSoFar) { Builder builder(*getModule()); // Convert // (try @@ -332,7 +336,7 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { // If we need an outer block for other reasons (if this is a target of a // delegate), we insert the new try_table into it. If not we just replace // the current try with the new try_table. - if (outerBlock) { + if (outerBlock && outerBlockUsedSoFar) { outerBlock->list.push_back(tryTable); replaceCurrent(outerBlock); } else { @@ -340,7 +344,7 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { } } - void processCatches(Try* curr, Block* outerBlock) { + void processCatches(Try* curr, Block* outerBlock, bool outerBlockUsedSoFar) { Module* wasm = getModule(); Builder builder(*wasm); @@ -385,7 +389,15 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { // If we don't have any catches, we don't need to do more. if (curr->catchBodies.empty()) { // catch-less try - replaceCurrent(tryTable); + // If we need an outer block for other reasons (if this is a target of a + // delegate), we insert the new try_table into it. If not we just replace + // the current try with the new try_table. + if (outerBlock && outerBlockUsedSoFar) { + outerBlock->list.push_back(tryTable); + replaceCurrent(outerBlock); + } else { + replaceCurrent(tryTable); + } return; } @@ -679,13 +691,14 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { builder.makeBlock(labels->getUnique("outer"), {}, curr->type); } + bool outerBlockUsedSoFar = false; if (it != delegateTargetToBrTarget.end()) { - processDelegateTarget(curr, outerBlock); + processDelegateTarget(curr, outerBlock, outerBlockUsedSoFar); } if (curr->isDelegate()) { - processDelegate(curr, outerBlock); + processDelegate(curr, outerBlock, outerBlockUsedSoFar); } else { // try-catch or catch-less try - processCatches(curr, outerBlock); + processCatches(curr, outerBlock, outerBlockUsedSoFar); } } |