diff options
author | Alon Zakai <azakai@google.com> | 2021-01-15 18:13:05 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-15 10:13:05 -0800 |
commit | e2dc4c338476aedff8d95c7549ab0f39d1aaf6d1 (patch) | |
tree | fa6fc4184c5ee762ccdc861a1f1c52188a7a3dc5 /src/wasm-binary.h | |
parent | d808e900b8b8a0bc99d77fd38e94426df73c3afa (diff) | |
download | binaryen-e2dc4c338476aedff8d95c7549ab0f39d1aaf6d1.tar.gz binaryen-e2dc4c338476aedff8d95c7549ab0f39d1aaf6d1.tar.bz2 binaryen-e2dc4c338476aedff8d95c7549ab0f39d1aaf6d1.zip |
[GC] Read and lower Let instructions (#3485)
For now we don't support non-nullability, and can therefore lower a let into
simpler things. That is,
(let $x = ...
;;
)
=>
(block
$x = ...
;;
)
This lets us handle wasm binaries with let, so that we can optimize them
(with the current downside of losing non-nullability).
This is still not trivial to do, sadly, because the indexing of lets is somewhat
odd in the binary. A let modifies the indexes of other things declared before it,
which means that index "0" means different things at different times. And this
is trickier for us because we add more locals as needed for tuples and stacky
code. So this PR makes us track the absolute local indexes from which each
let started to allocate its locals.
The binary testcase was created from this wat using wasp:
(module
(type $vector (array (field (mut f64))))
(func $main
(local $x i32)
(local $y i32)
(drop (local.get $x)) ;; 0 is the index appearing in the binary
;; first let
(array.new_with_rtt $vector
(f64.const 3.14159)
(i32.const 1)
(rtt.canon $vector)
)
(let (local $v (ref $vector))
(drop (local.get $v)) ;; 0
(drop (local.get $x)) ;; 1
;; another one, nested
(array.new_with_rtt $vector
(f64.const 1234)
(i32.const 2)
(rtt.canon $vector)
)
(let (local $w (ref $vector))
(drop (local.get $v)) ;; 1
(drop (local.get $w)) ;; 0
(drop (local.get $x)) ;; 2
)
)
;; another one, later
(array.new_with_rtt $vector
(f64.const 2.1828)
(i32.const 3)
(rtt.canon $vector)
)
(let (local $v (ref $vector))
(drop (local.get $v)) ;; 0
(drop (local.get $x)) ;; 1
)
(drop (local.get $x)) ;; 0
)
)
Diffstat (limited to 'src/wasm-binary.h')
-rw-r--r-- | src/wasm-binary.h | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ea18fdf67..bda793216 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1004,6 +1004,7 @@ enum ASTNodes { CallRef = 0x14, RetCallRef = 0x15, + Let = 0x17, // gc opcodes @@ -1348,6 +1349,7 @@ public: void requireFunctionContext(const char* error); void readFunctions(); + void readVars(); std::map<Export*, Index> exportIndices; std::vector<Export*> exportOrder; @@ -1368,6 +1370,29 @@ public: std::vector<Expression*> expressionStack; + // Each let block in the binary adds new locals to the bottom of the index + // space. That is, all previously-existing indexes are bumped to higher + // indexes. getAbsoluteLocalIndex does this computation. + // Note that we must track not just the number of locals added in each let, + // but also the absolute index from which they were allocated, as binaryen + // will add new locals as it goes for things like stacky code and tuples (so + // there isn't a simple way to get to the absolute index from a relative one). + // Hence each entry here is a pair of the number of items, and the absolute + // index they begin at. + struct LetData { + // How many items are defined in this let. + Index num; + // The absolute index from which they are allocated from. That is, if num is + // 5 and absoluteStart is 10, then we use indexes 10-14. + Index absoluteStart; + }; + std::vector<LetData> letStack; + + // Given a relative index of a local (the one used in the wasm binary), get + // the absolute one which takes into account lets, and is the one used in + // Binaryen IR. + Index getAbsoluteLocalIndex(Index index); + // Control flow structure parsing: these have not just the normal binary // data for an instruction, but also some bytes later on like "end" or "else". // We must be aware of the connection between those things, for debug info. @@ -1522,6 +1547,8 @@ public: void visitRethrow(Rethrow* curr); void visitBrOnExn(BrOnExn* curr); void visitCallRef(CallRef* curr); + // Let is lowered into a block. + void visitLet(Block* curr); void throwError(std::string text); |