summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp9
-rw-r--r--src/wasm/wasm-validator.cpp131
2 files changed, 68 insertions, 72 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 1644c2950..c4aaec5e9 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2272,11 +2272,16 @@ void WasmBinaryReader::readTypes() {
TypeBuilder builder(getU32LEB());
BYN_TRACE("num: " << builder.size() << std::endl);
- auto readHeapType = [&]() {
+ auto readHeapType = [&]() -> HeapType {
int64_t htCode = getS64LEB(); // TODO: Actually s33
+ auto share = Unshared;
+ if (htCode == BinaryConsts::EncodedType::Shared) {
+ share = Shared;
+ htCode = getS64LEB(); // TODO: Actually s33
+ }
HeapType ht;
if (getBasicHeapType(htCode, ht)) {
- return ht;
+ return ht.getBasic(share);
}
if (size_t(htCode) >= builder.size()) {
throwError("invalid type index: " + std::to_string(htCode));
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 13993c825..281f3ec45 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -209,6 +209,18 @@ struct ValidationInfo {
fail(text, curr, func);
return false;
}
+
+ bool shouldBeSubTypeIgnoringShared(Type left,
+ Type right,
+ Expression* curr,
+ const char* text,
+ Function* func = nullptr) {
+ assert(right.isRef() && right.getHeapType().isBasic());
+ auto share = left.isRef() ? left.getHeapType().getShared() : Unshared;
+ auto ht = right.getHeapType();
+ auto matchedRight = Type(ht.getBasic(share), right.getNullability());
+ return shouldBeSubType(left, matchedRight, curr, text, func);
+ }
};
struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> {
@@ -526,6 +538,13 @@ private:
return info.shouldBeSubType(left, right, curr, text, getFunction());
}
+ bool shouldBeSubTypeIgnoringShared(Type left,
+ Type right,
+ Expression* curr,
+ const char* text) {
+ return info.shouldBeSubTypeIgnoringShared(left, right, curr, text);
+ }
+
void validateOffset(Address offset, Memory* mem, Expression* curr);
void validateAlignment(
size_t align, Type type, Index bytes, bool isAtomic, Expression* curr);
@@ -2256,14 +2275,16 @@ void FunctionValidator::visitRefEq(RefEq* curr) {
Type eqref = Type(HeapType::eq, Nullable);
shouldBeTrue(
getModule()->features.hasGC(), curr, "ref.eq requires gc [--enable-gc]");
- shouldBeSubType(curr->left->type,
- eqref,
- curr->left,
- "ref.eq's left argument should be a subtype of eqref");
- shouldBeSubType(curr->right->type,
- eqref,
- curr->right,
- "ref.eq's right argument should be a subtype of eqref");
+ shouldBeSubTypeIgnoringShared(
+ curr->left->type,
+ eqref,
+ curr->left,
+ "ref.eq's left argument should be a subtype of eqref");
+ shouldBeSubTypeIgnoringShared(
+ curr->right->type,
+ eqref,
+ curr->right,
+ "ref.eq's right argument should be a subtype of eqref");
}
void FunctionValidator::visitTableGet(TableGet* curr) {
@@ -2689,10 +2710,10 @@ void FunctionValidator::visitI31Get(I31Get* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"i31.get_s/u requires gc [--enable-gc]");
- shouldBeSubType(curr->i31->type,
- Type(HeapType::i31, Nullable),
- curr->i31,
- "i31.get_s/u's argument should be i31ref");
+ shouldBeSubTypeIgnoringShared(curr->i31->type,
+ Type(HeapType::i31, Nullable),
+ curr->i31,
+ "i31.get_s/u's argument should be i31ref");
}
void FunctionValidator::visitRefTest(RefTest* curr) {
@@ -3008,24 +3029,15 @@ void FunctionValidator::visitArrayGet(ArrayGet* curr) {
getModule()->features.hasGC(), curr, "array.get requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(
curr->index->type, Type(Type::i32), curr, "array.get index must be an i32");
- if (curr->type == Type::unreachable) {
- return;
- }
- if (!shouldBeSubType(curr->ref->type,
- Type(HeapType::array, Nullable),
- curr,
- "array.get target should be an array reference")) {
+ const char* mustBeArray =
+ "array.get target should be a specific array reference";
+ if (curr->type == Type::unreachable ||
+ !shouldBeTrue(curr->ref->type.isRef(), curr, mustBeArray) ||
+ curr->ref->type.getHeapType().isBottom() ||
+ !shouldBeTrue(curr->ref->type.isArray(), curr, mustBeArray)) {
return;
}
auto heapType = curr->ref->type.getHeapType();
- if (heapType == HeapType::none) {
- return;
- }
- if (!shouldBeTrue(heapType != HeapType::array,
- curr,
- "array.get target should be a specific array reference")) {
- return;
- }
const auto& element = heapType.getArray().element;
// If the type is not packed, it must be marked internally as unsigned, by
// convention.
@@ -3044,19 +3056,11 @@ void FunctionValidator::visitArraySet(ArraySet* curr) {
if (curr->type == Type::unreachable) {
return;
}
- if (!shouldBeSubType(curr->ref->type,
- Type(HeapType::array, Nullable),
- curr,
- "array.set target should be an array reference")) {
- return;
- }
- auto heapType = curr->ref->type.getHeapType();
- if (heapType == HeapType::none) {
- return;
- }
- if (!shouldBeTrue(heapType != HeapType::array,
- curr,
- "array.set target should be a specific array reference")) {
+ const char* mustBeArray = "array.set target should be an array reference";
+ if (curr->type == Type::unreachable ||
+ !shouldBeTrue(curr->ref->type.isRef(), curr, mustBeArray) ||
+ curr->ref->type.getHeapType().isBottom() ||
+ !shouldBeTrue(curr->ref->type.isArray(), curr, mustBeArray)) {
return;
}
const auto& element = curr->ref->type.getHeapType().getArray().element;
@@ -3072,10 +3076,11 @@ void FunctionValidator::visitArrayLen(ArrayLen* curr) {
getModule()->features.hasGC(), curr, "array.len requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "array.len result must be an i32");
- shouldBeSubType(curr->ref->type,
- Type(HeapType::array, Nullable),
- curr,
- "array.len argument must be an array reference");
+ shouldBeSubTypeIgnoringShared(
+ curr->ref->type,
+ Type(HeapType::array, Nullable),
+ curr,
+ "array.len argument must be an array reference");
}
void FunctionValidator::visitArrayCopy(ArrayCopy* curr) {
@@ -3145,22 +3150,15 @@ void FunctionValidator::visitArrayFill(ArrayFill* curr) {
"array.fill index must be an i32");
shouldBeEqualOrFirstIsUnreachable(
curr->size->type, Type(Type::i32), curr, "array.fill size must be an i32");
- if (curr->type == Type::unreachable) {
- return;
- }
- if (!shouldBeSubType(curr->ref->type,
- Type(HeapType::array, Nullable),
- curr,
- "array.fill destination should be an array reference")) {
+ const char* mustBeArray =
+ "array.fill destination should be an array reference";
+ if (curr->type == Type::unreachable ||
+ !shouldBeTrue(curr->ref->type.isRef(), curr, mustBeArray) ||
+ curr->ref->type.getHeapType().isBottom() ||
+ !shouldBeTrue(curr->ref->type.isArray(), curr, mustBeArray)) {
return;
}
auto heapType = curr->ref->type.getHeapType();
- if (heapType == HeapType::none ||
- !shouldBeTrue(heapType.isArray(),
- curr,
- "array.fill destination should be an array reference")) {
- return;
- }
auto element = heapType.getArray().element;
shouldBeSubType(curr->value->type,
element.type,
@@ -3187,22 +3185,15 @@ void FunctionValidator::visitArrayInit(ArrayInit* curr) {
Type(Type::i32),
curr,
"array.init_* size must be an i32");
- if (curr->type == Type::unreachable) {
- return;
- }
- if (!shouldBeSubType(curr->ref->type,
- Type(HeapType::array, Nullable),
- curr,
- "array.init_* destination must be an array reference")) {
+ const char* mustBeArray =
+ "array.init_* destination must be an array reference";
+ if (curr->type == Type::unreachable ||
+ !shouldBeTrue(curr->ref->type.isRef(), curr, mustBeArray) ||
+ curr->ref->type.getHeapType().isBottom() ||
+ !shouldBeTrue(curr->ref->type.isArray(), curr, mustBeArray)) {
return;
}
auto heapType = curr->ref->type.getHeapType();
- if (heapType == HeapType::none ||
- !shouldBeTrue(heapType.isArray(),
- curr,
- "array.init_* destination must be an array reference")) {
- return;
- }
auto element = heapType.getArray().element;
shouldBeTrue(
element.mutable_, curr, "array.init_* destination must be mutable");