diff options
-rw-r--r-- | src/passes/RemoveNonJSOps.cpp | 29 | ||||
-rw-r--r-- | test/passes/stub-unsupported-js.txt | 26 | ||||
-rw-r--r-- | test/passes/stub-unsupported-js.wast | 21 |
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) + ) + ) +) + |