diff options
Diffstat (limited to 'src/wasm-ir-builder.h')
-rw-r--r-- | src/wasm-ir-builder.h | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index 6a1b3f18a..3805a3e38 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -42,9 +42,7 @@ public: // Get the valid Binaryen IR expression representing the sequence of visited // instructions. The IRBuilder is reset and can be used with a fresh sequence // of instructions after this is called. - Expression* build(); - - [[nodiscard]] Result<std::vector<Expression*>> finishInstrs(); + [[nodiscard]] Result<Expression*> build(); // Call visit() on an existing Expression with its non-child fields // initialized to initialize the child fields and refinalize it. The specific @@ -56,11 +54,13 @@ public: [[nodiscard]] Result<> visitStructNew(StructNew*); [[nodiscard]] Result<> visitArrayNew(ArrayNew*); + [[nodiscard]] Result<> visitEnd(); + // Alternatively, call makeXYZ to have the IRBuilder allocate the nodes. This // is generally safer than calling `visit` because the function signatures // ensure that there are no missing fields. [[nodiscard]] Result<> makeNop(); - [[nodiscard]] Result<> makeBlock(); + [[nodiscard]] Result<> makeBlock(Name label, Type type); // [[nodiscard]] Result<> makeIf(); // [[nodiscard]] Result<> makeLoop(); // [[nodiscard]] Result<> makeBreak(); @@ -168,9 +168,6 @@ public: // [[nodiscard]] Result<> makeStringSliceWTF(); // [[nodiscard]] Result<> makeStringSliceIter(); - // TODO: make this private. - void pushScope(Type type) { scopeStack.push_back({{}, type}); } - void setFunction(Function* func) { this->func = func; } private: @@ -183,24 +180,42 @@ private: // to have. struct BlockCtx { std::vector<Expression*> exprStack; - Type type; + Block* block; + // Whether we have seen an unreachable instruction and are in + // stack-polymorphic unreachable mode. + bool unreachable = false; }; // The stack of block contexts currently being parsed. std::vector<BlockCtx> scopeStack; - std::vector<Expression*>& getExprStack(); - Type getResultType() { - assert(!scopeStack.empty()); - return scopeStack.back().type; + + BlockCtx& getScope() { + if (scopeStack.empty()) { + // We are not in a block context, so push a dummy scope. + scopeStack.push_back({{}, nullptr}); + } + return scopeStack.back(); } - // Whether we have seen an unreachable instruction and are in - // stack-polymorphic unreachable mode. - bool unreachable = false; + [[nodiscard]] Result<Index> addScratchLocal(Type); + [[nodiscard]] Result<Expression*> pop(); + void push(Expression*); + + struct HoistedVal { + // The index in the stack of the original value-producing expression. + Index valIndex; + // The local.get placed on the stack, if any. + LocalGet* get; + }; - Result<Index> addScratchLocal(Type); - [[nodiscard]] Result<> push(Expression*); - Result<Expression*> pop(); + // Find the last value-producing expression, if any, and hoist its value to + // the top of the stack using a scratch local if necessary. + [[nodiscard]] MaybeResult<HoistedVal> hoistLastValue(); + // Transform the stack as necessary such that the original producer of the + // hoisted value will be popped along with the final expression that produces + // the value, if they are different. May only be called directly after + // hoistLastValue(). + [[nodiscard]] Result<> packageHoistedValue(const HoistedVal&); }; } // namespace wasm |