From f8365ca6c3690e63a74b831f211f3087a4f93a80 Mon Sep 17 00:00:00 2001 From: Amuthan Mannar Date: Thu, 5 Oct 2023 21:27:56 +0530 Subject: [PATCH 1/4] Implemented compare operation for boolean types in JIT engine --- jit/src/instructions.rs | 16 +++++++++ jit/tests/bool_tests.rs | 75 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/jit/src/instructions.rs b/jit/src/instructions.rs index 86dc58aca4..c6b5362fb9 100644 --- a/jit/src/instructions.rs +++ b/jit/src/instructions.rs @@ -348,6 +348,22 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> { .push(JitValue::Bool(self.builder.ins().bint(types::I8, val))); Ok(()) } + (JitValue::Bool(a), JitValue::Bool(b)) => { + let cond = match op { + ComparisonOperator::Equal => IntCC::Equal, + ComparisonOperator::NotEqual => IntCC::NotEqual, + ComparisonOperator::Less => IntCC::UnsignedLessThan, + ComparisonOperator::LessOrEqual => IntCC::UnsignedLessThanOrEqual, + ComparisonOperator::Greater => IntCC::UnsignedGreaterThan, + ComparisonOperator::GreaterOrEqual => IntCC::UnsignedGreaterThanOrEqual, + }; + + let val = self.builder.ins().icmp(cond, a, b); + // TODO: Remove this `bint` in cranelift 0.90 as icmp now returns i8 + self.stack + .push(JitValue::Bool(self.builder.ins().bint(types::I8, val))); + Ok(()) + } _ => Err(JitCompileError::NotSupported), } } diff --git a/jit/tests/bool_tests.rs b/jit/tests/bool_tests.rs index ed25ddb83f..64b1fd0cd5 100644 --- a/jit/tests/bool_tests.rs +++ b/jit/tests/bool_tests.rs @@ -50,3 +50,78 @@ fn test_if_not() { assert_eq!(if_not(true), Ok(1)); assert_eq!(if_not(false), Ok(0)); } + +#[test] +fn test_eq() { + let eq = jit_function! { eq(a:bool, b:bool) -> i64 => r##" + def eq(a: bool, b: bool): + if a == b: + return 1 + return 0 + "## }; + + assert_eq!(eq(false, false), Ok(1)); + assert_eq!(eq(true, true), Ok(1)); + assert_eq!(eq(false, true), Ok(0)); + assert_eq!(eq(true, false), Ok(0)); +} + +#[test] +fn test_gt() { + let gt = jit_function! { gt(a:bool, b:bool) -> i64 => r##" + def gt(a: bool, b: bool): + if a > b: + return 1 + return 0 + "## }; + + assert_eq!(gt(false, false), Ok(0)); + assert_eq!(gt(true, true), Ok(0)); + assert_eq!(gt(false, true), Ok(0)); + assert_eq!(gt(true, false), Ok(1)); +} + +#[test] +fn test_lt() { + let lt = jit_function! { lt(a:bool, b:bool) -> i64 => r##" + def lt(a: bool, b: bool): + if a < b: + return 1 + return 0 + "## }; + + assert_eq!(lt(false, false), Ok(0)); + assert_eq!(lt(true, true), Ok(0)); + assert_eq!(lt(false, true), Ok(1)); + assert_eq!(lt(true, false), Ok(0)); +} + +#[test] +fn test_gte() { + let gte = jit_function! { gte(a:bool, b:bool) -> i64 => r##" + def gte(a: bool, b: bool): + if a >= b: + return 1 + return 0 + "## }; + + assert_eq!(gte(false, false), Ok(1)); + assert_eq!(gte(true, true), Ok(1)); + assert_eq!(gte(false, true), Ok(0)); + assert_eq!(gte(true, false), Ok(1)); +} + +#[test] +fn test_lte() { + let lte = jit_function! { lte(a:bool, b:bool) -> i64 => r##" + def lte(a: bool, b: bool): + if a <= b: + return 1 + return 0 + "## }; + + assert_eq!(lte(false, false), Ok(1)); + assert_eq!(lte(true, true), Ok(1)); + assert_eq!(lte(false, true), Ok(1)); + assert_eq!(lte(true, false), Ok(0)); +} From b9ee0b6b7a73df3d18980358d4cec2c84d0ebcdb Mon Sep 17 00:00:00 2001 From: Amuthan Mannar Date: Fri, 6 Oct 2023 17:51:54 +0530 Subject: [PATCH 2/4] Implemented compare operation for boolean and int types --- jit/src/instructions.rs | 40 +++++++++++----------- jit/tests/bool_tests.rs | 76 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 19 deletions(-) diff --git a/jit/src/instructions.rs b/jit/src/instructions.rs index c6b5362fb9..2959361a0f 100644 --- a/jit/src/instructions.rs +++ b/jit/src/instructions.rs @@ -315,18 +315,36 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> { let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?; let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?; + let a_type:Option = a.to_jit_type(); + let b_type:Option = b.to_jit_type(); + match (a, b) { - (JitValue::Int(a), JitValue::Int(b)) => { + (JitValue::Int(a), JitValue::Int(b)) | + (JitValue::Bool(a), JitValue::Bool(b)) | + (JitValue::Bool(a), JitValue::Int(b)) | + (JitValue::Int(a), JitValue::Bool(b)) + => { + + let operand_one = match a_type.unwrap() { + JitType::Bool => self.builder.ins().uextend(types::I64, a), + _=> a + }; + + let operand_two = match b_type.unwrap() { + JitType::Bool => self.builder.ins().uextend(types::I64, b), + _=> b + }; + let cond = match op { ComparisonOperator::Equal => IntCC::Equal, ComparisonOperator::NotEqual => IntCC::NotEqual, ComparisonOperator::Less => IntCC::SignedLessThan, ComparisonOperator::LessOrEqual => IntCC::SignedLessThanOrEqual, ComparisonOperator::Greater => IntCC::SignedGreaterThan, - ComparisonOperator::GreaterOrEqual => IntCC::SignedLessThanOrEqual, + ComparisonOperator::GreaterOrEqual => IntCC::SignedGreaterThanOrEqual, }; - let val = self.builder.ins().icmp(cond, a, b); + let val = self.builder.ins().icmp(cond, operand_one, operand_two); // TODO: Remove this `bint` in cranelift 0.90 as icmp now returns i8 self.stack .push(JitValue::Bool(self.builder.ins().bint(types::I8, val))); @@ -348,22 +366,6 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> { .push(JitValue::Bool(self.builder.ins().bint(types::I8, val))); Ok(()) } - (JitValue::Bool(a), JitValue::Bool(b)) => { - let cond = match op { - ComparisonOperator::Equal => IntCC::Equal, - ComparisonOperator::NotEqual => IntCC::NotEqual, - ComparisonOperator::Less => IntCC::UnsignedLessThan, - ComparisonOperator::LessOrEqual => IntCC::UnsignedLessThanOrEqual, - ComparisonOperator::Greater => IntCC::UnsignedGreaterThan, - ComparisonOperator::GreaterOrEqual => IntCC::UnsignedGreaterThanOrEqual, - }; - - let val = self.builder.ins().icmp(cond, a, b); - // TODO: Remove this `bint` in cranelift 0.90 as icmp now returns i8 - self.stack - .push(JitValue::Bool(self.builder.ins().bint(types::I8, val))); - Ok(()) - } _ => Err(JitCompileError::NotSupported), } } diff --git a/jit/tests/bool_tests.rs b/jit/tests/bool_tests.rs index 64b1fd0cd5..26afb97780 100644 --- a/jit/tests/bool_tests.rs +++ b/jit/tests/bool_tests.rs @@ -66,6 +66,21 @@ fn test_eq() { assert_eq!(eq(true, false), Ok(0)); } +#[test] +fn test_eq_with_integers() { + let eq = jit_function! { eq(a:bool, b:i64) -> i64 => r##" + def eq(a: bool, b: int): + if a == b: + return 1 + return 0 + "## }; + + assert_eq!(eq(false, 0), Ok(1)); + assert_eq!(eq(true, 1), Ok(1)); + assert_eq!(eq(false, 1), Ok(0)); + assert_eq!(eq(true, 0), Ok(0)); +} + #[test] fn test_gt() { let gt = jit_function! { gt(a:bool, b:bool) -> i64 => r##" @@ -81,6 +96,21 @@ fn test_gt() { assert_eq!(gt(true, false), Ok(1)); } +#[test] +fn test_gt_with_integers() { + let gt = jit_function! { gt(a:i64, b:bool) -> i64 => r##" + def gt(a: int, b: bool): + if a > b: + return 1 + return 0 + "## }; + + assert_eq!(gt(0, false), Ok(0)); + assert_eq!(gt(1, true), Ok(0)); + assert_eq!(gt(0, true), Ok(0)); + assert_eq!(gt(1, false), Ok(1)); +} + #[test] fn test_lt() { let lt = jit_function! { lt(a:bool, b:bool) -> i64 => r##" @@ -96,6 +126,21 @@ fn test_lt() { assert_eq!(lt(true, false), Ok(0)); } +#[test] +fn test_lt_with_integers() { + let lt = jit_function! { lt(a:i64, b:bool) -> i64 => r##" + def lt(a: int, b: bool): + if a < b: + return 1 + return 0 + "## }; + + assert_eq!(lt(0, false), Ok(0)); + assert_eq!(lt(1, true), Ok(0)); + assert_eq!(lt(0, true), Ok(1)); + assert_eq!(lt(1, false), Ok(0)); +} + #[test] fn test_gte() { let gte = jit_function! { gte(a:bool, b:bool) -> i64 => r##" @@ -111,6 +156,22 @@ fn test_gte() { assert_eq!(gte(true, false), Ok(1)); } + +#[test] +fn test_gte_with_integers() { + let gte = jit_function! { gte(a:bool, b:i64) -> i64 => r##" + def gte(a: bool, b: int): + if a >= b: + return 1 + return 0 + "## }; + + assert_eq!(gte(false, 0), Ok(1)); + assert_eq!(gte(true, 1), Ok(1)); + assert_eq!(gte(false, 1), Ok(0)); + assert_eq!(gte(true, 0), Ok(1)); +} + #[test] fn test_lte() { let lte = jit_function! { lte(a:bool, b:bool) -> i64 => r##" @@ -125,3 +186,18 @@ fn test_lte() { assert_eq!(lte(false, true), Ok(1)); assert_eq!(lte(true, false), Ok(0)); } + +#[test] +fn test_lte_with_integers() { + let lte = jit_function! { lte(a:bool, b:i64) -> i64 => r##" + def lte(a: bool, b: int): + if a <= b: + return 1 + return 0 + "## }; + + assert_eq!(lte(false, 0), Ok(1)); + assert_eq!(lte(true, 1), Ok(1)); + assert_eq!(lte(false, 1), Ok(1)); + assert_eq!(lte(true, 0), Ok(0)); +} From b69e6a910d5ae8be69eef2e5c6496a7c6d3701c9 Mon Sep 17 00:00:00 2001 From: Amuthan Mannar Date: Fri, 6 Oct 2023 18:18:12 +0530 Subject: [PATCH 3/4] Added missed tests in int_tests of jit --- jit/tests/int_tests.rs | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/jit/tests/int_tests.rs b/jit/tests/int_tests.rs index 314849a06e..9ce3f3b4a6 100644 --- a/jit/tests/int_tests.rs +++ b/jit/tests/int_tests.rs @@ -160,6 +160,52 @@ fn test_gt() { assert_eq!(gt(1, -1), Ok(1)); } +#[test] +fn test_lt() { + let lt = jit_function! { lt(a:i64, b:i64) -> i64 => r##" + def lt(a: int, b: int): + if a < b: + return 1 + return 0 + "## }; + + assert_eq!(lt(-1, -5), Ok(0)); + assert_eq!(lt(10, 0), Ok(0)); + assert_eq!(lt(0, 1), Ok(1)); + assert_eq!(lt(-10, -1), Ok(1)); + assert_eq!(lt(100, 100), Ok(0)); +} + +#[test] +fn test_gte() { + let gte = jit_function! { gte(a:i64, b:i64) -> i64 => r##" + def gte(a: int, b: int): + if a >= b: + return 1 + return 0 + "## }; + + assert_eq!(gte(-64, -64), Ok(1)); + assert_eq!(gte(100, -1), Ok(1)); + assert_eq!(gte(1, 2), Ok(0)); + assert_eq!(gte(1, 0), Ok(1)); +} + +#[test] +fn test_lte() { + let lte = jit_function! { lte(a:i64, b:i64) -> i64 => r##" + def lte(a: int, b: int): + if a <= b: + return 1 + return 0 + "## }; + + assert_eq!(lte(-100, -100), Ok(1)); + assert_eq!(lte(-100, 100), Ok(1)); + assert_eq!(lte(10, 1), Ok(0)); + assert_eq!(lte(0, -2), Ok(0)); +} + #[test] fn test_minus() { let minus = jit_function! { minus(a:i64) -> i64 => r##" From eb83b729b2cd1da84af3332e4e509651c9b6dfbf Mon Sep 17 00:00:00 2001 From: Amuthan Mannar Date: Sat, 7 Oct 2023 12:29:24 +0530 Subject: [PATCH 4/4] Formatted code files --- jit/src/instructions.rs | 18 ++++++++---------- jit/tests/bool_tests.rs | 1 - 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/jit/src/instructions.rs b/jit/src/instructions.rs index 2959361a0f..ef099026e8 100644 --- a/jit/src/instructions.rs +++ b/jit/src/instructions.rs @@ -315,24 +315,22 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> { let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?; let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?; - let a_type:Option = a.to_jit_type(); - let b_type:Option = b.to_jit_type(); + let a_type: Option = a.to_jit_type(); + let b_type: Option = b.to_jit_type(); match (a, b) { - (JitValue::Int(a), JitValue::Int(b)) | - (JitValue::Bool(a), JitValue::Bool(b)) | - (JitValue::Bool(a), JitValue::Int(b)) | - (JitValue::Int(a), JitValue::Bool(b)) - => { - + (JitValue::Int(a), JitValue::Int(b)) + | (JitValue::Bool(a), JitValue::Bool(b)) + | (JitValue::Bool(a), JitValue::Int(b)) + | (JitValue::Int(a), JitValue::Bool(b)) => { let operand_one = match a_type.unwrap() { JitType::Bool => self.builder.ins().uextend(types::I64, a), - _=> a + _ => a, }; let operand_two = match b_type.unwrap() { JitType::Bool => self.builder.ins().uextend(types::I64, b), - _=> b + _ => b, }; let cond = match op { diff --git a/jit/tests/bool_tests.rs b/jit/tests/bool_tests.rs index 26afb97780..191993938d 100644 --- a/jit/tests/bool_tests.rs +++ b/jit/tests/bool_tests.rs @@ -156,7 +156,6 @@ fn test_gte() { assert_eq!(gte(true, false), Ok(1)); } - #[test] fn test_gte_with_integers() { let gte = jit_function! { gte(a:bool, b:i64) -> i64 => r##"