summaryrefslogtreecommitdiff
path: root/test/binaryen.js/expressionrunner.js
diff options
context:
space:
mode:
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);