From 8fe48e4a475535e54d052dc42e8e29050ae6de29 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:31:32 +0300 Subject: [PATCH 01/27] feat: i32.and bitwise operation --- src/execution/mod.rs | 19 ++++++++++++++----- src/validation/code.rs | 7 +++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 609f3d86..5d7d0891 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -209,12 +209,21 @@ impl<'b> RuntimeInstance<'b> { } // i32.mul: [i32 i32] -> [i32] 0x6C => { - let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); - let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); - let res = v1.wrapping_mul(v2); + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1.wrapping_mul(v2); + + trace!("Instruction: i32.mul [{v1} {v2}] -> [{res}]"); + stack.push_value(res.into()); + } + // i32.and: [i32 i32] -> [i32] + 0x71 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1 & v2; - trace!("Instruction: i32.mul [{v1} {v2}] -> [{res}]"); - stack.push_value(res.into()); + trace!("Instruction: i32.and [{v1} {v2}] -> [{res}]"); + stack.push_value(res.into()); } other => { trace!("Unknown instruction {other:#x}, skipping.."); diff --git a/src/validation/code.rs b/src/validation/code.rs index 3a32adff..341bda8b 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -181,6 +181,13 @@ fn read_instructions( let _num = wasm.read_var_i32()?; value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.and: [i32 i32] -> [i32] + 0x71 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From a6f34d596beb57ef54ed3d2bfe7e9b85edc10d6c Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:33:36 +0300 Subject: [PATCH 02/27] test: i32.add test case --- tests/arithmetic/bitwise.rs | 26 ++++++++++++++++++++++++++ tests/arithmetic/mod.rs | 1 + 2 files changed, 27 insertions(+) create mode 100644 tests/arithmetic/bitwise.rs diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs new file mode 100644 index 00000000..e0450924 --- /dev/null +++ b/tests/arithmetic/bitwise.rs @@ -0,0 +1,26 @@ +const BASE_WAT: &'static str = r#" + (module + (func (export "template") (param $x i32) (param $y i32) (result i32) + local.get $x + local.get $y + i32.{{0}}) + ) +"#; +/// A simple function to test the i32.and bitwise operation +#[test_log::test] +pub fn i32_bitwise_and() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "and"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(1, instance.invoke_func(0, (33, 11))); + assert_eq!(5, instance.invoke_func(0, (77, 23))); + assert_eq!(180244, instance.invoke_func(0, (192534, 1231412))); + assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX))); +} \ No newline at end of file diff --git a/tests/arithmetic/mod.rs b/tests/arithmetic/mod.rs index 284310a2..fe742f85 100644 --- a/tests/arithmetic/mod.rs +++ b/tests/arithmetic/mod.rs @@ -1 +1,2 @@ +mod bitwise; mod multiply; From 432fbcb418c83ef33458ce5a40f306d7520c2b00 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:51:11 +0300 Subject: [PATCH 03/27] feat: i32.or bitwise operation --- src/execution/mod.rs | 9 +++++++++ src/validation/code.rs | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 5d7d0891..c671fa24 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -225,6 +225,15 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.and [{v1} {v2}] -> [{res}]"); stack.push_value(res.into()); } + // i32.or: [i32 i32] -> [i32] + 0x72 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1 | v2; + + trace!("Instruction: i32.or [{v1} {v2}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 341bda8b..74e36dc6 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -188,6 +188,12 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + 0x72 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From 476bac0f71f4047af5d65898cefd96ca74c95b2d Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:51:38 +0300 Subject: [PATCH 04/27] test: i32.or test case --- tests/arithmetic/bitwise.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index e0450924..d73c9c4b 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -23,4 +23,23 @@ pub fn i32_bitwise_and() { assert_eq!(5, instance.invoke_func(0, (77, 23))); assert_eq!(180244, instance.invoke_func(0, (192534, 1231412))); assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX))); -} \ No newline at end of file +} + +/// A simple function to test the i32.or bitwise operation +#[test_log::test] +pub fn i32_bitwise_or() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "or"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(43, instance.invoke_func(0, (33, 11))); + assert_eq!(95, instance.invoke_func(0, (77, 23))); + assert_eq!(1243702, instance.invoke_func(0, (192534, 1231412))); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); +} From 6a1e413f26a96a4656eac5bdef6a9de5ec5474df Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:53:25 +0300 Subject: [PATCH 05/27] comment: i32.or tag --- src/validation/code.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/validation/code.rs b/src/validation/code.rs index 74e36dc6..e60e9933 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -188,6 +188,7 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.or: [i32 i32] -> [i32] 0x72 => { assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; From b23b17ba8fd14ef9b54be6aab9ae3af46292b821 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:06:41 +0300 Subject: [PATCH 06/27] cargo fmt --- src/execution/mod.rs | 10 +++++----- src/validation/code.rs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index c671fa24..6e89253c 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -227,12 +227,12 @@ impl<'b> RuntimeInstance<'b> { } // i32.or: [i32 i32] -> [i32] 0x72 => { - let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); - let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); - let res = v1 | v2; + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1 | v2; - trace!("Instruction: i32.or [{v1} {v2}] -> [{res}]"); - stack.push_value(res.into()); + trace!("Instruction: i32.or [{v1} {v2}] -> [{res}]"); + stack.push_value(res.into()); } other => { trace!("Unknown instruction {other:#x}, skipping.."); diff --git a/src/validation/code.rs b/src/validation/code.rs index e60e9933..62d25765 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -190,10 +190,10 @@ fn read_instructions( } // i32.or: [i32 i32] -> [i32] 0x72 => { - assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; - assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; - value_stack.push_back(ValType::NumType(NumType::I32)); + value_stack.push_back(ValType::NumType(NumType::I32)); } other => { return Err(Error::InvalidInstr(other)); From 6da367bd4e48d9b39b4bc112cd464de9290d07b8 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:08:37 +0300 Subject: [PATCH 07/27] feat: i32.xor bitwise operation --- src/execution/mod.rs | 9 +++++++++ src/validation/code.rs | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 6e89253c..33e9ef9c 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -234,6 +234,15 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.or [{v1} {v2}] -> [{res}]"); stack.push_value(res.into()); } + // i32.xor: [i32 i32] -> [i32] + 0x73 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1 ^ v2; + + trace!("Instruction: i32.xor [{v1} {v2}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 62d25765..26560a67 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -195,6 +195,13 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.xor: [i32 i32] -> [i32] + 0x73 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From 86f89e208e9f1dd32b16f2931fa0d250d0ce5a0f Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:08:52 +0300 Subject: [PATCH 08/27] test: i32.xor test case --- tests/arithmetic/bitwise.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index d73c9c4b..25832c4d 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -43,3 +43,22 @@ pub fn i32_bitwise_or() { assert_eq!(1243702, instance.invoke_func(0, (192534, 1231412))); assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); } + +/// A simple function to test the i32.xor bitwise operation +#[test_log::test] +pub fn i32_bitwise_xor() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "xor"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(42, instance.invoke_func(0, (33, 11))); + assert_eq!(90, instance.invoke_func(0, (77, 23))); + assert_eq!(1063458, instance.invoke_func(0, (192534, 1231412))); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); +} From b0f5c9e56a3fd304f814312e05aad780d1503068 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:21:31 +0300 Subject: [PATCH 09/27] feat: i32.shl bitwise operation --- src/execution/mod.rs | 9 +++++++++ src/validation/code.rs | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 33e9ef9c..3fc85817 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -243,6 +243,15 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.xor [{v1} {v2}] -> [{res}]"); stack.push_value(res.into()); } + // i32.shl: [i32 i32] -> [i32] + 0x74 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v2.wrapping_shl(v1 as u32); + + trace!("Instruction: i32.shl [{v2} {v1}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 26560a67..00ba7a2d 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -202,6 +202,13 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.shl: [i32 i32] -> [i32] + 0x74 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From 575c0a778321407de76664f48f57179d1c977f26 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:21:42 +0300 Subject: [PATCH 10/27] test: i32.shl test case --- tests/arithmetic/bitwise.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 25832c4d..389716d5 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -62,3 +62,22 @@ pub fn i32_bitwise_xor() { assert_eq!(1063458, instance.invoke_func(0, (192534, 1231412))); assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); } + +/// A simple function to test the i32.shl bitwise operation +#[test_log::test] +pub fn i32_bitwise_shl() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "shl"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(67584, instance.invoke_func(0, (33, 11))); + assert_eq!(645922816, instance.invoke_func(0, (77, 23))); + assert_eq!(23068672, instance.invoke_func(0, (192534, 1231412))); + assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX))); +} From 593572a7646626257ebefa409b66c41e11551a60 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:02:05 +0300 Subject: [PATCH 11/27] feature: i32.shr_s bitwise operation --- src/execution/mod.rs | 10 ++++++++++ src/validation/code.rs | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 3fc85817..873e1444 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -252,6 +252,16 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.shl [{v2} {v1}] -> [{res}]"); stack.push_value(res.into()); } + // i32.shr_s: [i32 i32] -> [i32] + 0x75 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + + let res = v2.wrapping_shr(v1 as u32); + + trace!("Instruction: i32.shr_s [{v2} {v1}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 00ba7a2d..13813fe9 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -209,6 +209,13 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.shr_s: [i32 i32] -> [i32] + 0x75 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From 4a86371cf8dde115aff6773e9e42c032a66c3e40 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:12:55 +0300 Subject: [PATCH 12/27] test: i32.shr_s test case --- tests/arithmetic/bitwise.rs | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 389716d5..6fc8f368 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -81,3 +81,53 @@ pub fn i32_bitwise_shl() { assert_eq!(23068672, instance.invoke_func(0, (192534, 1231412))); assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX))); } + +/// A simple function to test the i32.shr_s bitwise operation +#[test_log::test] +pub fn i32_bitwise_shr_s() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "shr_s"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(8881445, instance.invoke_func(0, (142_103_123, 4))); + assert_eq!(23879, instance.invoke_func(0, (391_248_921, 14))); + assert_eq!(601955006, instance.invoke_func(0, (1_203_910_012, 33))); + assert_eq!(1056594615, instance.invoke_func(0, (2_113_189_231, 33))); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + + // Basic positive number + assert_eq!(4, instance.invoke_func(0, (8, 1))); + + // Shifting by 0 (no shift) + assert_eq!(-1, instance.invoke_func(0, (-1, 0))); + assert_eq!(1, instance.invoke_func(0, (1, 0))); + + // Shifting negative numbers + assert_eq!(-4, instance.invoke_func(0, (-8, 1))); + assert_eq!(-1, instance.invoke_func(0, (-1, 1))); + + // Shifting by 31 (maximum shift for 32-bit int) + assert_eq!(-1, instance.invoke_func(0, (-1, 31))); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, 31))); + assert_eq!(0, instance.invoke_func(0, (i32::MAX, 31))); + + // Shifting by more than 31 + assert_eq!(-1, instance.invoke_func(0, (-1, 32))); + assert_eq!(1, instance.invoke_func(0, (1, 32))); + assert_eq!(-1, instance.invoke_func(0, (-1, 100))); + + // Minimum and maximum 32-bit integers + assert_eq!(i32::MIN / 2, instance.invoke_func(0, (i32::MIN, 1))); + assert_eq!(i32::MAX / 2, instance.invoke_func(0, (i32::MAX, 1))); + + // Shifting out all bits except sign + assert_eq!(-2, instance.invoke_func(0, (i32::MIN, 30))); + assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30))); + // assert_eq!(, instance.invoke_func(0, (,))); +} From 72c0b654207fb5c127c8747688f383f41070a7c3 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:15:01 +0300 Subject: [PATCH 13/27] feat: i32.shr_u bitwise operation --- src/execution/mod.rs | 10 ++++++++++ src/validation/code.rs | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 873e1444..82a9651c 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -262,6 +262,16 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.shr_s [{v2} {v1}] -> [{res}]"); stack.push_value(res.into()); } + // i32.shr_u: [i32 i32] -> [i32] + 0x76 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + + let res = (v2 as u32).wrapping_shr(v1 as u32) as i32; + + trace!("Instruction: i32.shr_u [{v2} {v1}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 13813fe9..2d5bbe2e 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -216,6 +216,13 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.shr_u: [i32 i32] -> [i32] + 0x76 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From 7c819c228ae45aef7551260fbf8f834814baede1 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:17:35 +0300 Subject: [PATCH 14/27] test: i32.shr_u test case --- tests/arithmetic/bitwise.rs | 53 ++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 6fc8f368..475118c1 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -129,5 +129,56 @@ pub fn i32_bitwise_shr_s() { // Shifting out all bits except sign assert_eq!(-2, instance.invoke_func(0, (i32::MIN, 30))); assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30))); - // assert_eq!(, instance.invoke_func(0, (,))); +} + +/// A simple function to test the i32.shr_u bitwise operation +#[test_log::test] +pub fn i32_bitwise_shr_u() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "shr_u"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(8881445, instance.invoke_func(0, (142_103_123, 4))); + assert_eq!(23879, instance.invoke_func(0, (391_248_921, 14))); + assert_eq!(601955006, instance.invoke_func(0, (1_203_910_012, 33))); + assert_eq!(1056594615, instance.invoke_func(0, (2_113_189_231, 33))); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + + // Basic positive number + assert_eq!(4, instance.invoke_func(0, (8, 1))); + + // Shifting by 0 (no shift) + assert_eq!(-1, instance.invoke_func(0, (-1, 0))); + assert_eq!(1, instance.invoke_func(0, (1, 0))); + + // Shifting negative numbers + assert_eq!(i32::MAX - 3, instance.invoke_func(0, (-8, 1))); + assert_eq!(i32::MAX, instance.invoke_func(0, (-1, 1))); + + // Shifting by 31 (maximum shift for 32-bit int) + assert_eq!(1, instance.invoke_func(0, (-1, 31))); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, 31))); + assert_eq!(0, instance.invoke_func(0, (i32::MAX, 31))); + + // Shifting by more than 31 + assert_eq!(-1, instance.invoke_func(0, (-1, 32))); + assert_eq!(1, instance.invoke_func(0, (1, 32))); + assert_eq!(268435455, instance.invoke_func(0, (-1, 100))); + + // Minimum and maximum 32-bit integers + assert_eq!( + (i32::MIN / 2) * (-1), + instance.invoke_func(0, (i32::MIN, 1)) + ); + assert_eq!(i32::MAX / 2, instance.invoke_func(0, (i32::MAX, 1))); + + // Shifting out all bits except sign + assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30))); + assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30))); } From 3af360141ff5f2fb0ef98f4eb59266bb802e99a3 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:15:09 +0300 Subject: [PATCH 15/27] feat: i32.rotl bitwise operation --- src/execution/mod.rs | 10 ++++++++++ src/validation/code.rs | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 82a9651c..cbfc8166 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -272,6 +272,16 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.shr_u [{v2} {v1}] -> [{res}]"); stack.push_value(res.into()); } + // i32.rotl: [i32 i32] -> [i32] + 0x77 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + + let res = v2.rotate_left(v1 as u32); + + trace!("Instruction: i32.rotl [{v2} {v1}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 2d5bbe2e..894f9a14 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -223,6 +223,13 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.rotl: [i32 i32] -> [i32] + 0x77 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From 35b39da02609c9d35468ea5b1289ee4fd49d4e53 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:15:27 +0300 Subject: [PATCH 16/27] test: i32.rotl test case --- tests/arithmetic/bitwise.rs | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 475118c1..2f338d78 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -182,3 +182,52 @@ pub fn i32_bitwise_shr_u() { assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30))); assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30))); } + +/// A simple function to test the i32.rotl bitwise operation +#[test_log::test] +pub fn i32_bitwise_rotl() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "rotl"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(-2021317328, instance.invoke_func(0, (142_103_123, 4))); + assert_eq!(2131117524, instance.invoke_func(0, (391_248_921, 14))); + assert_eq!(-1887147272, instance.invoke_func(0, (1_203_910_012, 33))); + assert_eq!(-68588834, instance.invoke_func(0, (2_113_189_231, 33))); + assert_eq!(1073741824, instance.invoke_func(0, (i32::MIN, i32::MAX))); + + // Basic positive number + assert_eq!(16, instance.invoke_func(0, (8, 1))); + + // Rotating by 0 (no shift) + assert_eq!(-1, instance.invoke_func(0, (-1, 0))); + assert_eq!(1, instance.invoke_func(0, (1, 0))); + + // Shifting negative numbers + assert_eq!(-15, instance.invoke_func(0, (-8, 1))); + assert_eq!(-1, instance.invoke_func(0, (-1, 1))); + + // Rotating by 31 + assert_eq!(-1, instance.invoke_func(0, (-1, 31))); + assert_eq!(i32::MAX / 2 + 1, instance.invoke_func(0, (i32::MIN, 31))); + assert_eq!(i32::MIN / 2 - 1, instance.invoke_func(0, (i32::MAX, 31))); + + // Rotating by more than 31 + assert_eq!(-1, instance.invoke_func(0, (-1, 32))); + assert_eq!(1, instance.invoke_func(0, (1, 32))); + assert_eq!(-1, instance.invoke_func(0, (-1, 100))); + + // Minimum and maximum 32-bit integers + assert_eq!(1, instance.invoke_func(0, (i32::MIN, 1))); + assert_eq!(-2, instance.invoke_func(0, (i32::MAX, 1))); + + // Shifting out all bits except sign + assert_eq!(i32::MAX / 4 + 1, instance.invoke_func(0, (i32::MIN, 30))); + assert_eq!(i32::MIN / 4 - 1, instance.invoke_func(0, (i32::MAX, 30))); +} From b980739b43583778d45d1c9006cbd3206eca566e Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:21:25 +0300 Subject: [PATCH 17/27] feat: i32.rotr bitwise operation --- src/execution/mod.rs | 10 ++++++++++ src/validation/code.rs | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index cbfc8166..d68fc5f3 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -282,6 +282,16 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.rotl [{v2} {v1}] -> [{res}]"); stack.push_value(res.into()); } + // i32.rotr: [i32 i32] -> [i32] + 0x78 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let v2: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + + let res = v2.rotate_right(v1 as u32); + + trace!("Instruction: i32.rotr [{v2} {v1}] -> [{res}]"); + stack.push_value(res.into()); + } other => { trace!("Unknown instruction {other:#x}, skipping.."); } diff --git a/src/validation/code.rs b/src/validation/code.rs index 894f9a14..1d99797f 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -230,6 +230,13 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.rotr: [i32 i32] -> [i32] + 0x78 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } other => { return Err(Error::InvalidInstr(other)); } From ef6c23787c6df0ccfd31a73fd66d850d6253522a Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:22:12 +0300 Subject: [PATCH 18/27] test: i32.rotr test case --- tests/arithmetic/bitwise.rs | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 2f338d78..a84a5e10 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -231,3 +231,52 @@ pub fn i32_bitwise_rotl() { assert_eq!(i32::MAX / 4 + 1, instance.invoke_func(0, (i32::MIN, 30))); assert_eq!(i32::MIN / 4 - 1, instance.invoke_func(0, (i32::MAX, 30))); } + +/// A simple function to test the i32.rotr bitwise operation +#[test_log::test] +pub fn i32_bitwise_rotr() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_WAT).replace("{{0}}", "rotr"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(814187813, instance.invoke_func(0, (142_103_123, 4))); + assert_eq!(-261857977, instance.invoke_func(0, (391_248_921, 14))); + assert_eq!(601955006, instance.invoke_func(0, (1_203_910_012, 33))); + assert_eq!(-1090889033, instance.invoke_func(0, (2_113_189_231, 33))); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + + // Basic positive number + assert_eq!(4, instance.invoke_func(0, (8, 1))); + + // Rotating by 0 (no shift) + assert_eq!(-1, instance.invoke_func(0, (-1, 0))); + assert_eq!(1, instance.invoke_func(0, (1, 0))); + + // Shifting negative numbers + assert_eq!(i32::MAX - 3, instance.invoke_func(0, (-8, 1))); + assert_eq!(-1, instance.invoke_func(0, (-1, 1))); + + // Rotating by 31 + assert_eq!(-1, instance.invoke_func(0, (-1, 31))); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, 31))); + assert_eq!(-2, instance.invoke_func(0, (i32::MAX, 31))); + + // Rotating by more than 31 + assert_eq!(-1, instance.invoke_func(0, (-1, 32))); + assert_eq!(1, instance.invoke_func(0, (1, 32))); + assert_eq!(-1, instance.invoke_func(0, (-1, 100))); + + // Minimum and maximum 32-bit integers + assert_eq!(i32::MAX / 2 + 1, instance.invoke_func(0, (i32::MIN, 1))); + assert_eq!(i32::MIN / 2 - 1, instance.invoke_func(0, (i32::MAX, 1))); + + // Shifting out all bits except sign + assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30))); + assert_eq!(-3, instance.invoke_func(0, (i32::MAX, 30))); +} From e2ab07d3632641a25d4b11455fc35bfebd06ac1c Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:34:43 +0300 Subject: [PATCH 19/27] feat: i32.clz bitwise operation --- src/execution/mod.rs | 8 ++++++++ src/validation/code.rs | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index d68fc5f3..4d30bcb5 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -198,6 +198,14 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.const [] -> [{constant}]"); stack.push_value(constant.into()); } + // i32.clz: [i32] -> [i32] + 0x67 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1.leading_zeros() as i32; + + trace!("Instruction: i32.clz [{v1}] -> [{res}]"); + stack.push_value(res.into()); + } // i32.add: [i32 i32] -> [i32] 0x6A => { let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); diff --git a/src/validation/code.rs b/src/validation/code.rs index 1d99797f..530934b2 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -181,6 +181,12 @@ fn read_instructions( let _num = wasm.read_var_i32()?; value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.clz: [i32] -> [i32] + 0x67 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } // i32.and: [i32 i32] -> [i32] 0x71 => { assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; From 205656fd6dedef9671a73b692cd98a711865bf42 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:38:18 +0300 Subject: [PATCH 20/27] test: i32.clz test case --- tests/arithmetic/bitwise.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index a84a5e10..08977986 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -280,3 +280,32 @@ pub fn i32_bitwise_rotr() { assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30))); assert_eq!(-3, instance.invoke_func(0, (i32::MAX, 30))); } + +const BASE_COUNT_WAT: &'static str = r#" + (module + (func (export "template") (param $x i32) (result i32) + local.get $x + i32.{{0}}) + ) +"#; + +/// A simple function to test the i32.clz bitwise operation +#[test_log::test] +pub fn i32_bitwise_clz() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_COUNT_WAT).replace("{{0}}", "clz"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(26, instance.invoke_func(0, 33)); + assert_eq!(25, instance.invoke_func(0, 77)); + assert_eq!(14, instance.invoke_func(0, 192534)); + assert_eq!(0, instance.invoke_func(0, i32::MIN)); + assert_eq!(1, instance.invoke_func(0, i32::MAX)); + assert_eq!(32, instance.invoke_func(0, 0)); +} From 6ab7b707bab42565fb8eb9aee63696edc4c54850 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:15:28 +0300 Subject: [PATCH 21/27] feat: i32.ctz bitwise operation --- src/execution/mod.rs | 8 ++++++++ src/validation/code.rs | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 4d30bcb5..25f84f75 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -206,6 +206,14 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.clz [{v1}] -> [{res}]"); stack.push_value(res.into()); } + // i32.ctz: [i32] -> [i32] + 0x68 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1.trailing_zeros() as i32; + + trace!("Instruction: i32.ctz [{v1}] -> [{res}]"); + stack.push_value(res.into()); + } // i32.add: [i32 i32] -> [i32] 0x6A => { let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); diff --git a/src/validation/code.rs b/src/validation/code.rs index 530934b2..bb07adcc 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -187,6 +187,12 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.ctz: [i32] -> [i32] + 0x68 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } // i32.and: [i32 i32] -> [i32] 0x71 => { assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; From aeb2e64eb317b6007bc85c98f9defb67f4029200 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:15:40 +0300 Subject: [PATCH 22/27] test: i32.ctz test case --- tests/arithmetic/bitwise.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 08977986..4c571eb8 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -309,3 +309,24 @@ pub fn i32_bitwise_clz() { assert_eq!(1, instance.invoke_func(0, i32::MAX)); assert_eq!(32, instance.invoke_func(0, 0)); } + +/// A simple function to test the i32.ctz bitwise operation +#[test_log::test] +pub fn i32_bitwise_ctz() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_COUNT_WAT).replace("{{0}}", "ctz"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(0, instance.invoke_func(0, 33)); + assert_eq!(0, instance.invoke_func(0, 77)); + assert_eq!(1, instance.invoke_func(0, 192534)); + assert_eq!(31, instance.invoke_func(0, i32::MIN)); + assert_eq!(0, instance.invoke_func(0, i32::MAX)); + assert_eq!(32, instance.invoke_func(0, 0)); +} From 0d0d59880f95bde9dcdfaf9a14456080b9b6cbdb Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:19:18 +0300 Subject: [PATCH 23/27] feat: i32.popcnt bitwise operation --- src/execution/mod.rs | 8 ++++++++ src/validation/code.rs | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 25f84f75..57b154b5 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -214,6 +214,14 @@ impl<'b> RuntimeInstance<'b> { trace!("Instruction: i32.ctz [{v1}] -> [{res}]"); stack.push_value(res.into()); } + // i32.popcnt: [i32] -> [i32] + 0x69 => { + let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); + let res = v1.count_ones() as i32; + + trace!("Instruction: i32.popcnt [{v1}] -> [{res}]"); + stack.push_value(res.into()); + } // i32.add: [i32 i32] -> [i32] 0x6A => { let v1: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); diff --git a/src/validation/code.rs b/src/validation/code.rs index bb07adcc..600fc9b3 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -193,6 +193,12 @@ fn read_instructions( value_stack.push_back(ValType::NumType(NumType::I32)); } + // i32.popcnt: [i32] -> [i32] + 0x69 => { + assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; + + value_stack.push_back(ValType::NumType(NumType::I32)); + } // i32.and: [i32 i32] -> [i32] 0x71 => { assert_pop_value_stack(value_stack, ValType::NumType(NumType::I32))?; From eef65f01b4a2fa2cff560b1bbd5767472099e283 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:19:37 +0300 Subject: [PATCH 24/27] test: i32.popcnt test case --- tests/arithmetic/bitwise.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 4c571eb8..7bd69908 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -330,3 +330,24 @@ pub fn i32_bitwise_ctz() { assert_eq!(0, instance.invoke_func(0, i32::MAX)); assert_eq!(32, instance.invoke_func(0, 0)); } + +/// A simple function to test the i32.popcnt bitwise operation +#[test_log::test] +pub fn i32_bitwise_popcnt() { + use wasm::{validate, RuntimeInstance}; + + let wat = String::from(BASE_COUNT_WAT).replace("{{0}}", "popcnt"); + + let wasm_bytes = wat::parse_str(wat).unwrap(); + + let validation_info = validate(&wasm_bytes).expect("validation failed"); + + let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); + + assert_eq!(2, instance.invoke_func(0, 33)); + assert_eq!(4, instance.invoke_func(0, 77)); + assert_eq!(8, instance.invoke_func(0, 192534)); + assert_eq!(1, instance.invoke_func(0, i32::MIN)); + assert_eq!(31, instance.invoke_func(0, i32::MAX)); + assert_eq!(0, instance.invoke_func(0, 0)); +} From ad91b3d88a97d5f69766c1a95c749f96310f1b96 Mon Sep 17 00:00:00 2001 From: Nero <46645625+nerodesu017@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:09:57 +0300 Subject: [PATCH 25/27] fix: added closing bracket --- src/execution/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 0dcdcf78..302d6119 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -318,6 +318,7 @@ impl<'b> RuntimeInstance<'b> { let res = v2.rotate_right(v1 as u32); trace!("Instruction: i32.rotr [{v2} {v1}] -> [{res}]"); + } // i32.div_s: [i32 i32] -> [i32] 0x6D => { let dividend: i32 = stack.pop_value(ValType::NumType(NumType::I32)).into(); From 37aad3fe9ed43c506b760699e87dac19c243d7a4 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:38:02 +0300 Subject: [PATCH 26/27] fix: fixed rotr --- src/execution/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 302d6119..d02f30aa 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -318,6 +318,7 @@ impl<'b> RuntimeInstance<'b> { let res = v2.rotate_right(v1 as u32); trace!("Instruction: i32.rotr [{v2} {v1}] -> [{res}]"); + stack.push_value(res.into()); } // i32.div_s: [i32 i32] -> [i32] 0x6D => { From ead749d1b05f1da335b2743f1b81d5b631a6f566 Mon Sep 17 00:00:00 2001 From: nerodesu017 <46645625+nerodesu017@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:38:20 +0300 Subject: [PATCH 27/27] fix: bitwise test cases --- tests/arithmetic/bitwise.rs | 297 ++++++++++++++++++++++-------------- 1 file changed, 183 insertions(+), 114 deletions(-) diff --git a/tests/arithmetic/bitwise.rs b/tests/arithmetic/bitwise.rs index 7bd69908..c48df4d3 100644 --- a/tests/arithmetic/bitwise.rs +++ b/tests/arithmetic/bitwise.rs @@ -19,10 +19,10 @@ pub fn i32_bitwise_and() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(1, instance.invoke_func(0, (33, 11))); - assert_eq!(5, instance.invoke_func(0, (77, 23))); - assert_eq!(180244, instance.invoke_func(0, (192534, 1231412))); - assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!(1, instance.invoke_func(0, (33, 11)).unwrap()); + assert_eq!(5, instance.invoke_func(0, (77, 23)).unwrap()); + assert_eq!(180244, instance.invoke_func(0, (192534, 1231412)).unwrap()); + assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); } /// A simple function to test the i32.or bitwise operation @@ -38,10 +38,10 @@ pub fn i32_bitwise_or() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(43, instance.invoke_func(0, (33, 11))); - assert_eq!(95, instance.invoke_func(0, (77, 23))); - assert_eq!(1243702, instance.invoke_func(0, (192534, 1231412))); - assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!(43, instance.invoke_func(0, (33, 11)).unwrap()); + assert_eq!(95, instance.invoke_func(0, (77, 23)).unwrap()); + assert_eq!(1243702, instance.invoke_func(0, (192534, 1231412)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); } /// A simple function to test the i32.xor bitwise operation @@ -57,10 +57,10 @@ pub fn i32_bitwise_xor() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(42, instance.invoke_func(0, (33, 11))); - assert_eq!(90, instance.invoke_func(0, (77, 23))); - assert_eq!(1063458, instance.invoke_func(0, (192534, 1231412))); - assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!(42, instance.invoke_func(0, (33, 11)).unwrap()); + assert_eq!(90, instance.invoke_func(0, (77, 23)).unwrap()); + assert_eq!(1063458, instance.invoke_func(0, (192534, 1231412)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); } /// A simple function to test the i32.shl bitwise operation @@ -76,10 +76,13 @@ pub fn i32_bitwise_shl() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(67584, instance.invoke_func(0, (33, 11))); - assert_eq!(645922816, instance.invoke_func(0, (77, 23))); - assert_eq!(23068672, instance.invoke_func(0, (192534, 1231412))); - assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!(67584, instance.invoke_func(0, (33, 11)).unwrap()); + assert_eq!(645922816, instance.invoke_func(0, (77, 23)).unwrap()); + assert_eq!( + 23068672, + instance.invoke_func(0, (192534, 1231412)).unwrap() + ); + assert_eq!(0, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); } /// A simple function to test the i32.shr_s bitwise operation @@ -95,40 +98,52 @@ pub fn i32_bitwise_shr_s() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(8881445, instance.invoke_func(0, (142_103_123, 4))); - assert_eq!(23879, instance.invoke_func(0, (391_248_921, 14))); - assert_eq!(601955006, instance.invoke_func(0, (1_203_910_012, 33))); - assert_eq!(1056594615, instance.invoke_func(0, (2_113_189_231, 33))); - assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!(8881445, instance.invoke_func(0, (142_103_123, 4)).unwrap()); + assert_eq!(23879, instance.invoke_func(0, (391_248_921, 14)).unwrap()); + assert_eq!( + 601955006, + instance.invoke_func(0, (1_203_910_012, 33)).unwrap() + ); + assert_eq!( + 1056594615, + instance.invoke_func(0, (2_113_189_231, 33)).unwrap() + ); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); // Basic positive number - assert_eq!(4, instance.invoke_func(0, (8, 1))); + assert_eq!(4, instance.invoke_func(0, (8, 1)).unwrap()); // Shifting by 0 (no shift) - assert_eq!(-1, instance.invoke_func(0, (-1, 0))); - assert_eq!(1, instance.invoke_func(0, (1, 0))); + assert_eq!(-1, instance.invoke_func(0, (-1, 0)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 0)).unwrap()); // Shifting negative numbers - assert_eq!(-4, instance.invoke_func(0, (-8, 1))); - assert_eq!(-1, instance.invoke_func(0, (-1, 1))); + assert_eq!(-4, instance.invoke_func(0, (-8, 1)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (-1, 1)).unwrap()); // Shifting by 31 (maximum shift for 32-bit int) - assert_eq!(-1, instance.invoke_func(0, (-1, 31))); - assert_eq!(-1, instance.invoke_func(0, (i32::MIN, 31))); - assert_eq!(0, instance.invoke_func(0, (i32::MAX, 31))); + assert_eq!(-1, instance.invoke_func(0, (-1, 31)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (i32::MIN, 31)).unwrap()); + assert_eq!(0, instance.invoke_func(0, (i32::MAX, 31)).unwrap()); // Shifting by more than 31 - assert_eq!(-1, instance.invoke_func(0, (-1, 32))); - assert_eq!(1, instance.invoke_func(0, (1, 32))); - assert_eq!(-1, instance.invoke_func(0, (-1, 100))); + assert_eq!(-1, instance.invoke_func(0, (-1, 32)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 32)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (-1, 100)).unwrap()); // Minimum and maximum 32-bit integers - assert_eq!(i32::MIN / 2, instance.invoke_func(0, (i32::MIN, 1))); - assert_eq!(i32::MAX / 2, instance.invoke_func(0, (i32::MAX, 1))); + assert_eq!( + i32::MIN / 2, + instance.invoke_func(0, (i32::MIN, 1)).unwrap() + ); + assert_eq!( + i32::MAX / 2, + instance.invoke_func(0, (i32::MAX, 1)).unwrap() + ); // Shifting out all bits except sign - assert_eq!(-2, instance.invoke_func(0, (i32::MIN, 30))); - assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30))); + assert_eq!(-2, instance.invoke_func(0, (i32::MIN, 30)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30)).unwrap()); } /// A simple function to test the i32.shr_u bitwise operation @@ -144,43 +159,52 @@ pub fn i32_bitwise_shr_u() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(8881445, instance.invoke_func(0, (142_103_123, 4))); - assert_eq!(23879, instance.invoke_func(0, (391_248_921, 14))); - assert_eq!(601955006, instance.invoke_func(0, (1_203_910_012, 33))); - assert_eq!(1056594615, instance.invoke_func(0, (2_113_189_231, 33))); - assert_eq!(1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!(8881445, instance.invoke_func(0, (142_103_123, 4)).unwrap()); + assert_eq!(23879, instance.invoke_func(0, (391_248_921, 14)).unwrap()); + assert_eq!( + 601955006, + instance.invoke_func(0, (1_203_910_012, 33)).unwrap() + ); + assert_eq!( + 1056594615, + instance.invoke_func(0, (2_113_189_231, 33)).unwrap() + ); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); // Basic positive number - assert_eq!(4, instance.invoke_func(0, (8, 1))); + assert_eq!(4, instance.invoke_func(0, (8, 1)).unwrap()); // Shifting by 0 (no shift) - assert_eq!(-1, instance.invoke_func(0, (-1, 0))); - assert_eq!(1, instance.invoke_func(0, (1, 0))); + assert_eq!(-1, instance.invoke_func(0, (-1, 0)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 0)).unwrap()); // Shifting negative numbers - assert_eq!(i32::MAX - 3, instance.invoke_func(0, (-8, 1))); - assert_eq!(i32::MAX, instance.invoke_func(0, (-1, 1))); + assert_eq!(i32::MAX - 3, instance.invoke_func(0, (-8, 1)).unwrap()); + assert_eq!(i32::MAX, instance.invoke_func(0, (-1, 1)).unwrap()); // Shifting by 31 (maximum shift for 32-bit int) - assert_eq!(1, instance.invoke_func(0, (-1, 31))); - assert_eq!(1, instance.invoke_func(0, (i32::MIN, 31))); - assert_eq!(0, instance.invoke_func(0, (i32::MAX, 31))); + assert_eq!(1, instance.invoke_func(0, (-1, 31)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, 31)).unwrap()); + assert_eq!(0, instance.invoke_func(0, (i32::MAX, 31)).unwrap()); // Shifting by more than 31 - assert_eq!(-1, instance.invoke_func(0, (-1, 32))); - assert_eq!(1, instance.invoke_func(0, (1, 32))); - assert_eq!(268435455, instance.invoke_func(0, (-1, 100))); + assert_eq!(-1, instance.invoke_func(0, (-1, 32)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 32)).unwrap()); + assert_eq!(268435455, instance.invoke_func(0, (-1, 100)).unwrap()); // Minimum and maximum 32-bit integers assert_eq!( (i32::MIN / 2) * (-1), - instance.invoke_func(0, (i32::MIN, 1)) + instance.invoke_func(0, (i32::MIN, 1)).unwrap() + ); + assert_eq!( + i32::MAX / 2, + instance.invoke_func(0, (i32::MAX, 1)).unwrap() ); - assert_eq!(i32::MAX / 2, instance.invoke_func(0, (i32::MAX, 1))); // Shifting out all bits except sign - assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30))); - assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30))); + assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (i32::MAX, 30)).unwrap()); } /// A simple function to test the i32.rotl bitwise operation @@ -196,40 +220,67 @@ pub fn i32_bitwise_rotl() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(-2021317328, instance.invoke_func(0, (142_103_123, 4))); - assert_eq!(2131117524, instance.invoke_func(0, (391_248_921, 14))); - assert_eq!(-1887147272, instance.invoke_func(0, (1_203_910_012, 33))); - assert_eq!(-68588834, instance.invoke_func(0, (2_113_189_231, 33))); - assert_eq!(1073741824, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!( + -2021317328, + instance.invoke_func(0, (142_103_123, 4)).unwrap() + ); + assert_eq!( + 2131117524, + instance.invoke_func(0, (391_248_921, 14)).unwrap() + ); + assert_eq!( + -1887147272, + instance.invoke_func(0, (1_203_910_012, 33)).unwrap() + ); + assert_eq!( + -68588834, + instance.invoke_func(0, (2_113_189_231, 33)).unwrap() + ); + assert_eq!( + 1073741824, + instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap() + ); // Basic positive number - assert_eq!(16, instance.invoke_func(0, (8, 1))); + assert_eq!(16, instance.invoke_func(0, (8, 1)).unwrap()); // Rotating by 0 (no shift) - assert_eq!(-1, instance.invoke_func(0, (-1, 0))); - assert_eq!(1, instance.invoke_func(0, (1, 0))); + assert_eq!(-1, instance.invoke_func(0, (-1, 0)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 0)).unwrap()); // Shifting negative numbers - assert_eq!(-15, instance.invoke_func(0, (-8, 1))); - assert_eq!(-1, instance.invoke_func(0, (-1, 1))); + assert_eq!(-15, instance.invoke_func(0, (-8, 1)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (-1, 1)).unwrap()); // Rotating by 31 - assert_eq!(-1, instance.invoke_func(0, (-1, 31))); - assert_eq!(i32::MAX / 2 + 1, instance.invoke_func(0, (i32::MIN, 31))); - assert_eq!(i32::MIN / 2 - 1, instance.invoke_func(0, (i32::MAX, 31))); + assert_eq!(-1, instance.invoke_func(0, (-1, 31)).unwrap()); + assert_eq!( + i32::MAX / 2 + 1, + instance.invoke_func(0, (i32::MIN, 31)).unwrap() + ); + assert_eq!( + i32::MIN / 2 - 1, + instance.invoke_func(0, (i32::MAX, 31)).unwrap() + ); // Rotating by more than 31 - assert_eq!(-1, instance.invoke_func(0, (-1, 32))); - assert_eq!(1, instance.invoke_func(0, (1, 32))); - assert_eq!(-1, instance.invoke_func(0, (-1, 100))); + assert_eq!(-1, instance.invoke_func(0, (-1, 32)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 32)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (-1, 100)).unwrap()); // Minimum and maximum 32-bit integers - assert_eq!(1, instance.invoke_func(0, (i32::MIN, 1))); - assert_eq!(-2, instance.invoke_func(0, (i32::MAX, 1))); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, 1)).unwrap()); + assert_eq!(-2, instance.invoke_func(0, (i32::MAX, 1)).unwrap()); // Shifting out all bits except sign - assert_eq!(i32::MAX / 4 + 1, instance.invoke_func(0, (i32::MIN, 30))); - assert_eq!(i32::MIN / 4 - 1, instance.invoke_func(0, (i32::MAX, 30))); + assert_eq!( + i32::MAX / 4 + 1, + instance.invoke_func(0, (i32::MIN, 30)).unwrap() + ); + assert_eq!( + i32::MIN / 4 - 1, + instance.invoke_func(0, (i32::MAX, 30)).unwrap() + ); } /// A simple function to test the i32.rotr bitwise operation @@ -245,40 +296,58 @@ pub fn i32_bitwise_rotr() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(814187813, instance.invoke_func(0, (142_103_123, 4))); - assert_eq!(-261857977, instance.invoke_func(0, (391_248_921, 14))); - assert_eq!(601955006, instance.invoke_func(0, (1_203_910_012, 33))); - assert_eq!(-1090889033, instance.invoke_func(0, (2_113_189_231, 33))); - assert_eq!(1, instance.invoke_func(0, (i32::MIN, i32::MAX))); + assert_eq!( + 814187813, + instance.invoke_func(0, (142_103_123, 4)).unwrap() + ); + assert_eq!( + -261857977, + instance.invoke_func(0, (391_248_921, 14)).unwrap() + ); + assert_eq!( + 601955006, + instance.invoke_func(0, (1_203_910_012, 33)).unwrap() + ); + assert_eq!( + -1090889033, + instance.invoke_func(0, (2_113_189_231, 33)).unwrap() + ); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, i32::MAX)).unwrap()); // Basic positive number - assert_eq!(4, instance.invoke_func(0, (8, 1))); + assert_eq!(4, instance.invoke_func(0, (8, 1)).unwrap()); // Rotating by 0 (no shift) - assert_eq!(-1, instance.invoke_func(0, (-1, 0))); - assert_eq!(1, instance.invoke_func(0, (1, 0))); + assert_eq!(-1, instance.invoke_func(0, (-1, 0)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 0)).unwrap()); // Shifting negative numbers - assert_eq!(i32::MAX - 3, instance.invoke_func(0, (-8, 1))); - assert_eq!(-1, instance.invoke_func(0, (-1, 1))); + assert_eq!(i32::MAX - 3, instance.invoke_func(0, (-8, 1)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (-1, 1)).unwrap()); // Rotating by 31 - assert_eq!(-1, instance.invoke_func(0, (-1, 31))); - assert_eq!(1, instance.invoke_func(0, (i32::MIN, 31))); - assert_eq!(-2, instance.invoke_func(0, (i32::MAX, 31))); + assert_eq!(-1, instance.invoke_func(0, (-1, 31)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (i32::MIN, 31)).unwrap()); + assert_eq!(-2, instance.invoke_func(0, (i32::MAX, 31)).unwrap()); // Rotating by more than 31 - assert_eq!(-1, instance.invoke_func(0, (-1, 32))); - assert_eq!(1, instance.invoke_func(0, (1, 32))); - assert_eq!(-1, instance.invoke_func(0, (-1, 100))); + assert_eq!(-1, instance.invoke_func(0, (-1, 32)).unwrap()); + assert_eq!(1, instance.invoke_func(0, (1, 32)).unwrap()); + assert_eq!(-1, instance.invoke_func(0, (-1, 100)).unwrap()); // Minimum and maximum 32-bit integers - assert_eq!(i32::MAX / 2 + 1, instance.invoke_func(0, (i32::MIN, 1))); - assert_eq!(i32::MIN / 2 - 1, instance.invoke_func(0, (i32::MAX, 1))); + assert_eq!( + i32::MAX / 2 + 1, + instance.invoke_func(0, (i32::MIN, 1)).unwrap() + ); + assert_eq!( + i32::MIN / 2 - 1, + instance.invoke_func(0, (i32::MAX, 1)).unwrap() + ); // Shifting out all bits except sign - assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30))); - assert_eq!(-3, instance.invoke_func(0, (i32::MAX, 30))); + assert_eq!(2, instance.invoke_func(0, (i32::MIN, 30)).unwrap()); + assert_eq!(-3, instance.invoke_func(0, (i32::MAX, 30)).unwrap()); } const BASE_COUNT_WAT: &'static str = r#" @@ -302,12 +371,12 @@ pub fn i32_bitwise_clz() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(26, instance.invoke_func(0, 33)); - assert_eq!(25, instance.invoke_func(0, 77)); - assert_eq!(14, instance.invoke_func(0, 192534)); - assert_eq!(0, instance.invoke_func(0, i32::MIN)); - assert_eq!(1, instance.invoke_func(0, i32::MAX)); - assert_eq!(32, instance.invoke_func(0, 0)); + assert_eq!(26, instance.invoke_func(0, 33).unwrap()); + assert_eq!(25, instance.invoke_func(0, 77).unwrap()); + assert_eq!(14, instance.invoke_func(0, 192534).unwrap()); + assert_eq!(0, instance.invoke_func(0, i32::MIN).unwrap()); + assert_eq!(1, instance.invoke_func(0, i32::MAX).unwrap()); + assert_eq!(32, instance.invoke_func(0, 0).unwrap()); } /// A simple function to test the i32.ctz bitwise operation @@ -323,12 +392,12 @@ pub fn i32_bitwise_ctz() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(0, instance.invoke_func(0, 33)); - assert_eq!(0, instance.invoke_func(0, 77)); - assert_eq!(1, instance.invoke_func(0, 192534)); - assert_eq!(31, instance.invoke_func(0, i32::MIN)); - assert_eq!(0, instance.invoke_func(0, i32::MAX)); - assert_eq!(32, instance.invoke_func(0, 0)); + assert_eq!(0, instance.invoke_func(0, 33).unwrap()); + assert_eq!(0, instance.invoke_func(0, 77).unwrap()); + assert_eq!(1, instance.invoke_func(0, 192534).unwrap()); + assert_eq!(31, instance.invoke_func(0, i32::MIN).unwrap()); + assert_eq!(0, instance.invoke_func(0, i32::MAX).unwrap()); + assert_eq!(32, instance.invoke_func(0, 0).unwrap()); } /// A simple function to test the i32.popcnt bitwise operation @@ -344,10 +413,10 @@ pub fn i32_bitwise_popcnt() { let mut instance = RuntimeInstance::new(&validation_info).expect("instantiation failed"); - assert_eq!(2, instance.invoke_func(0, 33)); - assert_eq!(4, instance.invoke_func(0, 77)); - assert_eq!(8, instance.invoke_func(0, 192534)); - assert_eq!(1, instance.invoke_func(0, i32::MIN)); - assert_eq!(31, instance.invoke_func(0, i32::MAX)); - assert_eq!(0, instance.invoke_func(0, 0)); + assert_eq!(2, instance.invoke_func(0, 33).unwrap()); + assert_eq!(4, instance.invoke_func(0, 77).unwrap()); + assert_eq!(8, instance.invoke_func(0, 192534).unwrap()); + assert_eq!(1, instance.invoke_func(0, i32::MIN).unwrap()); + assert_eq!(31, instance.invoke_func(0, i32::MAX).unwrap()); + assert_eq!(0, instance.invoke_func(0, 0).unwrap()); }