summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Print.cpp15
-rw-r--r--src/wasm/wasm-validator.cpp16
-rw-r--r--test/heap-types.wast8
-rw-r--r--test/heap-types.wast.from-wast13
-rw-r--r--test/heap-types.wast.fromBinary3
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo3
6 files changed, 58 insertions, 0 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 67deac35c..b7b7e1320 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1840,7 +1840,18 @@ struct PrintExpressionContents
o << "with_rtt ";
printHeapTypeName(o, curr->rtt->type.getHeapType());
}
+ void printUnreachableReplacement() {
+ // If we cannot print a valid unreachable instruction (say, a struct.get,
+ // where if the ref is unreachable, we don't know what heap type to print),
+ // then print the children in a block, which is good enough as this
+ // instruction is never reached anyhow.
+ printMedium(o, "block ");
+ }
void visitStructGet(StructGet* curr) {
+ if (curr->ref->type == Type::unreachable) {
+ printUnreachableReplacement();
+ return;
+ }
const auto& field =
curr->ref->type.getHeapType().getStruct().fields[curr->index];
if (field.type == Type::i32 && field.packedType != Field::not_packed) {
@@ -1857,6 +1868,10 @@ struct PrintExpressionContents
o << curr->index;
}
void visitStructSet(StructSet* curr) {
+ if (curr->ref->type == Type::unreachable) {
+ printUnreachableReplacement();
+ return;
+ }
printMedium(o, "struct.set ");
printHeapTypeName(o, curr->ref->type.getHeapType());
o << ' ';
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 6a1b72476..a9a69b244 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2296,6 +2296,14 @@ void FunctionValidator::visitStructGet(StructGet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.get requires gc to be enabled");
+ if (curr->ref->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(curr->ref->type.isStruct(),
+ curr->ref,
+ "struct.get ref must be a struct")) {
+ return;
+ }
const auto& fields = curr->ref->type.getHeapType().getStruct().fields;
shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
auto field = fields[curr->index];
@@ -2315,6 +2323,14 @@ void FunctionValidator::visitStructSet(StructSet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.set requires gc to be enabled");
+ if (curr->ref->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(curr->ref->type.isStruct(),
+ curr->ref,
+ "struct.set ref must be a struct")) {
+ return;
+ }
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");
diff --git a/test/heap-types.wast b/test/heap-types.wast
index 7558e1676..87d751691 100644
--- a/test/heap-types.wast
+++ b/test/heap-types.wast
@@ -226,4 +226,12 @@
)
)
)
+ (func $unreachables
+ (drop
+ (struct.get $struct.A 0 (unreachable))
+ )
+ (drop
+ (struct.set $struct.A 0 (unreachable) (unreachable))
+ )
+ )
)
diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast
index a93bd0d90..458842a7b 100644
--- a/test/heap-types.wast.from-wast
+++ b/test/heap-types.wast.from-wast
@@ -282,4 +282,17 @@
)
)
)
+ (func $unreachables
+ (drop
+ (block
+ (unreachable)
+ )
+ )
+ (drop
+ (block
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
)
diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary
index d8ddb48ed..5e48da116 100644
--- a/test/heap-types.wast.fromBinary
+++ b/test/heap-types.wast.fromBinary
@@ -281,5 +281,8 @@
)
)
)
+ (func $unreachables
+ (unreachable)
+ )
)
diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo
index 63f7e132e..d49d5fa1e 100644
--- a/test/heap-types.wast.fromBinary.noDebugInfo
+++ b/test/heap-types.wast.fromBinary.noDebugInfo
@@ -281,5 +281,8 @@
)
)
)
+ (func $8
+ (unreachable)
+ )
)