From b9ee0b6b7a73df3d18980358d4cec2c84d0ebcdb Mon Sep 17 00:00:00 2001 From: Amuthan Mannar Date: Fri, 6 Oct 2023 17:51:54 +0530 Subject: [PATCH] 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 c6b5362fb..2959361a0 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 64b1fd0cd..26afb9778 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)); +}