summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp79
1 files changed, 68 insertions, 11 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index e97541444..cf92cf4d3 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2277,14 +2277,19 @@ void FunctionValidator::visitStructGet(StructGet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.get requires gc to be enabled");
- if (curr->ref->type != Type::unreachable) {
- const auto& fields = curr->ref->type.getHeapType().getStruct().fields;
- shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
- shouldBeEqual(curr->type,
- fields[curr->index].type,
- curr,
- "struct.get must have the proper type");
+ const auto& fields = curr->ref->type.getHeapType().getStruct().fields;
+ shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
+ auto field = fields[curr->index];
+ // If the type is not packed, it must be marked internally as unsigned, by
+ // convention.
+ if (field.type != Type::i32 || field.packedType == Field::not_packed) {
+ shouldBeFalse(curr->signed_, curr, "non-packed get cannot be signed");
+ }
+ if (curr->ref->type == Type::unreachable) {
+ return;
}
+ shouldBeEqual(
+ curr->type, field.type, curr, "struct.get must have the proper type");
}
void FunctionValidator::visitStructSet(StructSet* curr) {
@@ -2304,25 +2309,77 @@ void FunctionValidator::visitStructSet(StructSet* curr) {
void FunctionValidator::visitArrayNew(ArrayNew* curr) {
shouldBeTrue(
getModule()->features.hasGC(), curr, "array.new requires gc to be enabled");
- WASM_UNREACHABLE("TODO (gc): array.new");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->size->type, Type(Type::i32), curr, "array.new size must be an i32");
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) {
+ return;
+ }
+ auto heapType = curr->rtt->type.getHeapType();
+ if (!shouldBeTrue(
+ heapType.isArray(), curr, "array.new heap type must be array")) {
+ return;
+ }
+ const auto& element = heapType.getArray().element;
+ if (curr->isWithDefault()) {
+ shouldBeTrue(
+ !curr->init, curr, "array.new_with_default should have no init");
+ // The element must be defaultable.
+ // TODO: add type.isDefaultable()?
+ shouldBeTrue(!element.type.isRef() || element.type.isNullable(),
+ element,
+ "array.new_with_default value type must be defaultable");
+ } else {
+ shouldBeTrue(!!curr->init, curr, "array.new should have an init");
+ // The inits must have the proper type.
+ shouldBeSubType(curr->init->type,
+ element.type,
+ curr,
+ "array.new init must have proper type");
+ }
}
void FunctionValidator::visitArrayGet(ArrayGet* curr) {
shouldBeTrue(
getModule()->features.hasGC(), curr, "array.get requires gc to be enabled");
- WASM_UNREACHABLE("TODO (gc): array.get");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->index->type, Type(Type::i32), curr, "array.get index must be an i32");
+ const auto& element = curr->ref->type.getHeapType().getArray().element;
+ // If the type is not packed, it must be marked internally as unsigned, by
+ // convention.
+ if (element.type != Type::i32 || element.packedType == Field::not_packed) {
+ shouldBeFalse(curr->signed_, curr, "non-packed get cannot be signed");
+ }
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ shouldBeEqual(
+ curr->type, element.type, curr, "array.get must have the proper type");
}
void FunctionValidator::visitArraySet(ArraySet* curr) {
shouldBeTrue(
getModule()->features.hasGC(), curr, "array.set requires gc to be enabled");
- WASM_UNREACHABLE("TODO (gc): array.set");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->index->type, Type(Type::i32), curr, "array.set index must be an i32");
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ const auto& element = curr->ref->type.getHeapType().getArray().element;
+ shouldBeEqual(curr->value->type,
+ element.type,
+ curr,
+ "array.set must have the proper type");
}
void FunctionValidator::visitArrayLen(ArrayLen* curr) {
shouldBeTrue(
getModule()->features.hasGC(), curr, "array.len requires gc to be enabled");
- WASM_UNREACHABLE("TODO (gc): array.len");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->type, Type(Type::i32), curr, "array.len result must be an i32");
}
void FunctionValidator::visitFunction(Function* curr) {