diff options
author | Alon Zakai <azakai@google.com> | 2020-12-17 16:47:38 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-17 16:47:38 -0800 |
commit | cad723a3827913f53ecfa7189b011be389d28ae7 (patch) | |
tree | 20e3e20db43dbb7333e4c1ed67034614485f1a6d /src/wasm-interpreter.h | |
parent | 46789afc681de080ec9ba68ffe27d9f9871d8bb3 (diff) | |
download | binaryen-cad723a3827913f53ecfa7189b011be389d28ae7.tar.gz binaryen-cad723a3827913f53ecfa7189b011be389d28ae7.tar.bz2 binaryen-cad723a3827913f53ecfa7189b011be389d28ae7.zip |
[GC] Add br_on_cast (#3451)
The tricky part here, as pointed out by aheejin in my previous attempt, is that
we need to know the type of the value we send if the branch is taken. We can
normally calculate that from the rtt parameter's type - we are casting to that
RTT, so we know what type that is - but if the rtt is unreachable, that's a problem.
To fix that, store the cast type on BrOnCast instructions.
This includes a test with a br_on_cast that succeeds and sends the cast value,
one that fails and passes through the uncast value, and also of one with an
unreachable RTT.
This includes a fix for Precompute, as noticed by that new test. If a break is
taken, with a ref as a value, we can't precompute it - for the same reasons
we can't precompute a ref in general, that it is a pointer to possibly shared
data.
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 223d02d87..019a56db1 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -60,6 +60,7 @@ public: Flow(Literals& values) : values(values) {} Flow(Literals&& values) : values(std::move(values)) {} Flow(Name breakTo) : values(), breakTo(breakTo) {} + Flow(Name breakTo, Literal value) : values{value}, breakTo(breakTo) {} Literals values; Name breakTo; // if non-null, a break is going on @@ -1462,7 +1463,15 @@ public: } Flow visitBrOnCast(BrOnCast* curr) { NOTE_ENTER("BrOnCast"); - WASM_UNREACHABLE("TODO (gc): br_on_cast"); + auto cast = doCast(curr); + if (cast.outcome == cast.Break) { + return cast.breaking; + } + if (cast.outcome == cast.Null || cast.outcome == cast.Failure) { + return cast.originalRef; + } + assert(cast.outcome == cast.Success); + return Flow(curr->name, cast.castRef); } Flow visitRttCanon(RttCanon* curr) { return Literal(curr->type); } Flow visitRttSub(RttSub* curr) { |