summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2019-07-23 17:12:22 -0700
committerGitHub <noreply@github.com>2019-07-23 17:12:22 -0700
commita2741b360b444a26cd87327a3d60a601bb33119f (patch)
treee7ea331a4236f33c4f8e28b8ef30a8a09ab29740 /src/wasm/wasm-validator.cpp
parent0beba8aad60e4bdadcd3fc3e5126e7befb7b7994 (diff)
downloadbinaryen-a2741b360b444a26cd87327a3d60a601bb33119f.tar.gz
binaryen-a2741b360b444a26cd87327a3d60a601bb33119f.tar.bz2
binaryen-a2741b360b444a26cd87327a3d60a601bb33119f.zip
Finalize tail call support (#2246)
Adds tail call support to fuzzer and makes small changes to handle return calls in multiple utilities and passes. Makes larger changes to DAE and inlining passes to properly handle tail calls.
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp60
1 files changed, 60 insertions, 0 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) {