diff options
Diffstat (limited to 'src/wasm-ir-builder.h')
-rw-r--r-- | src/wasm-ir-builder.h | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index e7613b373..ee6721738 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -64,13 +64,21 @@ public: [[nodiscard]] Result<> visitIfStart(If* iff, Name label = {}); [[nodiscard]] Result<> visitElse(); [[nodiscard]] Result<> visitLoopStart(Loop* iff); + [[nodiscard]] Result<> visitTryStart(Try* tryy, Name label = {}); + [[nodiscard]] Result<> visitCatch(Name tag); + [[nodiscard]] Result<> visitCatchAll(); + [[nodiscard]] Result<> visitDelegate(Index label); [[nodiscard]] Result<> visitEnd(); // Binaryen IR uses names to refer to branch targets, but in general there may // be branches to constructs that do not yet have names, so in IRBuilder we // use indices to refer to branch targets instead, just as the binary format // does. This function converts a branch target name to the correct index. - [[nodiscard]] Result<Index> getLabelIndex(Name label); + // + // Labels in delegates need special handling because the indexing needs to be + // relative to the try's enclosing scope rather than the try itself. + [[nodiscard]] Result<Index> getLabelIndex(Name label, + bool inDelegate = false); // Instead of calling visit, call makeXYZ to have the IRBuilder allocate the // nodes. This is generally safer than calling `visit` because the function @@ -145,7 +153,7 @@ public: // [[nodiscard]] Result<> makeTableGrow(); // [[nodiscard]] Result<> makeTableFill(); // [[nodiscard]] Result<> makeTableCopy(); - // [[nodiscard]] Result<> makeTry(); + [[nodiscard]] Result<> makeTry(Name label, Type type); [[nodiscard]] Result<> makeThrow(Name tag); // [[nodiscard]] Result<> makeRethrow(); // [[nodiscard]] Result<> makeTupleMake(); @@ -232,8 +240,27 @@ private: struct LoopScope { Loop* loop; }; - using Scope = std:: - variant<NoScope, FuncScope, BlockScope, IfScope, ElseScope, LoopScope>; + struct TryScope { + Try* tryy; + Name originalLabel; + }; + struct CatchScope { + Try* tryy; + Name originalLabel; + }; + struct CatchAllScope { + Try* tryy; + Name originalLabel; + }; + using Scope = std::variant<NoScope, + FuncScope, + BlockScope, + IfScope, + ElseScope, + LoopScope, + TryScope, + CatchScope, + CatchAllScope>; // The control flow structure we are building expressions for. Scope scope; @@ -264,6 +291,15 @@ private: return ScopeCtx(ElseScope{iff, originalLabel}, label); } static ScopeCtx makeLoop(Loop* loop) { return ScopeCtx(LoopScope{loop}); } + static ScopeCtx makeTry(Try* tryy, Name originalLabel = {}) { + return ScopeCtx(TryScope{tryy, originalLabel}); + } + static ScopeCtx makeCatch(Try* tryy, Name originalLabel, Name label) { + return ScopeCtx(CatchScope{tryy, originalLabel}, label); + } + static ScopeCtx makeCatchAll(Try* tryy, Name originalLabel, Name label) { + return ScopeCtx(CatchAllScope{tryy, originalLabel}, label); + } bool isNone() { return std::get_if<NoScope>(&scope); } Function* getFunction() { @@ -296,6 +332,24 @@ private: } return nullptr; } + Try* getTry() { + if (auto* tryScope = std::get_if<TryScope>(&scope)) { + return tryScope->tryy; + } + return nullptr; + } + Try* getCatch() { + if (auto* catchScope = std::get_if<CatchScope>(&scope)) { + return catchScope->tryy; + } + return nullptr; + } + Try* getCatchAll() { + if (auto* catchAllScope = std::get_if<CatchAllScope>(&scope)) { + return catchAllScope->tryy; + } + return nullptr; + } Type getResultType() { if (auto* func = getFunction()) { return func->type.getSignature().results; @@ -312,6 +366,15 @@ private: if (auto* loop = getLoop()) { return loop->type; } + if (auto* tryy = getTry()) { + return tryy->type; + } + if (auto* tryy = getCatch()) { + return tryy->type; + } + if (auto* tryy = getCatchAll()) { + return tryy->type; + } WASM_UNREACHABLE("unexpected scope kind"); } Name getOriginalLabel() { @@ -330,6 +393,15 @@ private: if (auto* loop = getLoop()) { return loop->name; } + if (auto* tryScope = std::get_if<TryScope>(&scope)) { + return tryScope->originalLabel; + } + if (auto* catchScope = std::get_if<CatchScope>(&scope)) { + return catchScope->originalLabel; + } + if (auto* catchAllScope = std::get_if<CatchAllScope>(&scope)) { + return catchAllScope->originalLabel; + } WASM_UNREACHABLE("unexpected scope kind"); } }; |