mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge pull request #2034 from rtfeldman/dev-backend-num-lt
Add x86_64 Int lt support for gen_dev
This commit is contained in:
commit
cbbe04509b
5 changed files with 96 additions and 43 deletions
|
@ -500,6 +500,16 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
unimplemented!("registers non-equality not implemented yet for AArch64");
|
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)]
|
#[inline(always)]
|
||||||
fn ret(buf: &mut Vec<'_, u8>) {
|
fn ret(buf: &mut Vec<'_, u8>) {
|
||||||
ret_reg64(buf, AArch64GeneralReg::LR)
|
ret_reg64(buf, AArch64GeneralReg::LR)
|
||||||
|
|
|
@ -179,6 +179,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait> {
|
||||||
src2: GeneralReg,
|
src2: GeneralReg,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn lt_reg64_reg64_reg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
src1: GeneralReg,
|
||||||
|
src2: GeneralReg,
|
||||||
|
);
|
||||||
|
|
||||||
fn ret(buf: &mut Vec<'_, u8>);
|
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(
|
fn create_struct(
|
||||||
&mut self,
|
&mut self,
|
||||||
sym: &Symbol,
|
sym: &Symbol,
|
||||||
|
|
|
@ -1107,6 +1107,17 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
||||||
setne_reg64(buf, dst);
|
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)]
|
#[inline(always)]
|
||||||
fn ret(buf: &mut Vec<'_, u8>) {
|
fn ret(buf: &mut Vec<'_, u8>) {
|
||||||
ret(buf);
|
ret(buf);
|
||||||
|
@ -1498,6 +1509,12 @@ fn setne_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
||||||
set_reg64_help(buf, reg, 0x95);
|
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.
|
/// `RET` -> Near return to calling procedure.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ret(buf: &mut Vec<'_, u8>) {
|
fn ret(buf: &mut Vec<'_, u8>) {
|
||||||
|
@ -2082,7 +2099,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sete_reg64() {
|
fn test_set_reg64_help() {
|
||||||
let arena = bumpalo::Bump::new();
|
let arena = bumpalo::Bump::new();
|
||||||
let mut buf = bumpalo::vec![in &arena];
|
let mut buf = bumpalo::vec![in &arena];
|
||||||
|
|
||||||
|
@ -2095,7 +2112,7 @@ mod tests {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
sete_reg64(&mut buf, reg);
|
set_reg64_help(&mut buf, reg, 0x94); // sete_reg64
|
||||||
assert_eq!(expected, &buf[..]);
|
assert_eq!(expected, &buf[..]);
|
||||||
|
|
||||||
// tests for 8 bytes in the output buffer
|
// tests for 8 bytes in the output buffer
|
||||||
|
@ -2120,47 +2137,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
] {
|
] {
|
||||||
buf.clear();
|
buf.clear();
|
||||||
sete_reg64(&mut buf, *reg);
|
set_reg64_help(&mut buf, *reg, 0x94); // sete_reg64
|
||||||
assert_eq!(expected, &buf[..]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
// follow test_sete_reg64
|
|
||||||
// refer it
|
|
||||||
fn test_setne_reg64() {
|
|
||||||
let arena = bumpalo::Bump::new();
|
|
||||||
let mut buf = bumpalo::vec![in &arena];
|
|
||||||
|
|
||||||
let (reg, expected) = (
|
|
||||||
X86_64GeneralReg::RAX,
|
|
||||||
[
|
|
||||||
0x0F, 0x95, 0xC0, // SETNE al ;
|
|
||||||
0x48, 0x83, 0xE0, 0x01,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
buf.clear();
|
|
||||||
setne_reg64(&mut buf, reg);
|
|
||||||
assert_eq!(expected, &buf[..]);
|
|
||||||
|
|
||||||
for (reg, expected) in &[
|
|
||||||
(
|
|
||||||
X86_64GeneralReg::RSP,
|
|
||||||
[
|
|
||||||
// SETNE spl;
|
|
||||||
0x40, 0x0F, 0x95, 0xC4, 0x48, 0x83, 0xE4, 0x01,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
X86_64GeneralReg::R15,
|
|
||||||
[
|
|
||||||
// SETNE r15b;
|
|
||||||
0x41, 0x0F, 0x95, 0xC7, 0x49, 0x83, 0xE7, 0x01,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
] {
|
|
||||||
buf.clear();
|
|
||||||
setne_reg64(&mut buf, *reg);
|
|
||||||
assert_eq!(expected, &buf[..]);
|
assert_eq!(expected, &buf[..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -433,6 +433,23 @@ where
|
||||||
);
|
);
|
||||||
self.build_neq(sym, &args[0], &args[1], &arg_layouts[0])
|
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(
|
LowLevel::NumRound => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_ROUND[FloatWidth::F64].to_string(),
|
bitcode::NUM_ROUND[FloatWidth::F64].to_string(),
|
||||||
|
@ -523,6 +540,15 @@ where
|
||||||
arg_layout: &Layout<'a>,
|
arg_layout: &Layout<'a>,
|
||||||
) -> Result<(), String>;
|
) -> 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.
|
/// 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>>;
|
fn literal_map(&mut self) -> &mut MutMap<Symbol, Literal<'a>>;
|
||||||
|
|
||||||
|
|
|
@ -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]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
fn gen_dec_eq() {
|
fn gen_dec_eq() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue