From ec1b58ef6433d967b2be0702fbb63dfb52b3b8bd Mon Sep 17 00:00:00 2001 From: pjuftring Date: Wed, 14 Oct 2015 13:18:09 +0200 Subject: [PATCH 1/4] Added store operations to left-to-right.wast I added store operations and adjusted the memory size. I already added the four dummy functions, which will be used to test the evaluation order of functions. --- ml-proto/test/left-to-right.wast | 43 ++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/ml-proto/test/left-to-right.wast b/ml-proto/test/left-to-right.wast index 5a804a8ace..fa649c2317 100644 --- a/ml-proto/test/left-to-right.wast +++ b/ml-proto/test/left-to-right.wast @@ -1,20 +1,22 @@ (module - (memory 1) + (memory 9) ;; The idea is: We reset the memory, then the arithmetic instruction calls $*_left and $*_right. ;; $*_left stores the number 1, and $*_right stores the number 2 (both at address 0) ;; Then we read the value at address 0. If it's 0, the VM did an unwanted optimzation. ;; If it's 1, then $*_right was called before $*_left. If it's 2, then everything's fine. - (func $reset (i32.store8 (i32.const 0)(i32.const 0))) - (func $get (result i32) (i32.load8_u (i32.const 0))) - (func $i32_left (result i32) (i32.store8 (i32.const 0) (i32.const 1)) (i32.const 127)) - (func $i32_right (result i32) (i32.store8 (i32.const 0) (i32.const 2)) (i32.const 141)) - (func $i64_left (result i64) (i32.store8 (i32.const 0) (i32.const 1)) (i64.const 163)) - (func $i64_right (result i64) (i32.store8 (i32.const 0) (i32.const 2)) (i64.const 155)) - (func $f32_left (result f32) (i32.store8 (i32.const 0) (i32.const 1)) (f32.const 124)) - (func $f32_right (result f32) (i32.store8 (i32.const 0) (i32.const 2)) (f32.const 145)) - (func $f64_left (result f64) (i32.store8 (i32.const 0) (i32.const 1)) (f64.const 163)) - (func $f64_right (result f64) (i32.store8 (i32.const 0) (i32.const 2)) (f64.const 164)) + (func $reset (i32.store8 (i32.const 8)(i32.const 0))) + (func $get (result i32) (i32.load8_u (i32.const 8))) + (func $i32_left (result i32) (i32.store8 (i32.const 8) (i32.const 1)) (i32.const 0)) + (func $i32_right (result i32) (i32.store8 (i32.const 8) (i32.const 2)) (i32.const 1)) + (func $i64_left (result i64) (i32.store8 (i32.const 8) (i32.const 1)) (i64.const 0)) + (func $i64_right (result i64) (i32.store8 (i32.const 8) (i32.const 2)) (i64.const 1)) + (func $f32_left (result f32) (i32.store8 (i32.const 8) (i32.const 1)) (f32.const 0)) + (func $f32_right (result f32) (i32.store8 (i32.const 8) (i32.const 2)) (f32.const 1)) + (func $f64_left (result f64) (i32.store8 (i32.const 8) (i32.const 1)) (f64.const 0)) + (func $f64_right (result f64) (i32.store8 (i32.const 8) (i32.const 2)) (f64.const 1)) + (func $i32_dummy (param i32 i32)) (func $i64_dummy (param i64 i64)) + (func $f32_dummy (param f32 f32)) (func $f64_dummy (param f64 f64)) (func $i32_add (result i32) (call $reset) (i32.add (call $i32_left) (call $i32_right)) (call $get)) @@ -40,6 +42,9 @@ (func $i32_ge_s (result i32) (call $reset) (i32.ge_s (call $i32_left) (call $i32_right)) (call $get)) (func $i32_gt_u (result i32) (call $reset) (i32.gt_u (call $i32_left) (call $i32_right)) (call $get)) (func $i32_ge_u (result i32) (call $reset) (i32.ge_u (call $i32_left) (call $i32_right)) (call $get)) + (func $i32_store (result i32) (call $reset) (i32.store (call $i32_left) (call $i32_right)) (call $get)) + (func $i32_store8 (result i32) (call $reset) (i32.store8 (call $i32_left) (call $i32_right)) (call $get)) + (func $i32_store16 (result i32) (call $reset) (i32.store16 (call $i32_left) (call $i32_right)) (call $get)) (func $i64_add (result i32) (call $reset) (i64.add (call $i64_left) (call $i64_right)) (call $get)) (func $i64_sub (result i32) (call $reset) (i64.sub (call $i64_left) (call $i64_right)) (call $get)) @@ -64,6 +69,10 @@ (func $i64_ge_s (result i32) (call $reset) (i64.ge_s (call $i64_left) (call $i64_right)) (call $get)) (func $i64_gt_u (result i32) (call $reset) (i64.gt_u (call $i64_left) (call $i64_right)) (call $get)) (func $i64_ge_u (result i32) (call $reset) (i64.ge_u (call $i64_left) (call $i64_right)) (call $get)) + (func $i64_store (result i32) (call $reset) (i64.store (call $i32_left) (call $i64_right)) (call $get)) + (func $i64_store8 (result i32) (call $reset) (i64.store8 (call $i32_left) (call $i64_right)) (call $get)) + (func $i64_store16 (result i32) (call $reset) (i64.store16 (call $i32_left) (call $i64_right)) (call $get)) + (func $i64_store32 (result i32) (call $reset) (i64.store32 (call $i32_left) (call $i64_right)) (call $get)) (func $f32_add (result i32) (call $reset) (f32.add (call $f32_left) (call $f32_right)) (call $get)) @@ -79,6 +88,7 @@ (func $f32_ge (result i32) (call $reset) (f32.ge (call $f32_left) (call $f32_right)) (call $get)) (func $f32_min (result i32) (call $reset) (f32.min (call $f32_left) (call $f32_right)) (call $get)) (func $f32_max (result i32) (call $reset) (f32.max (call $f32_left) (call $f32_right)) (call $get)) + (func $f32_store (result i32) (call $reset) (f32.store (call $i32_left) (call $f32_right)) (call $get)) (func $f64_add (result i32) (call $reset) (f64.add (call $f64_left) (call $f64_right)) (call $get)) (func $f64_sub (result i32) (call $reset) (f64.sub (call $f64_left) (call $f64_right)) (call $get)) @@ -93,6 +103,7 @@ (func $f64_ge (result i32) (call $reset) (f64.ge (call $f64_left) (call $f64_right)) (call $get)) (func $f64_min (result i32) (call $reset) (f64.min (call $f64_left) (call $f64_right)) (call $get)) (func $f64_max (result i32) (call $reset) (f64.max (call $f64_left) (call $f64_right)) (call $get)) + (func $f64_store (result i32) (call $reset) (f64.store (call $i32_left) (call $f64_right)) (call $get)) (export "i32_add" $i32_add) (export "i64_add" $i64_add) @@ -118,6 +129,10 @@ (export "i32_ge_s" $i32_ge_s) (export "i64_ge_s" $i64_ge_s) (export "i32_gt_u" $i32_gt_u) (export "i64_gt_u" $i64_gt_u) (export "i32_ge_u" $i32_ge_u) (export "i64_ge_u" $i64_ge_u) + (export "i32_store" $i32_store) (export "i64_store" $i64_store) + (export "i32_store8" $i32_store) (export "i64_store8" $i64_store8) + (export "i32_store16" $i32_store) (export "i64_store16" $i64_store16) + (export "i64_store32" $i64_store32) (export "f32_add" $f32_add) (export "f64_add" $f64_add) (export "f32_sub" $f32_sub) (export "f64_sub" $f64_sub) @@ -132,6 +147,7 @@ (export "f32_ge" $f32_ge) (export "f64_ge" $f64_ge) (export "f32_min" $f32_min) (export "f64_min" $f64_min) (export "f32_max" $f32_max) (export "f64_max" $f64_max) + (export "f32_store" $f32_store) (export "f64_store" $f64_store) ) (assert_return (invoke "i32_add") (i32.const 2)) (assert_return (invoke "i64_add") (i32.const 2)) @@ -157,6 +173,10 @@ (assert_return (invoke "i32_ge_s") (i32.const 2)) (assert_return (invoke "i64_ge_s") (i32.const 2)) (assert_return (invoke "i32_gt_u") (i32.const 2)) (assert_return (invoke "i64_gt_u") (i32.const 2)) (assert_return (invoke "i32_ge_u") (i32.const 2)) (assert_return (invoke "i64_ge_u") (i32.const 2)) +(assert_return (invoke "i32_store") (i32.const 2)) (assert_return (invoke "i64_store") (i32.const 2)) +(assert_return (invoke "i32_store8") (i32.const 2)) (assert_return (invoke "i64_store8") (i32.const 2)) +(assert_return (invoke "i32_store16") (i32.const 2)) (assert_return (invoke "i64_store16") (i32.const 2)) +(assert_return (invoke "i64_store32") (i32.const 2)) (assert_return (invoke "f32_add") (i32.const 2)) (assert_return (invoke "f64_add") (i32.const 2)) (assert_return (invoke "f32_sub") (i32.const 2)) (assert_return (invoke "f64_sub") (i32.const 2)) @@ -171,3 +191,4 @@ (assert_return (invoke "f32_ge") (i32.const 2)) (assert_return (invoke "f64_ge") (i32.const 2)) (assert_return (invoke "f32_min") (i32.const 2)) (assert_return (invoke "f64_min") (i32.const 2)) (assert_return (invoke "f32_max") (i32.const 2)) (assert_return (invoke "f64_max") (i32.const 2)) +(assert_return (invoke "f32_store") (i32.const 2)) (assert_return (invoke "f64_store") (i32.const 2)) From 2552d3ec2d1045222fb2c3513b24c299b73a3b3b Mon Sep 17 00:00:00 2001 From: pjuftring Date: Wed, 14 Oct 2015 16:23:16 +0200 Subject: [PATCH 2/4] Fixed typo and added left-to-right tests for calls. --- ml-proto/test/left-to-right.wast | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ml-proto/test/left-to-right.wast b/ml-proto/test/left-to-right.wast index fa649c2317..dc4846e80d 100644 --- a/ml-proto/test/left-to-right.wast +++ b/ml-proto/test/left-to-right.wast @@ -45,6 +45,7 @@ (func $i32_store (result i32) (call $reset) (i32.store (call $i32_left) (call $i32_right)) (call $get)) (func $i32_store8 (result i32) (call $reset) (i32.store8 (call $i32_left) (call $i32_right)) (call $get)) (func $i32_store16 (result i32) (call $reset) (i32.store16 (call $i32_left) (call $i32_right)) (call $get)) + (func $i32_call (result i32) (call $reset) (call $i32_dummy (call $i32_left) (call $i32_right)) (call $get)) (func $i64_add (result i32) (call $reset) (i64.add (call $i64_left) (call $i64_right)) (call $get)) (func $i64_sub (result i32) (call $reset) (i64.sub (call $i64_left) (call $i64_right)) (call $get)) @@ -73,6 +74,7 @@ (func $i64_store8 (result i32) (call $reset) (i64.store8 (call $i32_left) (call $i64_right)) (call $get)) (func $i64_store16 (result i32) (call $reset) (i64.store16 (call $i32_left) (call $i64_right)) (call $get)) (func $i64_store32 (result i32) (call $reset) (i64.store32 (call $i32_left) (call $i64_right)) (call $get)) + (func $i64_call (result i32) (call $reset) (call $i64_dummy (call $i64_left) (call $i64_right)) (call $get)) (func $f32_add (result i32) (call $reset) (f32.add (call $f32_left) (call $f32_right)) (call $get)) @@ -89,6 +91,7 @@ (func $f32_min (result i32) (call $reset) (f32.min (call $f32_left) (call $f32_right)) (call $get)) (func $f32_max (result i32) (call $reset) (f32.max (call $f32_left) (call $f32_right)) (call $get)) (func $f32_store (result i32) (call $reset) (f32.store (call $i32_left) (call $f32_right)) (call $get)) + (func $f32_call (result i32) (call $reset) (call $f32_dummy (call $f32_left) (call $f32_right)) (call $get)) (func $f64_add (result i32) (call $reset) (f64.add (call $f64_left) (call $f64_right)) (call $get)) (func $f64_sub (result i32) (call $reset) (f64.sub (call $f64_left) (call $f64_right)) (call $get)) @@ -104,6 +107,7 @@ (func $f64_min (result i32) (call $reset) (f64.min (call $f64_left) (call $f64_right)) (call $get)) (func $f64_max (result i32) (call $reset) (f64.max (call $f64_left) (call $f64_right)) (call $get)) (func $f64_store (result i32) (call $reset) (f64.store (call $i32_left) (call $f64_right)) (call $get)) + (func $f64_call (result i32) (call $reset) (call $f64_dummy (call $f64_left) (call $f64_right)) (call $get)) (export "i32_add" $i32_add) (export "i64_add" $i64_add) @@ -130,9 +134,10 @@ (export "i32_gt_u" $i32_gt_u) (export "i64_gt_u" $i64_gt_u) (export "i32_ge_u" $i32_ge_u) (export "i64_ge_u" $i64_ge_u) (export "i32_store" $i32_store) (export "i64_store" $i64_store) - (export "i32_store8" $i32_store) (export "i64_store8" $i64_store8) - (export "i32_store16" $i32_store) (export "i64_store16" $i64_store16) + (export "i32_store8" $i32_store8) (export "i64_store8" $i64_store8) + (export "i32_store16" $i32_store16) (export "i64_store16" $i64_store16) (export "i64_store32" $i64_store32) + (export "i32_call" $i32_call) (export "i64_call" $i64_call) (export "f32_add" $f32_add) (export "f64_add" $f64_add) (export "f32_sub" $f32_sub) (export "f64_sub" $f64_sub) @@ -148,6 +153,7 @@ (export "f32_min" $f32_min) (export "f64_min" $f64_min) (export "f32_max" $f32_max) (export "f64_max" $f64_max) (export "f32_store" $f32_store) (export "f64_store" $f64_store) + (export "f32_call" $f32_call) (export "f64_call" $f64_call) ) (assert_return (invoke "i32_add") (i32.const 2)) (assert_return (invoke "i64_add") (i32.const 2)) @@ -177,6 +183,7 @@ (assert_return (invoke "i32_store8") (i32.const 2)) (assert_return (invoke "i64_store8") (i32.const 2)) (assert_return (invoke "i32_store16") (i32.const 2)) (assert_return (invoke "i64_store16") (i32.const 2)) (assert_return (invoke "i64_store32") (i32.const 2)) +(assert_return (invoke "i32_call") (i32.const 2)) (assert_return (invoke "i64_call") (i32.const 2)) (assert_return (invoke "f32_add") (i32.const 2)) (assert_return (invoke "f64_add") (i32.const 2)) (assert_return (invoke "f32_sub") (i32.const 2)) (assert_return (invoke "f64_sub") (i32.const 2)) @@ -192,3 +199,4 @@ (assert_return (invoke "f32_min") (i32.const 2)) (assert_return (invoke "f64_min") (i32.const 2)) (assert_return (invoke "f32_max") (i32.const 2)) (assert_return (invoke "f64_max") (i32.const 2)) (assert_return (invoke "f32_store") (i32.const 2)) (assert_return (invoke "f64_store") (i32.const 2)) +(assert_return (invoke "f32_call") (i32.const 2)) (assert_return (invoke "f64_call") (i32.const 2)) From 788faa0b201e7975a791cb76996186da09b3dcbb Mon Sep 17 00:00:00 2001 From: pjuftring Date: Wed, 14 Oct 2015 16:27:02 +0200 Subject: [PATCH 3/4] Removed second left-to-right test from TestingTodo --- ml-proto/TestingTodo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-proto/TestingTodo.md b/ml-proto/TestingTodo.md index 063fbc64b3..a2c2d42ce0 100644 --- a/ml-proto/TestingTodo.md +++ b/ml-proto/TestingTodo.md @@ -22,7 +22,7 @@ Operator semantics: - ~~test that shifts don't mask their shift count. 32 is particularly nice to test.~~ - test that `page_size` returns a power of 2 - ~~test that arithmetic operands are evaluated left-to-right~~ - - test that call and store operands are evaluated left-to-right too + - ~~test that call and store operands are evaluated left-to-right too~~ - ~~test that add/sub/mul/wrap/wrapping-store silently wrap on overflow~~ - ~~test that sdiv/udiv/srem/urem trap on divide-by-zero~~ - ~~test that sdiv traps on overflow~~ From fde0f8fe65f6d0b87b6f46deb58d34cf78e92af6 Mon Sep 17 00:00:00 2001 From: pjuftring Date: Thu, 15 Oct 2015 19:47:43 +0200 Subject: [PATCH 4/4] Fix indent/comment, add call_indirect to test list I added a space between two brackets, fixed the comment and added a new "test to write" to TestingTodo, which will test the evaluation order of call_indirect --- ml-proto/TestingTodo.md | 1 + ml-proto/test/left-to-right.wast | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ml-proto/TestingTodo.md b/ml-proto/TestingTodo.md index a2c2d42ce0..5e337a9c2f 100644 --- a/ml-proto/TestingTodo.md +++ b/ml-proto/TestingTodo.md @@ -23,6 +23,7 @@ Operator semantics: - test that `page_size` returns a power of 2 - ~~test that arithmetic operands are evaluated left-to-right~~ - ~~test that call and store operands are evaluated left-to-right too~~ + - test that call and argument operands of call_indirect are evaluated left-to-right, too - ~~test that add/sub/mul/wrap/wrapping-store silently wrap on overflow~~ - ~~test that sdiv/udiv/srem/urem trap on divide-by-zero~~ - ~~test that sdiv traps on overflow~~ diff --git a/ml-proto/test/left-to-right.wast b/ml-proto/test/left-to-right.wast index dc4846e80d..93f9100f09 100644 --- a/ml-proto/test/left-to-right.wast +++ b/ml-proto/test/left-to-right.wast @@ -2,10 +2,10 @@ (memory 9) ;; The idea is: We reset the memory, then the arithmetic instruction calls $*_left and $*_right. - ;; $*_left stores the number 1, and $*_right stores the number 2 (both at address 0) - ;; Then we read the value at address 0. If it's 0, the VM did an unwanted optimzation. + ;; $*_left stores the number 1, and $*_right stores the number 2 (both at address 8) + ;; Then we read the value at address 8. If it's 0, the VM did an unwanted optimzation. ;; If it's 1, then $*_right was called before $*_left. If it's 2, then everything's fine. - (func $reset (i32.store8 (i32.const 8)(i32.const 0))) + (func $reset (i32.store8 (i32.const 8) (i32.const 0))) (func $get (result i32) (i32.load8_u (i32.const 8))) (func $i32_left (result i32) (i32.store8 (i32.const 8) (i32.const 1)) (i32.const 0)) (func $i32_right (result i32) (i32.store8 (i32.const 8) (i32.const 2)) (i32.const 1))