summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-08-06 19:16:20 -0700
committerGitHub <noreply@github.com>2020-08-06 19:16:20 -0700
commit1b102f2ca87d54781b10110c375ea7d0cf5da837 (patch)
treec993c5b8799eed26de19006ef7af6738354e890d
parent449e7a410bdaee17e139c8121cdf125d82a73dff (diff)
downloadbinaryen-1b102f2ca87d54781b10110c375ea7d0cf5da837.tar.gz
binaryen-1b102f2ca87d54781b10110c375ea7d0cf5da837.tar.bz2
binaryen-1b102f2ca87d54781b10110c375ea7d0cf5da837.zip
StubUnsupportedJSOps: Remove CallIndirects (#3027)
wasm2js does not have full call_indirect support as we don't trap if the type is incorrect, which wasm does. Therefore the StubUnsupportedJSOps pass needs to remove those operations so that the fuzzer doesn't find spurious issues.
-rw-r--r--src/passes/RemoveNonJSOps.cpp29
-rw-r--r--test/passes/stub-unsupported-js.txt26
-rw-r--r--test/passes/stub-unsupported-js.wast21
3 files changed, 70 insertions, 6 deletions
diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp
index b89ef60c0..14b4f7a77 100644
--- a/src/passes/RemoveNonJSOps.cpp
+++ b/src/passes/RemoveNonJSOps.cpp
@@ -349,19 +349,36 @@ struct StubUnsupportedJSOpsPass
}
}
+ void visitCallIndirect(CallIndirect* curr) {
+ // Indirect calls of the wrong type trap in wasm, but not in wasm2js. Remove
+ // the indirect call, but leave the arguments.
+ Builder builder(*getModule());
+ std::vector<Expression*> items;
+ for (auto* operand : curr->operands) {
+ items.push_back(builder.makeDrop(operand));
+ }
+ items.push_back(builder.makeDrop(curr->target));
+ stubOut(builder.makeBlock(items), curr->type);
+ }
+
void stubOut(Expression* value, Type outputType) {
Builder builder(*getModule());
+ // In some cases we can just replace with the value.
+ auto* replacement = value;
if (outputType == Type::unreachable) {
// This is unreachable anyhow; just leave the value instead of the
// original node.
assert(value->type == Type::unreachable);
- replaceCurrent(value);
- } else {
- // Drop the value, and return something with the right output type.
- replaceCurrent(
- builder.makeSequence(builder.makeDrop(value),
- LiteralUtils::makeZero(outputType, *getModule())));
+ } else if (outputType != Type::none) {
+ // Drop the value if we need to.
+ if (value->type != Type::none) {
+ value = builder.makeDrop(value);
+ }
+ // Return something with the right output type.
+ replacement = builder.makeSequence(
+ value, LiteralUtils::makeZero(outputType, *getModule()));
}
+ replaceCurrent(replacement);
}
};
diff --git a/test/passes/stub-unsupported-js.txt b/test/passes/stub-unsupported-js.txt
index 531c767c0..784431116 100644
--- a/test/passes/stub-unsupported-js.txt
+++ b/test/passes/stub-unsupported-js.txt
@@ -22,3 +22,29 @@
)
)
)
+(module
+ (type $none_=>_none (func))
+ (type $none_=>_i32 (func (result i32)))
+ (type $none_=>_f32 (func (result f32)))
+ (table $0 2 2 funcref)
+ (elem (i32.const 1) $return-f32)
+ (func $return-f32 (result f32)
+ (f32.const 3.141590118408203)
+ )
+ (func $bad-indirect-call
+ (drop
+ (i32.const 1)
+ )
+ )
+ (func $bad-indirect-call-2 (result i32)
+ (block
+ (drop
+ (i64.const 1234)
+ )
+ (drop
+ (i32.const 1)
+ )
+ )
+ (i32.const 0)
+ )
+)
diff --git a/test/passes/stub-unsupported-js.wast b/test/passes/stub-unsupported-js.wast
index 6cfc7bef2..b68aef64f 100644
--- a/test/passes/stub-unsupported-js.wast
+++ b/test/passes/stub-unsupported-js.wast
@@ -12,3 +12,24 @@
(f32.convert_i32_u (unreachable))
)
)
+(module
+ (type $none_=>_none (func))
+ (type $i64_=>_i32 (func (param $foo i64) (result i32)))
+ (table $0 2 2 funcref)
+ (elem (i32.const 1) $return-f32)
+ (func $return-f32 (result f32)
+ (f32.const 3.14159)
+ )
+ (func $bad-indirect-call
+ (call_indirect (type $none_=>_none) ;; note how it's the wrong type
+ (i32.const 1)
+ )
+ )
+ (func $bad-indirect-call-2 (result i32)
+ (call_indirect (type $i64_=>_i32) ;; note how it's the wrong type
+ (i64.const 1234)
+ (i32.const 1)
+ )
+ )
+)
+