diff --git a/compiler/gen_dev/src/generic64/aarch64.rs b/compiler/gen_dev/src/generic64/aarch64.rs index d344be324c..890995c726 100644 --- a/compiler/gen_dev/src/generic64/aarch64.rs +++ b/compiler/gen_dev/src/generic64/aarch64.rs @@ -500,6 +500,16 @@ impl Assembler for AArch64Assembler { unimplemented!("registers non-equality not implemented yet for AArch64"); } + #[inline(always)] + fn lt_reg64_reg64_reg64( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _src1: AArch64GeneralReg, + _src2: AArch64GeneralReg, + ) { + unimplemented!("registers less than not implemented yet for AArch64"); + } + #[inline(always)] fn ret(buf: &mut Vec<'_, u8>) { ret_reg64(buf, AArch64GeneralReg::LR) diff --git a/compiler/gen_dev/src/generic64/mod.rs b/compiler/gen_dev/src/generic64/mod.rs index dbffdcf8f4..b3936857b9 100644 --- a/compiler/gen_dev/src/generic64/mod.rs +++ b/compiler/gen_dev/src/generic64/mod.rs @@ -179,6 +179,13 @@ pub trait Assembler { src2: GeneralReg, ); + fn lt_reg64_reg64_reg64( + buf: &mut Vec<'_, u8>, + dst: GeneralReg, + src1: GeneralReg, + src2: GeneralReg, + ); + fn ret(buf: &mut Vec<'_, u8>); } @@ -868,6 +875,25 @@ impl< } } + fn build_num_lt( + &mut self, + dst: &Symbol, + src1: &Symbol, + src2: &Symbol, + arg_layout: &Layout<'a>, + ) -> Result<(), String> { + match arg_layout { + Layout::Builtin(Builtin::Int64) => { + let dst_reg = self.claim_general_reg(dst)?; + let src1_reg = self.load_to_general_reg(src1)?; + let src2_reg = self.load_to_general_reg(src2)?; + ASM::lt_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); + Ok(()) + } + x => Err(format!("NumLt: layout, {:?}, not implemented yet", x)), + } + } + fn create_struct( &mut self, sym: &Symbol, diff --git a/compiler/gen_dev/src/generic64/x86_64.rs b/compiler/gen_dev/src/generic64/x86_64.rs index d5e1b134cb..ce052c7448 100644 --- a/compiler/gen_dev/src/generic64/x86_64.rs +++ b/compiler/gen_dev/src/generic64/x86_64.rs @@ -1107,6 +1107,17 @@ impl Assembler for X86_64Assembler { setne_reg64(buf, dst); } + #[inline(always)] + fn lt_reg64_reg64_reg64( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + src1: X86_64GeneralReg, + src2: X86_64GeneralReg, + ) { + cmp_reg64_reg64(buf, src1, src2); + setl_reg64(buf, dst); + } + #[inline(always)] fn ret(buf: &mut Vec<'_, u8>) { ret(buf); @@ -1498,6 +1509,12 @@ fn setne_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) { set_reg64_help(buf, reg, 0x95); } +/// `SETL r/m64` -> Set byte if less (SF=ΜΈ OF). +#[inline(always)] +fn setl_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) { + set_reg64_help(buf, reg, 0x9c); +} + /// `RET` -> Near return to calling procedure. #[inline(always)] fn ret(buf: &mut Vec<'_, u8>) { diff --git a/compiler/gen_dev/src/lib.rs b/compiler/gen_dev/src/lib.rs index e8dff1d967..a87e2ecdf7 100644 --- a/compiler/gen_dev/src/lib.rs +++ b/compiler/gen_dev/src/lib.rs @@ -433,6 +433,23 @@ where ); self.build_neq(sym, &args[0], &args[1], &arg_layouts[0]) } + LowLevel::NumLt => { + debug_assert_eq!( + 2, + args.len(), + "NumLt: expected to have exactly two argument" + ); + debug_assert_eq!( + arg_layouts[0], arg_layouts[1], + "NumLt: expected all arguments of to have the same layout" + ); + debug_assert_eq!( + Layout::Builtin(Builtin::Int1), + *ret_layout, + "NumLt: expected to have return layout of type I1" + ); + self.build_num_lt(sym, &args[0], &args[1], &arg_layouts[0]) + } LowLevel::NumRound => self.build_fn_call( sym, bitcode::NUM_ROUND[FloatWidth::F64].to_string(), @@ -523,6 +540,15 @@ where arg_layout: &Layout<'a>, ) -> Result<(), String>; + /// build_num_lt stores the result of `src1 < src2` into dst. + fn build_num_lt( + &mut self, + dst: &Symbol, + src1: &Symbol, + src2: &Symbol, + arg_layout: &Layout<'a>, + ) -> Result<(), String>; + /// literal_map gets the map from symbol to literal, used for lazy loading and literal folding. fn literal_map(&mut self) -> &mut MutMap>; diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index df451c4898..1c283bac43 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -726,6 +726,20 @@ fn gen_int_neq() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn gen_int_less_than() { + assert_evals_to!( + indoc!( + r#" + 4 < 5 + "# + ), + true, + bool + ); +} + #[test] #[cfg(any(feature = "gen-llvm"))] fn gen_dec_eq() {