diff options
author | Alon Zakai <azakai@google.com> | 2020-08-06 19:16:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-06 19:16:20 -0700 |
commit | 1b102f2ca87d54781b10110c375ea7d0cf5da837 (patch) | |
tree | c993c5b8799eed26de19006ef7af6738354e890d | |
parent | 449e7a410bdaee17e139c8121cdf125d82a73dff (diff) | |
download | binaryen-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.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) + ) + ) +) + |