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.cpp141
1 files changed, 86 insertions, 55 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 845f0f6b6..318657034 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -22,6 +22,7 @@
#include "ir/eh-utils.h"
#include "ir/features.h"
#include "ir/find_all.h"
+#include "ir/gc-type-utils.h"
#include "ir/global-utils.h"
#include "ir/intrinsics.h"
#include "ir/local-graph.h"
@@ -456,14 +457,18 @@ public:
void visitStructGet(StructGet* curr);
void visitStructSet(StructSet* curr);
void visitArrayNew(ArrayNew* curr);
- void visitArrayNewSeg(ArrayNewSeg* curr);
+ template<typename ArrayNew> void visitArrayNew(ArrayNew* curr);
+ void visitArrayNewData(ArrayNewData* curr);
+ void visitArrayNewElem(ArrayNewElem* curr);
void visitArrayNewFixed(ArrayNewFixed* curr);
void visitArrayGet(ArrayGet* curr);
void visitArraySet(ArraySet* curr);
void visitArrayLen(ArrayLen* curr);
void visitArrayCopy(ArrayCopy* curr);
void visitArrayFill(ArrayFill* curr);
- void visitArrayInit(ArrayInit* curr);
+ template<typename ArrayInit> void visitArrayInit(ArrayInit* curr);
+ void visitArrayInitData(ArrayInitData* curr);
+ void visitArrayInitElem(ArrayInitElem* curr);
void visitFunction(Function* curr);
// helpers
@@ -2703,7 +2708,8 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) {
}
}
-void FunctionValidator::visitArrayNewSeg(ArrayNewSeg* curr) {
+template<typename ArrayNew>
+void FunctionValidator::visitArrayNew(ArrayNew* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"array.new_{data, elem} requires gc [--enable-gc]");
@@ -2717,24 +2723,6 @@ void FunctionValidator::visitArrayNewSeg(ArrayNewSeg* curr) {
Type(Type::i32),
curr,
"array.new_{data, elem} size must be an i32");
- switch (curr->op) {
- case NewData:
- if (!shouldBeTrue(getModule()->getDataSegment(curr->segment),
- curr,
- "array.new_data segment should exist")) {
- return;
- }
- break;
- case NewElem:
- if (!shouldBeTrue(getModule()->getElementSegment(curr->segment),
- curr,
- "array.new_elem segment should exist")) {
- return;
- }
- break;
- default:
- WASM_UNREACHABLE("unexpected op");
- }
if (curr->type == Type::unreachable) {
return;
}
@@ -2748,26 +2736,49 @@ void FunctionValidator::visitArrayNewSeg(ArrayNewSeg* curr) {
if (!shouldBeTrue(
heapType.isArray(),
curr,
- "array.new_{data, elem} type shoudl be an array reference")) {
+ "array.new_{data, elem} type should be an array reference")) {
return;
}
- auto elemType = heapType.getArray().element.type;
- switch (curr->op) {
- case NewData:
- shouldBeTrue(elemType.isNumber(),
- curr,
- "array.new_data result element type should be numeric");
- break;
- case NewElem:
- shouldBeSubType(getModule()->getElementSegment(curr->segment)->type,
- elemType,
- curr,
- "array.new_elem segment type should be a subtype of the "
- "result element type");
- break;
- default:
- WASM_UNREACHABLE("unexpected op");
+}
+
+void FunctionValidator::visitArrayNewData(ArrayNewData* curr) {
+ visitArrayNew(curr);
+
+ if (!shouldBeTrue(getModule()->getDataSegment(curr->segment),
+ curr,
+ "array.new_data segment should exist")) {
+ return;
}
+
+ auto field = GCTypeUtils::getField(curr->type);
+ if (!field) {
+ // A bottom type, or unreachable.
+ return;
+ }
+ shouldBeTrue(field->type.isNumber(),
+ curr,
+ "array.new_data result element type should be numeric");
+}
+
+void FunctionValidator::visitArrayNewElem(ArrayNewElem* curr) {
+ visitArrayNew(curr);
+
+ if (!shouldBeTrue(getModule()->getElementSegment(curr->segment),
+ curr,
+ "array.new_elem segment should exist")) {
+ return;
+ }
+
+ auto field = GCTypeUtils::getField(curr->type);
+ if (!field) {
+ // A bottom type, or unreachable.
+ return;
+ }
+ shouldBeSubType(getModule()->getElementSegment(curr->segment)->type,
+ field->type,
+ curr,
+ "array.new_elem segment type should be a subtype of the "
+ "result element type");
}
void FunctionValidator::visitArrayNewFixed(ArrayNewFixed* curr) {
@@ -2956,6 +2967,7 @@ void FunctionValidator::visitArrayFill(ArrayFill* curr) {
element.mutable_, curr, "array.fill destination must be mutable");
}
+template<typename ArrayInit>
void FunctionValidator::visitArrayInit(ArrayInit* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
@@ -2991,24 +3003,43 @@ void FunctionValidator::visitArrayInit(ArrayInit* curr) {
auto element = heapType.getArray().element;
shouldBeTrue(
element.mutable_, curr, "array.init_* destination must be mutable");
- if (curr->op == InitData) {
- shouldBeTrue(getModule()->getDataSegmentOrNull(curr->segment),
- curr,
- "array.init_data segment must exist");
- shouldBeTrue(element.type.isNumber(),
- curr,
- "array.init_data destination must be numeric");
- } else {
- assert(curr->op == InitElem);
- auto* seg = getModule()->getElementSegmentOrNull(curr->segment);
- if (!shouldBeTrue(seg, curr, "array.init_elem segment must exist")) {
- return;
- }
- shouldBeSubType(seg->type,
- element.type,
- curr,
- "array.init_elem segment type must match destination type");
+}
+
+void FunctionValidator::visitArrayInitData(ArrayInitData* curr) {
+ visitArrayInit(curr);
+
+ shouldBeTrue(getModule()->getDataSegmentOrNull(curr->segment),
+ curr,
+ "array.init_data segment must exist");
+
+ auto field = GCTypeUtils::getField(curr->ref->type);
+ if (!field) {
+ // A bottom type, or unreachable.
+ return;
}
+ shouldBeTrue(field->type.isNumber(),
+ curr,
+ "array.init_data destination must be numeric");
+}
+
+void FunctionValidator::visitArrayInitElem(ArrayInitElem* curr) {
+ visitArrayInit(curr);
+
+ auto* seg = getModule()->getElementSegmentOrNull(curr->segment);
+ if (!shouldBeTrue(seg, curr, "array.init_elem segment must exist")) {
+ return;
+ }
+
+ auto field = GCTypeUtils::getField(curr->ref->type);
+ if (!field) {
+ // A bottom type, or unreachable.
+ return;
+ }
+
+ shouldBeSubType(seg->type,
+ field->type,
+ curr,
+ "array.init_elem segment type must match destination type");
}
void FunctionValidator::visitFunction(Function* curr) {