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.cpp105
1 files changed, 101 insertions, 4 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 73731d3e5..8eb3341de 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -254,6 +254,7 @@ public:
}
void noteBreak(Name name, Expression* value, Expression* curr);
+ void noteBreak(Name name, Type valueType, Expression* curr);
void visitBreak(Break* curr);
void visitSwitch(Switch* curr);
void visitCall(Call* curr);
@@ -284,6 +285,10 @@ public:
void visitDrop(Drop* curr);
void visitReturn(Return* curr);
void visitHost(Host* curr);
+ void visitTry(Try* curr);
+ void visitThrow(Throw* curr);
+ void visitRethrow(Rethrow* curr);
+ void visitBrOnExn(BrOnExn* curr);
void visitFunction(Function* curr);
// helpers
@@ -519,11 +524,15 @@ void FunctionValidator::visitIf(If* curr) {
void FunctionValidator::noteBreak(Name name,
Expression* value,
Expression* curr) {
- Type valueType = none;
- Index arity = 0;
if (value) {
- valueType = value->type;
- shouldBeUnequal(valueType, none, curr, "breaks must have a valid value");
+ shouldBeUnequal(value->type, none, curr, "breaks must have a valid value");
+ }
+ noteBreak(name, value ? value->type : none, curr);
+}
+
+void FunctionValidator::noteBreak(Name name, Type valueType, Expression* curr) {
+ Index arity = 0;
+ if (valueType != none) {
arity = 1;
}
auto iter = breakInfos.find(name);
@@ -1581,6 +1590,94 @@ void FunctionValidator::visitHost(Host* curr) {
}
}
+void FunctionValidator::visitTry(Try* curr) {
+ if (curr->type != unreachable) {
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->body->type,
+ curr->type,
+ curr->body,
+ "try's type does not match try body's type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->catchBody->type,
+ curr->type,
+ curr->catchBody,
+ "try's type does not match catch's body type");
+ }
+ if (isConcreteType(curr->body->type)) {
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->catchBody->type,
+ curr->body->type,
+ curr->catchBody,
+ "try's body type must match catch's body type");
+ }
+ if (isConcreteType(curr->catchBody->type)) {
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->body->type,
+ curr->catchBody->type,
+ curr->body,
+ "try's body type must match catch's body type");
+ }
+}
+
+void FunctionValidator::visitThrow(Throw* curr) {
+ if (!info.validateGlobally) {
+ return;
+ }
+ shouldBeEqual(
+ curr->type, unreachable, curr, "throw's type must be unreachable");
+ auto* event = getModule()->getEventOrNull(curr->event);
+ if (!shouldBeTrue(!!event, curr, "throw's event must exist")) {
+ return;
+ }
+ if (!shouldBeTrue(curr->operands.size() == event->params.size(),
+ curr,
+ "event's param numbers must match")) {
+ return;
+ }
+ for (size_t i = 0; i < curr->operands.size(); i++) {
+ if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type,
+ event->params[i],
+ curr->operands[i],
+ "event param types must match") &&
+ !info.quiet) {
+ getStream() << "(on argument " << i << ")\n";
+ }
+ }
+}
+
+void FunctionValidator::visitRethrow(Rethrow* curr) {
+ shouldBeEqual(
+ curr->type, unreachable, curr, "rethrow's type must be unreachable");
+ shouldBeEqual(curr->exnref->type,
+ exnref,
+ curr->exnref,
+ "rethrow's argument must be exnref type");
+}
+
+void FunctionValidator::visitBrOnExn(BrOnExn* curr) {
+ Event* event = getModule()->getEventOrNull(curr->event);
+ shouldBeTrue(event != nullptr, curr, "br_on_exn's event must exist");
+ shouldBeTrue(event->params == curr->eventParams,
+ curr,
+ "br_on_exn's event params and event's params are different");
+ noteBreak(curr->name, curr->getSingleSentType(), curr);
+ shouldBeTrue(curr->exnref->type == unreachable ||
+ curr->exnref->type == exnref,
+ curr,
+ "br_on_exn's argument must be unreachable or exnref type");
+ if (curr->exnref->type == unreachable) {
+ shouldBeTrue(curr->type == unreachable,
+ curr,
+ "If exnref argument's type is unreachable, br_on_exn should "
+ "be unreachable too");
+ } else {
+ shouldBeTrue(curr->type == exnref,
+ curr,
+ "br_on_exn's type should be exnref unless its exnref argument "
+ "is unreachable");
+ }
+}
+
void FunctionValidator::visitFunction(Function* curr) {
FeatureSet typeFeatures = getFeatures(curr->result);
for (auto type : curr->params) {