summaryrefslogtreecommitdiff
path: root/test/binaryen.js/expressionrunner.js
diff options
context:
space:
mode:
authorDaniel Wirtz <dcode@dcode.io>2020-04-20 23:01:26 +0200
committerGitHub <noreply@github.com>2020-04-20 14:01:26 -0700
commit483d759230f4693abfca3a74a97b1c1db6d2a0d6 (patch)
treec37b39802b9e5791abb3e329b88ba7185557de49 /test/binaryen.js/expressionrunner.js
parent1dc820c913712a2c50d05caee77e90a7ec49d2e1 (diff)
downloadbinaryen-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.js208
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);