diff options
author | Alon Zakai <azakai@google.com> | 2022-05-31 12:29:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-31 12:29:36 -0700 |
commit | 4d0646a6ea6d0104d8a5997f1d607d91e0a661a2 (patch) | |
tree | e7fe83c1f13f0607a6cd49f120d280c768c83299 /src | |
parent | 07d90673f1765c3ddff03f7748caefe9a7d14ffa (diff) | |
download | binaryen-4d0646a6ea6d0104d8a5997f1d607d91e0a661a2.tar.gz binaryen-4d0646a6ea6d0104d8a5997f1d607d91e0a661a2.tar.bz2 binaryen-4d0646a6ea6d0104d8a5997f1d607d91e0a661a2.zip |
[WasmGC] Fix non-nullable locals and try-catch in SimplifyLocals (#4703)
Binaryen will not change dominance in SimplifyLocals, however, the current spec's
notion of dominance is simpler than ours, and we must not optimize certain cases in
order to still validate. See details in the comment and test.
Helps #4702
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 35980f503..5cf3b8241 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -299,12 +299,47 @@ struct SimplifyLocals Expression** currp) { Expression* curr = *currp; - // Expressions that may throw cannot be sinked into 'try'. At the start of - // 'try', we drop all sinkables that may throw. + // Certain expressions cannot be sinked into 'try', and so at the start of + // 'try' we forget about them. if (curr->is<Try>()) { std::vector<Index> invalidated; for (auto& [index, info] : self->sinkables) { - if (info.effects.throws()) { + // Expressions that may throw cannot be moved into a try (which might + // catch them, unlike before the move). + // + // Also, non-nullable local.sets cannot be moved into a try, as that may + // change dominance from the perspective of the spec + // + // (local.set $x X) + // (try + // .. + // (Y + // (local.get $x)) + // (catch + // (Z + // (local.get $x))) + // + // => + // + // (try + // .. + // (Y + // (local.tee $x X)) + // (catch + // (Z + // (local.get $x))) + // + // After sinking the set, the tee does not dominate the get in the + // catch, at least not in the simple way the spec defines it, see + // https://github.com/WebAssembly/function-references/issues/44#issuecomment-1083146887 + // We have more refined information about control flow and dominance + // than the spec, and so we would see if ".." can throw or not (only if + // it can throw is there a branch to the catch, which can change + // dominance). To stay compliant with the spec, however, we must not + // move code regardless of whether ".." can throw - we must simply keep + // the set outside of the try. + if (info.effects.throws() || + self->getFunction()->getLocalType(index).isNonNullable()) { invalidated.push_back(index); } } |