diff options
author | Alon Zakai <azakai@google.com> | 2022-08-18 09:14:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-18 09:14:25 -0700 |
commit | 68bf5e3790c8ca95f52c5c5758775a592e708d77 (patch) | |
tree | 11269c53340c60cf261e1ff2debf1929060ea9d8 /src/wasm/wasm.cpp | |
parent | 0c9ffd618ba69128caa61583a7cd9a831fef1d98 (diff) | |
download | binaryen-68bf5e3790c8ca95f52c5c5758775a592e708d77.tar.gz binaryen-68bf5e3790c8ca95f52c5c5758775a592e708d77.tar.bz2 binaryen-68bf5e3790c8ca95f52c5c5758775a592e708d77.zip |
[Wasm GC] Fix TypeRefining on fallthrough values via tee (#4900)
A rather tricky corner case: we normally look at fallthrough values for copies of
fields, so when we try to refine a field, we ignore stuff like this:
a.x = b.x;
That copies the same field on the same type to itself, so refining is not limited by
it. But if we have something else in the middle, and that thing cannot change
type, then it is a problem, like this:
(struct.set
(..ref..)
(local.tee $temp
(struct.get)))
tee has the type of the local, which does not change in this pass. So we can't
look at just the fallthrough here and skip the tee: after refining the field, the
tee's old type might not fit in the field's new type.
We could perhaps add casts to fix things up, but those may have too big a
cost. For now, just ignore the fallthrough.
Diffstat (limited to 'src/wasm/wasm.cpp')
-rw-r--r-- | src/wasm/wasm.cpp | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 574eb5c47..20d1b643e 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -259,6 +259,12 @@ void Break::finalize() { if (condition->type == Type::unreachable) { type = Type::unreachable; } else if (value) { + // N.B. This is not correct wrt the spec, which mandates that it be the + // type of the block we target. In practice this does not matter because + // the br_if return value is not really used in the wild. To fix this, + // we'd need to do something like what we do for local.tee's type, which + // is to fix it up in a way that is aware of function-level context and + // not just the instruction itself (which would be a pain). type = value->type; } else { type = Type::none; |