diff options
author | Daniel Wirtz <dcode@dcode.io> | 2020-04-20 23:01:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-20 14:01:26 -0700 |
commit | 483d759230f4693abfca3a74a97b1c1db6d2a0d6 (patch) | |
tree | c37b39802b9e5791abb3e329b88ba7185557de49 /test/binaryen.js/expressionrunner.js | |
parent | 1dc820c913712a2c50d05caee77e90a7ec49d2e1 (diff) | |
download | binaryen-483d759230f4693abfca3a74a97b1c1db6d2a0d6.tar.gz binaryen-483d759230f4693abfca3a74a97b1c1db6d2a0d6.tar.bz2 binaryen-483d759230f4693abfca3a74a97b1c1db6d2a0d6.zip |
Refactor expression runner so it can be used via the C and JS APIs (#2702)
Refactors most of the precompute pass's expression runner into its
base class so it can also be used via the C and JS APIs. Also adds
the option to populate the runner with known constant local and global
values upfront, and remembers assigned intermediate values as well
as traversing into functions if requested.
Diffstat (limited to 'test/binaryen.js/expressionrunner.js')
-rw-r--r-- | test/binaryen.js/expressionrunner.js | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/test/binaryen.js/expressionrunner.js b/test/binaryen.js/expressionrunner.js new file mode 100644 index 000000000..35117c453 --- /dev/null +++ b/test/binaryen.js/expressionrunner.js @@ -0,0 +1,208 @@ +var Flags = binaryen.ExpressionRunner.Flags; +console.log("// ExpressionRunner.Flags.Default = " + Flags.Default); +console.log("// ExpressionRunner.Flags.PreserveSideeffects = " + Flags.PreserveSideeffects); +console.log("// ExpressionRunner.Flags.TraverseCalls = " + Flags.TraverseCalls); + +binaryen.setAPITracing(true); + +function assertDeepEqual(x, y) { + if (typeof x === "object") { + for (let i in x) assertDeepEqual(x[i], y[i]); + for (let i in y) assertDeepEqual(x[i], y[i]); + } else { + assert(x === y); + } +} + +var module = new binaryen.Module(); +module.addGlobal("aGlobal", binaryen.i32, true, module.i32.const(0)); + +// Should evaluate down to a constant +var runner = new binaryen.ExpressionRunner(module); +var expr = runner.runAndDispose( + module.i32.add( + module.i32.const(1), + module.i32.const(2) + ) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 3 + } +); + +// Should traverse control structures +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.i32.add( + module.i32.const(1), + module.if( + module.i32.const(0), + module.i32.const(0), + module.i32.const(3) + ) + ), +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 4 + } +); + +// Should be unable to evaluate a local if not explicitly specified +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.i32.add( + module.local.get(0, binaryen.i32), + module.i32.const(1) + ) +); +assert(expr === 0); + +// Should handle traps properly +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.unreachable() +); +assert(expr === 0); + +// Should ignore `local.tee` side-effects if just evaluating the expression +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.i32.add( + module.local.tee(0, module.i32.const(4), binaryen.i32), + module.i32.const(1) + ) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 5 + } +); + +// Should preserve any side-effects if explicitly requested +runner = new binaryen.ExpressionRunner(module, Flags.PreserveSideeffects); +expr = runner.runAndDispose( + module.i32.add( + module.local.tee(0, module.i32.const(4), binaryen.i32), + module.i32.const(1) + ) +); +assert(expr === 0); + +// Should work with temporary values if just evaluating the expression +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.i32.add( + module.block(null, [ + module.local.set(0, module.i32.const(2)), + module.local.get(0, binaryen.i32) + ], binaryen.i32), + module.block(null, [ + module.global.set("aGlobal", module.i32.const(4)), + module.global.get("aGlobal", binaryen.i32) + ], binaryen.i32) + ) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 6 + } +); + +// Should pick up explicitly preset values +runner = new binaryen.ExpressionRunner(module, Flags.PreserveSideeffects); +assert(runner.setLocalValue(0, module.i32.const(3))); +assert(runner.setGlobalValue("aGlobal", module.i32.const(4))); +expr = runner.runAndDispose( + module.i32.add( + module.local.get(0, binaryen.i32), + module.global.get("aGlobal", binaryen.i32) + ) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 7 + } +); + +// Should traverse into (simple) functions if requested +runner = new binaryen.ExpressionRunner(module, Flags.TraverseCalls); +module.addFunction("add", binaryen.createType([ binaryen.i32, binaryen.i32 ]), binaryen.i32, [], + module.block(null, [ + module.i32.add( + module.local.get(0, binaryen.i32), + module.local.get(1, binaryen.i32) + ) + ], binaryen.i32) +); +assert(runner.setLocalValue(0, module.i32.const(1))); +expr = runner.runAndDispose( + module.i32.add( + module.i32.add( + module.local.get(0, binaryen.i32), + module.call("add", [ + module.i32.const(2), + module.i32.const(4) + ], binaryen.i32) + ), + module.local.get(0, binaryen.i32) + ) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 8 + } +); + +// Should not attempt to traverse into functions if not explicitly set +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.i32.add( + module.i32.const(1), + module.call("add", [ + module.i32.const(3), + module.i32.const(4) + ], binaryen.i32) + ) +); +assert(expr === 0); + +// Should stop on maxDepth +runner = new binaryen.ExpressionRunner(module, Flags.Default, 1); +expr = runner.runAndDispose( + module.block(null, [ + module.i32.const(1), + ], binaryen.i32) +); +assert(expr === 0); + +// Should not loop infinitely +runner = new binaryen.ExpressionRunner(module, Flags.Default, 50, 3); +expr = runner.runAndDispose( + module.loop("theLoop", + module.br("theLoop") + ) +); +assert(expr === 0); + +module.dispose(); +binaryen.setAPITracing(false); |