summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
+ )
+ )
+)
+