diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 60 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 10 |
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; } |