summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-12-09 11:17:28 -0800
committerGitHub <noreply@github.com>2020-12-09 11:17:28 -0800
commit823222ff566b38495327bc28b4726871b0a86b26 (patch)
treed0425f0c40d61e9085bc3a9880faa08eafd70276 /src/wasm/wasm-validator.cpp
parent63a042e3a94df7ba3a5c9dde03990a9813fdc366 (diff)
downloadbinaryen-823222ff566b38495327bc28b4726871b0a86b26.tar.gz
binaryen-823222ff566b38495327bc28b4726871b0a86b26.tar.bz2
binaryen-823222ff566b38495327bc28b4726871b0a86b26.zip
[GC] Add struct.new and start to test interesting execution (#3433)
With struct.new read/write support, we can start to do interesting things! This adds a test of creating a struct and seeing that references behave like references, that is, if we write to the value X refers to, and if Y refers to the same thing, when reading from Y's value we see the change as well. The test is run through all of -O1, which uncovered a minor issue in Precompute: We can't try to precompute a reference type, as we can't replace a reference with a value. Note btw that the test shows the optimizer properly running CoalesceLocals on reference types, merging two locals.
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index c6e22899c..e97541444 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2238,7 +2238,39 @@ void FunctionValidator::visitStructNew(StructNew* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.new requires gc to be enabled");
- WASM_UNREACHABLE("TODO (gc): struct.new");
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) {
+ return;
+ }
+ auto heapType = curr->rtt->type.getHeapType();
+ if (!shouldBeTrue(
+ heapType.isStruct(), curr, "struct.new heap type must be struct")) {
+ return;
+ }
+ const auto& fields = heapType.getStruct().fields;
+ if (curr->isWithDefault()) {
+ shouldBeTrue(curr->operands.empty(),
+ curr,
+ "struct.new_with_default should have no operands");
+ // All the fields must be defaultable.
+ for (const auto& field : fields) {
+ // TODO: add type.isDefaultable()?
+ shouldBeTrue(!field.type.isRef() || field.type.isNullable(),
+ field,
+ "struct.new_with_default value type must be defaultable");
+ }
+ } else {
+ // All the fields must have the proper type.
+ for (Index i = 0; i < fields.size(); i++) {
+ shouldBeSubType(curr->operands[i]->type,
+ fields[i].type,
+ curr,
+ "struct.new operand must have proper type");
+ }
+ }
}
void FunctionValidator::visitStructGet(StructGet* curr) {