Add x86_64 Int lt support for gen_dev

Close #2033
This commit is contained in:
satotake 2021-11-20 06:17:22 +00:00 committed by GitHub
parent b7ee16afc8
commit 3a890f46d3
5 changed files with 93 additions and 0 deletions

View file

@ -500,6 +500,16 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> 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)

View file

@ -179,6 +179,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait> {
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,

View file

@ -1107,6 +1107,17 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> 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>) {

View file

@ -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<Symbol, Literal<'a>>;

View file

@ -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() {