@@ -342,6 +342,16 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
342342 Type inputType;
343343 Index inputLocal = -1 ;
344344
345+ // If there are br_on_*, try_table, or resume branches that target this
346+ // scope and carry additional values, we need to use a scratch local to
347+ // deliver those additional values because the IR does not support them. We
348+ // may need scratch locals of different arities for the same branch target.
349+ // For each arity we also need a trampoline label to branch to. TODO:
350+ // Support additional values on any branch once we have better multivalue
351+ // optimization support.
352+ std::vector<Index> outputLocals;
353+ std::vector<Name> outputLabels;
354+
345355 // The stack of instructions being built in this scope.
346356 std::vector<Expression*> exprStack;
347357
@@ -372,42 +382,43 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
372382 static ScopeCtx makeIf (If* iff, Name originalLabel, Type inputType) {
373383 return ScopeCtx (IfScope{iff, originalLabel}, inputType);
374384 }
375- static ScopeCtx makeElse (If* iff,
376- Name originalLabel,
377- Name label,
378- bool labelUsed,
379- Type inputType,
380- Index inputLocal) {
381- return ScopeCtx (
382- ElseScope{iff, originalLabel}, label, labelUsed, inputType, inputLocal);
385+ static ScopeCtx makeElse (ScopeCtx&& scope) {
386+ scope.scope = ElseScope{scope.getIf (), scope.getOriginalLabel ()};
387+ scope.resetForDelimiter (/* keepInput=*/ true );
388+ return scope;
383389 }
384390 static ScopeCtx makeLoop (Loop* loop, Type inputType) {
385391 return ScopeCtx (LoopScope{loop}, inputType);
386392 }
387393 static ScopeCtx makeTry (Try* tryy, Name originalLabel, Type inputType) {
388394 return ScopeCtx (TryScope{tryy, originalLabel}, inputType);
389395 }
390- static ScopeCtx makeCatch (Try* tryy,
391- Name originalLabel,
392- Name label,
393- bool labelUsed,
394- Name branchLabel) {
395- return ScopeCtx (
396- CatchScope{tryy, originalLabel}, label, labelUsed, branchLabel);
397- }
398- static ScopeCtx makeCatchAll (Try* tryy,
399- Name originalLabel,
400- Name label,
401- bool labelUsed,
402- Name branchLabel) {
403- return ScopeCtx (
404- CatchAllScope{tryy, originalLabel}, label, labelUsed, branchLabel);
396+ static ScopeCtx makeCatch (ScopeCtx&& scope, Try* tryy) {
397+ scope.scope = CatchScope{tryy, scope.getOriginalLabel ()};
398+ scope.resetForDelimiter (/* keepInput=*/ false );
399+ return scope;
400+ }
401+ static ScopeCtx makeCatchAll (ScopeCtx&& scope, Try* tryy) {
402+ scope.scope = CatchAllScope{tryy, scope.getOriginalLabel ()};
403+ scope.resetForDelimiter (/* keepInput=*/ false );
404+ return scope;
405405 }
406406 static ScopeCtx
407407 makeTryTable (TryTable* trytable, Name originalLabel, Type inputType) {
408408 return ScopeCtx (TryTableScope{trytable, originalLabel}, inputType);
409409 }
410-
410+ // When transitioning to a new scope for a delimiter like `else` or catch,
411+ // most of the scope context is preserved, but some parts need to be reset.
412+ // `keepInput` means that control flow parameters are available at the
413+ // begninning of the scope after the delimiter.
414+ void resetForDelimiter (bool keepInput) {
415+ exprStack.clear ();
416+ unreachable = false ;
417+ if (!keepInput) {
418+ inputType = Type::none;
419+ inputLocal = -1 ;
420+ }
421+ }
411422 bool isNone () { return std::get_if<NoScope>(&scope); }
412423 Function* getFunction () {
413424 if (auto * funcScope = std::get_if<FuncScope>(&scope)) {
@@ -514,6 +525,10 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
514525 }
515526 WASM_UNREACHABLE (" unexpected scope kind" );
516527 }
528+ Type getLabelType () {
529+ // Loops receive their input type rather than their output type.
530+ return getLoop () ? inputType : getResultType ();
531+ }
517532 Name getOriginalLabel () {
518533 if (std::get_if<NoScope>(&scope) || getFunction ()) {
519534 return Name{};
@@ -651,6 +666,9 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
651666 Result<Type> getLabelType (Index label);
652667 Result<Type> getLabelType (Name labelName);
653668
669+ Result<std::pair<Index, Name>> getExtraOutputLocalAndLabel (Index label,
670+ size_t extraArity);
671+ Expression* fixExtraOutput (ScopeCtx& scope, Name label, Expression* expr);
654672 void fixLoopWithInput (Loop* loop, Type inputType, Index scratch);
655673
656674 void dump ();
0 commit comments