diff options
author | Thomas Lively <tlively@google.com> | 2023-08-28 12:41:14 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-28 10:41:14 -0700 |
commit | 0e5ee1cb368548f6890efcc05c980d5bb56f27d6 (patch) | |
tree | f3e82d514a5967a8bc7bac5470a4be6f2c7cb07b /src/wasm-ir-builder.h | |
parent | 91114e6a9b69969e673ffb40e7dc54029d15a0f8 (diff) | |
download | binaryen-0e5ee1cb368548f6890efcc05c980d5bb56f27d6.tar.gz binaryen-0e5ee1cb368548f6890efcc05c980d5bb56f27d6.tar.bz2 binaryen-0e5ee1cb368548f6890efcc05c980d5bb56f27d6.zip |
Refactor IRBuilder to build blocks internally (#5901)
The initial PR introducing IRBuilder kept the interface the same as the previous
internal interface in the new wat parser. This PR updates that interface to
avoid exposing implementation details of the IRBuilder and to provide an API
that matches the binary format. For example, after calling `makeBlock` or
`visitBlock` at the beginning of a block, users now call `visitEnd()` at the end
of the block without having to manually install the block's contents.
Providing this improved interface requires refactoring some of the IRBuilder
internals. While we are refactoring things anyway, put in extra effort to avoid
unnecessarily splitting up and recombining tuples that could simply be returned
from a multivalue block.
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 |