summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-validator.cpp60
-rw-r--r--src/wasm/wasm.cpp10
2 files changed, 69 insertions, 1 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 8098116be..372c5bf6d 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -549,6 +549,10 @@ void FunctionValidator::noteBreak(Name name,
}
void FunctionValidator::visitBreak(Break* curr) {
noteBreak(curr->name, curr->value, curr);
+ if (curr->value) {
+ shouldBeTrue(
+ curr->value->type != none, curr, "break value must not have none type");
+ }
if (curr->condition) {
shouldBeTrue(curr->condition->type == unreachable ||
curr->condition->type == i32,
@@ -593,6 +597,33 @@ void FunctionValidator::visitCall(Call* curr) {
getStream() << "(on argument " << i << ")\n";
}
}
+ if (curr->isReturn) {
+ shouldBeEqual(curr->type,
+ unreachable,
+ curr,
+ "return_call should have unreachable type");
+ shouldBeEqual(
+ getFunction()->result,
+ target->result,
+ curr,
+ "return_call callee return type must match caller return type");
+ } else {
+ if (curr->type == unreachable) {
+ bool hasUnreachableOperand =
+ std::any_of(curr->operands.begin(),
+ curr->operands.end(),
+ [](Expression* op) { return op->type == unreachable; });
+ shouldBeTrue(
+ hasUnreachableOperand,
+ curr,
+ "calls may only be unreachable if they have unreachable operands");
+ } else {
+ shouldBeEqual(curr->type,
+ target->result,
+ curr,
+ "call type must match callee return type");
+ }
+ }
}
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
@@ -622,6 +653,35 @@ void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
getStream() << "(on argument " << i << ")\n";
}
}
+ if (curr->isReturn) {
+ shouldBeEqual(curr->type,
+ unreachable,
+ curr,
+ "return_call_indirect should have unreachable type");
+ shouldBeEqual(
+ getFunction()->result,
+ type->result,
+ curr,
+ "return_call_indirect callee return type must match caller return type");
+ } else {
+ if (curr->type == unreachable) {
+ if (curr->target->type != unreachable) {
+ bool hasUnreachableOperand =
+ std::any_of(curr->operands.begin(),
+ curr->operands.end(),
+ [](Expression* op) { return op->type == unreachable; });
+ shouldBeTrue(hasUnreachableOperand,
+ curr,
+ "call_indirects may only be unreachable if they have "
+ "unreachable operands");
+ }
+ } else {
+ shouldBeEqual(curr->type,
+ type->result,
+ curr,
+ "call_indirect type must match callee return type");
+ }
+ }
}
void FunctionValidator::visitConst(Const* curr) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index d0a916072..04abbcd9f 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -405,10 +405,18 @@ template<typename T> void handleUnreachableOperands(T* curr) {
}
}
-void Call::finalize() { handleUnreachableOperands(this); }
+void Call::finalize() {
+ handleUnreachableOperands(this);
+ if (isReturn) {
+ type = unreachable;
+ }
+}
void CallIndirect::finalize() {
handleUnreachableOperands(this);
+ if (isReturn) {
+ type = unreachable;
+ }
if (target->type == unreachable) {
type = unreachable;
}