@@ -99,7 +99,7 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
9999 // that can reach catch blocks (each item is assumed to be able to reach any
100100 // of the catches, although that could be improved perhaps).
101101 std::vector<std::vector<BasicBlock*>> throwingInstsStack;
102- // stack of 'Try' expressions corresponding to throwingInstsStack.
102+ // stack of 'Try'/'TryTable' expressions corresponding to throwingInstsStack.
103103 std::vector<Expression*> tryStack;
104104 // A stack for each try, where each entry is a list of blocks, one for each
105105 // catch, used during processing. We start by assigning the start blocks to
@@ -254,11 +254,11 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
254254 }
255255
256256 static void doEndThrowingInst (SubType* self, Expression** currp) {
257- // If the innermost try does not have a catch_all clause, an exception
258- // thrown can be caught by any of its outer catch block. And if that outer
259- // try-catch also does not have a catch_all, this continues until we
260- // encounter a try-catch_all. Create a link to all those possible catch
261- // unwind destinations.
257+ // If the innermost try/try_table does not have a catch_all clause, an
258+ // exception thrown can be caught by any of its outer catch block. And if
259+ // that outer try/try_table also does not have a catch_all, this continues
260+ // until we encounter a try/try_table -catch_all. Create a link to all those
261+ // possible catch unwind destinations.
262262 // TODO This can be more precise for `throw`s if we compare tag types and
263263 // create links to outer catch BBs only when the exception is not caught.
264264 // TODO This can also be more precise if we analyze the structure of nested
@@ -281,36 +281,47 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
281281 // end
282282 assert (self->tryStack .size () == self->throwingInstsStack .size ());
283283 for (int i = self->throwingInstsStack .size () - 1 ; i >= 0 ;) {
284- auto * tryy = self->tryStack [i]->template cast <Try>();
285- if (tryy->isDelegate ()) {
286- // If this delegates to the caller, there is no possibility that this
287- // instruction can throw to outer catches.
288- if (tryy->delegateTarget == DELEGATE_CALLER_TARGET) {
289- break ;
290- }
291- // If this delegates to an outer try, we skip catches between this try
292- // and the target try.
293- [[maybe_unused]] bool found = false ;
294- for (int j = i - 1 ; j >= 0 ; j--) {
295- if (self->tryStack [j]->template cast <Try>()->name ==
296- tryy->delegateTarget ) {
297- i = j;
298- found = true ;
284+ if (auto * tryy = self->tryStack [i]->template dynCast <Try>()) {
285+ if (tryy->isDelegate ()) {
286+ // If this delegates to the caller, there is no possibility that this
287+ // instruction can throw to outer catches.
288+ if (tryy->delegateTarget == DELEGATE_CALLER_TARGET) {
299289 break ;
300290 }
291+ // If this delegates to an outer try, we skip catches between this try
292+ // and the target try.
293+ [[maybe_unused]] bool found = false ;
294+ for (int j = i - 1 ; j >= 0 ; j--) {
295+ if (self->tryStack [j]->template cast <Try>()->name ==
296+ tryy->delegateTarget ) {
297+ i = j;
298+ found = true ;
299+ break ;
300+ }
301+ }
302+ assert (found);
303+ continue ;
301304 }
302- assert (found);
303- continue ;
304305 }
305306
306307 // Exception thrown. Note outselves so that we will create a link to each
307- // catch within the try when we get there.
308+ // catch within the try / each destination block within the try_table when
309+ // we get there.
308310 self->throwingInstsStack [i].push_back (self->currBasicBlock );
309311
310- // If this try has catch_all, there is no possibility that this
311- // instruction can throw to outer catches. Stop here.
312- if (tryy->hasCatchAll ()) {
313- break ;
312+ if (auto * tryy = self->tryStack [i]->template dynCast <Try>()) {
313+ // If this try has catch_all, there is no possibility that this
314+ // instruction can throw to outer catches. Stop here.
315+ if (tryy->hasCatchAll ()) {
316+ break ;
317+ }
318+ } else if (auto * tryTable =
319+ self->tryStack [i]->template dynCast <TryTable>()) {
320+ if (tryTable->hasCatchAll ()) {
321+ break ;
322+ }
323+ } else {
324+ WASM_UNREACHABLE (" invalid throwingInstsStack item" );
314325 }
315326 i--;
316327 }
@@ -411,6 +422,28 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
411422 self->startUnreachableBlock ();
412423 }
413424
425+ static void doStartTryTable (SubType* self, Expression** currp) {
426+ auto * curr = (*currp)->cast <TryTable>();
427+ self->throwingInstsStack .emplace_back ();
428+ self->tryStack .push_back (curr);
429+ }
430+
431+ static void doEndTryTable (SubType* self, Expression** currp) {
432+ auto * curr = (*currp)->cast <TryTable>();
433+
434+ auto catchTargets = BranchUtils::getUniqueTargets (curr);
435+ // Add catch destinations to the targets.
436+ for (auto target : catchTargets) {
437+ auto & preds = self->throwingInstsStack .back ();
438+ for (auto * pred : preds) {
439+ self->branches [target].push_back (pred);
440+ }
441+ }
442+
443+ self->throwingInstsStack .pop_back ();
444+ self->tryStack .pop_back ();
445+ }
446+
414447 static bool isReturnCall (Expression* curr) {
415448 switch (curr->_id ) {
416449 case Expression::Id::CallId:
@@ -478,8 +511,13 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
478511 self->pushTask (SubType::doStartTry, currp);
479512 return ; // don't do anything else
480513 }
514+ case Expression::Id::TryTableId: {
515+ self->pushTask (SubType::doEndTryTable, currp);
516+ break ;
517+ }
481518 case Expression::Id::ThrowId:
482- case Expression::Id::RethrowId: {
519+ case Expression::Id::RethrowId:
520+ case Expression::Id::ThrowRefId: {
483521 self->pushTask (SubType::doEndThrow, currp);
484522 break ;
485523 }
@@ -499,6 +537,10 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
499537 self->pushTask (SubType::doStartLoop, currp);
500538 break ;
501539 }
540+ case Expression::Id::TryTableId: {
541+ self->pushTask (SubType::doStartTryTable, currp);
542+ break ;
543+ }
502544 default : {}
503545 }
504546 }
0 commit comments