summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-08-21 10:39:09 -0700
committerGitHub <noreply@github.com>2024-08-21 10:39:09 -0700
commit7889abf8137291cc591cac8f38570789ebaf354d (patch)
tree135b0de5f6ab7c696cfe0796f4a2f4b98901aabe /src
parentadf53b3b7606a16988b548fe5423b0272913a05a (diff)
downloadbinaryen-7889abf8137291cc591cac8f38570789ebaf354d.tar.gz
binaryen-7889abf8137291cc591cac8f38570789ebaf354d.tar.bz2
binaryen-7889abf8137291cc591cac8f38570789ebaf354d.zip
Support `ref.extern n` in spec tests (#6858)
Spec tests pass the value `ref.extern n`, where `n` is some integer, into exported functions that expect to receive externrefs and receive such values back out as return values. The payload serves to distinguish externrefs so the test can assert that the correct one was returned. Parse these values in wast scripts and represent them as externalized i31refs carrying the payload. We will need a different representation eventually, since some tests explicitly expect these externrefs to not be i31refs, but this suffices to get several new tests passing. To get the memory64 version of table_grow.wast passing, additionally fix the interpreter to handle growing 64-bit tables correctly. Delete the local versions of the upstream tests that can now be run successfully.
Diffstat (limited to 'src')
-rw-r--r--src/parser/wast-parser.cpp12
-rw-r--r--src/tools/wasm-shell.cpp3
-rw-r--r--src/wasm-interpreter.h13
-rw-r--r--src/wasm/literal.cpp3
4 files changed, 21 insertions, 10 deletions
diff --git a/src/parser/wast-parser.cpp b/src/parser/wast-parser.cpp
index a3a6c14ce..00269a577 100644
--- a/src/parser/wast-parser.cpp
+++ b/src/parser/wast-parser.cpp
@@ -25,7 +25,17 @@ using namespace std::string_view_literals;
namespace {
Result<Literal> const_(Lexer& in) {
- // TODO: handle `ref.extern n` as well.
+ if (in.takeSExprStart("ref.extern"sv)) {
+ auto n = in.takeI32();
+ if (!n) {
+ return in.err("expected host reference payload");
+ }
+ if (!in.takeRParen()) {
+ return in.err("expected end of ref.extern");
+ }
+ // Represent host references as externalized i31s.
+ return Literal::makeI31(*n, Unshared).externalize();
+ }
return parseConst(in);
}
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index 651857965..eda4facc9 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -318,7 +318,8 @@ struct Shell {
return Err{err.str()};
}
} else if (auto* ref = std::get_if<RefResult>(&expected)) {
- if (!val.type.isRef() || val.type.getHeapType() != ref->type) {
+ if (!val.type.isRef() ||
+ !HeapType::isSubType(val.type.getHeapType(), ref->type)) {
err << "expected " << ref->type << " reference, got " << val
<< atIndex();
return Err{err.str()};
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 1bf135c40..cbd2b31d6 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -3172,20 +3172,17 @@ public:
}
auto info = getTableInstanceInfo(curr->table);
- Index tableSize = info.interface()->tableSize(info.name);
+ uint64_t tableSize = info.interface()->tableSize(info.name);
auto* table = info.instance->wasm.getTable(info.name);
Flow ret = Literal::makeFromInt64(tableSize, table->indexType);
Flow fail = Literal::makeFromInt64(-1, table->indexType);
- Index delta = deltaFlow.getSingleValue().geti32();
+ uint64_t delta = deltaFlow.getSingleValue().getUnsigned();
- if (tableSize >= uint32_t(-1) - delta) {
+ uint64_t newSize;
+ if (std::ckd_add(&newSize, tableSize, delta)) {
return fail;
}
- if (uint64_t(tableSize) + uint64_t(delta) > uint64_t(table->max)) {
- return fail;
- }
- Index newSize = tableSize + delta;
- if (newSize > WebLimitations::MaxTableSize) {
+ if (newSize > table->max || newSize > WebLimitations::MaxTableSize) {
return fail;
}
if (!info.interface()->growTable(
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 650318be3..d60e2f8a9 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -463,6 +463,9 @@ bool Literal::operator==(const Literal& other) const {
if (type.getHeapType().isMaybeShared(HeapType::i31)) {
return i32 == other.i32;
}
+ if (type.getHeapType().isMaybeShared(HeapType::ext)) {
+ return internalize() == other.internalize();
+ }
WASM_UNREACHABLE("unexpected type");
}
WASM_UNREACHABLE("unexpected type");