Merge remote-tracking branch 'origin/main' into str-unicode

This commit is contained in:
Richard Feldman 2024-01-21 12:29:34 -05:00
commit 2970fc4384
No known key found for this signature in database
GPG key ID: F1F21AA5B1D9E43B
78 changed files with 2747 additions and 2467 deletions

View file

@ -1242,6 +1242,16 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
fabs_freg_freg(buf, FloatWidth::F64, dst, src);
}
#[inline(always)]
fn abs_freg32_freg32(
buf: &mut Vec<'_, u8>,
_relocs: &mut Vec<'_, Relocation>,
dst: AArch64FloatReg,
src: AArch64FloatReg,
) {
fabs_freg_freg(buf, FloatWidth::F32, dst, src);
}
#[inline(always)]
fn add_reg64_reg64_imm32(
buf: &mut Vec<'_, u8>,

View file

@ -164,6 +164,12 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
dst: FloatReg,
src: FloatReg,
);
fn abs_freg32_freg32(
buf: &mut Vec<'_, u8>,
relocs: &mut Vec<'_, Relocation>,
dst: FloatReg,
src: FloatReg,
);
fn add_reg64_reg64_imm32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src1: GeneralReg, imm32: i32);
fn add_reg64_reg64_reg64(
@ -1316,6 +1322,11 @@ impl<
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::abs_freg64_freg64(&mut self.buf, &mut self.relocs, dst_reg, src_reg);
}
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::abs_freg32_freg32(&mut self.buf, &mut self.relocs, dst_reg, src_reg);
}
x => todo!("NumAbs: layout, {:?}", x),
}
}
@ -2798,6 +2809,55 @@ impl<
self.storage_manager.list_len(&mut self.buf, dst, list);
}
fn build_list_clone(
&mut self,
dst: Symbol,
input_list: Symbol,
elem_layout: InLayout<'a>,
ret_layout: InLayout<'a>,
) {
// List alignment argument (u32).
self.load_layout_alignment(ret_layout, Symbol::DEV_TMP);
// Load element_width argument (usize).
self.load_layout_stack_size(elem_layout, Symbol::DEV_TMP2);
// Setup the return location.
let base_offset =
self.storage_manager
.claim_stack_area_layout(self.layout_interner, dst, ret_layout);
let lowlevel_args = [
input_list,
// alignment
Symbol::DEV_TMP,
// element_width
Symbol::DEV_TMP2,
];
let lowlevel_arg_layouts = [ret_layout, Layout::U32, Layout::U64];
self.build_fn_call(
&Symbol::DEV_TMP3,
bitcode::LIST_CLONE.to_string(),
&lowlevel_args,
&lowlevel_arg_layouts,
&ret_layout,
);
self.free_symbol(&Symbol::DEV_TMP);
self.free_symbol(&Symbol::DEV_TMP2);
// Copy from list to the output record.
self.storage_manager.copy_symbol_to_stack_offset(
self.layout_interner,
&mut self.buf,
base_offset,
&Symbol::DEV_TMP3,
&ret_layout,
);
self.free_symbol(&Symbol::DEV_TMP3);
}
fn build_list_with_capacity(
&mut self,
dst: &Symbol,

View file

@ -1955,6 +1955,24 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
andpd_freg64_freg64(buf, dst, src);
}
#[inline(always)]
fn abs_freg32_freg32(
buf: &mut Vec<'_, u8>,
relocs: &mut Vec<'_, Relocation>,
dst: X86_64FloatReg,
src: X86_64FloatReg,
) {
movss_freg32_rip_offset32(buf, dst, 0);
// TODO: make sure this constant only loads once instead of every call to abs
relocs.push(Relocation::LocalData {
offset: buf.len() as u64 - 4,
data: 0x7fffffffu64.to_le_bytes().to_vec(),
});
andps_freg32_freg32(buf, dst, src);
}
#[inline(always)]
fn add_reg64_reg64_imm32(
buf: &mut Vec<'_, u8>,
@ -3179,6 +3197,25 @@ fn andpd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64Fl
}
}
#[inline(always)]
fn andps_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
let dst_high = dst as u8 > 7;
let dst_mod = dst as u8 % 8;
let src_high = src as u8 > 7;
let src_mod = src as u8 % 8;
if dst_high || src_high {
buf.extend([
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
0x0F,
0x54,
0xC0 | (dst_mod << 3) | (src_mod),
])
} else {
buf.extend([0x0F, 0x54, 0xC0 | (dst_mod << 3) | (src_mod)])
}
}
/// r/m64 AND imm8 (sign-extended).
#[inline(always)]
fn and_reg64_imm8(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, imm: i8) {
@ -4483,6 +4520,16 @@ mod tests {
);
}
#[test]
fn test_andps_freg32_freg32() {
disassembler_test!(
andps_freg32_freg32,
|reg1, reg2| format!("andps {reg1}, {reg2}"),
ALL_FLOAT_REGS,
ALL_FLOAT_REGS
);
}
#[test]
fn test_and_reg64_reg64() {
disassembler_test!(

View file

@ -1518,6 +1518,15 @@ trait Backend<'a> {
let elem_layout = list_element_layout!(self.interner(), *ret_layout);
self.build_list_with_capacity(sym, args[0], arg_layouts[0], elem_layout, ret_layout)
}
LowLevel::ListClone => {
debug_assert_eq!(
1,
args.len(),
"ListClone: expected to have exactly one argument"
);
let elem_layout = list_element_layout!(self.interner(), *ret_layout);
self.build_list_clone(*sym, args[0], elem_layout, *ret_layout)
}
LowLevel::ListReserve => {
debug_assert_eq!(
2,
@ -2369,6 +2378,14 @@ trait Backend<'a> {
fn build_indirect_inc(&mut self, layout: InLayout<'a>) -> Symbol;
fn build_indirect_dec(&mut self, layout: InLayout<'a>) -> Symbol;
fn build_list_clone(
&mut self,
dst: Symbol,
input_list: Symbol,
elem_layout: InLayout<'a>,
ret_layout: InLayout<'a>,
);
/// build_list_with_capacity creates and returns a list with the given capacity.
fn build_list_with_capacity(
&mut self,