summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-03-26 13:38:15 -0700
committerGitHub <noreply@github.com>2024-03-26 13:38:15 -0700
commit165953e3267997e606598a91d0c79f92e39ee2cc (patch)
tree7f8dbc5477ed800de2927d1ae57ad99c0cf2683a /src
parent19f8cc706e823f97554f5e4e9167060061d32a41 (diff)
downloadbinaryen-165953e3267997e606598a91d0c79f92e39ee2cc.tar.gz
binaryen-165953e3267997e606598a91d0c79f92e39ee2cc.tar.bz2
binaryen-165953e3267997e606598a91d0c79f92e39ee2cc.zip
Fix stringview subtyping (#6440)
The stringview types (`stringview_wtf8`, `stringview_wtf16`, and `stringview_iter`) are not subtypes of `any` even though they are supertypes of `none`. This breaks the type system invariant that types share a bottom type iff they share a top type, but we can work around that.
Diffstat (limited to 'src')
-rw-r--r--src/tools/fuzzing/heap-types.cpp9
-rw-r--r--src/wasm/wasm-type.cpp37
2 files changed, 38 insertions, 8 deletions
diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp
index 13ad01474..5c948e44d 100644
--- a/src/tools/fuzzing/heap-types.cpp
+++ b/src/tools/fuzzing/heap-types.cpp
@@ -454,12 +454,19 @@ struct HeapTypeGeneratorImpl {
candidates.push_back(HeapType::any);
break;
case HeapType::string:
+ candidates.push_back(HeapType::any);
+ break;
case HeapType::stringview_wtf8:
case HeapType::stringview_wtf16:
case HeapType::stringview_iter:
- candidates.push_back(HeapType::any);
break;
case HeapType::none:
+ if (rand.oneIn(10)) {
+ candidates.push_back(HeapType::stringview_wtf8);
+ candidates.push_back(HeapType::stringview_wtf16);
+ candidates.push_back(HeapType::stringview_iter);
+ break;
+ }
return pickSubAny();
case HeapType::nofunc:
return pickSubFunc();
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 5957f9388..32da64470 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -456,7 +456,7 @@ std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a,
if (a == b) {
return a;
}
- if (HeapType(a).getBottom() != HeapType(b).getBottom()) {
+ if (HeapType(a).getTop() != HeapType(b).getTop()) {
return {};
}
if (HeapType(a).isBottom()) {
@@ -494,10 +494,12 @@ std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a,
return {HeapType::any};
case HeapType::array:
case HeapType::string:
+ return {HeapType::any};
case HeapType::stringview_wtf8:
case HeapType::stringview_wtf16:
case HeapType::stringview_iter:
- return {HeapType::any};
+ // Only joinable with bottom or self, both already handled.
+ return std::nullopt;
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc:
@@ -1411,6 +1413,14 @@ HeapType::BasicHeapType HeapType::getBottom() const {
}
HeapType::BasicHeapType HeapType::getTop() const {
+ if (*this == HeapType::stringview_wtf8 ||
+ *this == HeapType::stringview_wtf16 ||
+ *this == HeapType::stringview_iter) {
+ // These types are their own top types even though they share a bottom type
+ // `none` with the anyref hierarchy. This means that technically there are
+ // multiple top types for `none`, but `any` is the canonical one.
+ return getBasic();
+ }
switch (getBottom()) {
case none:
return any;
@@ -1418,7 +1428,20 @@ HeapType::BasicHeapType HeapType::getTop() const {
return func;
case noext:
return ext;
- default:
+ case noexn:
+ return exn;
+ case ext:
+ case func:
+ case any:
+ case eq:
+ case i31:
+ case struct_:
+ case array:
+ case exn:
+ case string:
+ case stringview_wtf8:
+ case stringview_wtf16:
+ case stringview_iter:
break;
}
WASM_UNREACHABLE("unexpected type");
@@ -1693,13 +1716,13 @@ bool SubTyper::isSubType(HeapType a, HeapType b) {
if (b.isBasic()) {
switch (b.getBasic()) {
case HeapType::ext:
- return a.getBottom() == HeapType::noext;
+ return a.getTop() == HeapType::ext;
case HeapType::func:
- return a.getBottom() == HeapType::nofunc;
+ return a.getTop() == HeapType::func;
case HeapType::exn:
- return a.getBottom() == HeapType::noexn;
+ return a.getTop() == HeapType::exn;
case HeapType::any:
- return a.getBottom() == HeapType::none;
+ return a.getTop() == HeapType::any;
case HeapType::eq:
return a == HeapType::i31 || a == HeapType::none ||
a == HeapType::struct_ || a == HeapType::array || a.isStruct() ||