mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
copy arguments that are not size multiple of 8
This commit is contained in:
parent
64130dbbbc
commit
f95c79bb53
3 changed files with 105 additions and 24 deletions
|
@ -980,7 +980,17 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
todo!("saving floating point reg to stack for AArch64");
|
||||
}
|
||||
#[inline(always)]
|
||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: AArch64GeneralReg) {
|
||||
fn mov_stack32_reg(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
register_width: RegisterWidth,
|
||||
offset: i32,
|
||||
src: AArch64GeneralReg,
|
||||
) {
|
||||
match register_width {
|
||||
RegisterWidth::W8 => todo!(),
|
||||
RegisterWidth::W16 => todo!(),
|
||||
RegisterWidth::W32 => todo!(),
|
||||
RegisterWidth::W64 => {
|
||||
if offset < 0 {
|
||||
todo!("negative stack offsets for AArch64");
|
||||
} else if offset < (0xFFF << 8) {
|
||||
|
@ -990,6 +1000,8 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
todo!("stack offsets over 32k for AArch64");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn neg_reg64_reg64(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, src: AArch64GeneralReg) {
|
||||
neg_reg64_reg64(buf, dst, src);
|
||||
|
|
|
@ -362,7 +362,26 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
fn mov_freg64_stack32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
|
||||
fn mov_reg64_stack32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
|
||||
fn mov_stack32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg);
|
||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
||||
|
||||
fn mov_stack32_reg(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
register_width: RegisterWidth,
|
||||
offset: i32,
|
||||
src: GeneralReg,
|
||||
);
|
||||
|
||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg) {
|
||||
Self::mov_stack32_reg(buf, RegisterWidth::W64, offset, src)
|
||||
}
|
||||
fn mov_stack32_reg32(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg) {
|
||||
Self::mov_stack32_reg(buf, RegisterWidth::W32, offset, src)
|
||||
}
|
||||
fn mov_stack32_reg16(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg) {
|
||||
Self::mov_stack32_reg(buf, RegisterWidth::W16, offset, src)
|
||||
}
|
||||
fn mov_stack32_reg8(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg) {
|
||||
Self::mov_stack32_reg(buf, RegisterWidth::W8, offset, src)
|
||||
}
|
||||
|
||||
fn sqrt_freg64_freg64(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
|
||||
fn sqrt_freg32_freg32(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
|
||||
|
|
|
@ -536,21 +536,50 @@ impl X64_64SystemVStoreArgs {
|
|||
self.tmp_stack_offset += size as i32;
|
||||
}
|
||||
Layout::Union(UnionLayout::NonRecursive(_)) => {
|
||||
// for now, just also store this on the stack
|
||||
type ASM = X86_64Assembler;
|
||||
|
||||
let tmp_reg = Self::GENERAL_RETURN_REGS[0];
|
||||
let stack_offset = self.tmp_stack_offset as i32;
|
||||
|
||||
let mut copied = 0;
|
||||
let (base_offset, size) = storage_manager.stack_offset_and_size(&sym);
|
||||
debug_assert_eq!(base_offset % 8, 0);
|
||||
for i in (0..size as i32).step_by(8) {
|
||||
X86_64Assembler::mov_reg64_base32(
|
||||
buf,
|
||||
Self::GENERAL_RETURN_REGS[0],
|
||||
base_offset + i,
|
||||
);
|
||||
X86_64Assembler::mov_stack32_reg64(
|
||||
buf,
|
||||
self.tmp_stack_offset + i,
|
||||
Self::GENERAL_RETURN_REGS[0],
|
||||
);
|
||||
|
||||
if size - copied >= 8 {
|
||||
for _ in (0..(size - copied)).step_by(8) {
|
||||
ASM::mov_reg64_base32(buf, tmp_reg, base_offset + copied as i32);
|
||||
ASM::mov_stack32_reg64(buf, stack_offset + copied as i32, tmp_reg);
|
||||
|
||||
copied += 8;
|
||||
}
|
||||
}
|
||||
|
||||
if size - copied >= 4 {
|
||||
for _ in (0..(size - copied)).step_by(4) {
|
||||
ASM::mov_reg32_base32(buf, tmp_reg, base_offset + copied as i32);
|
||||
ASM::mov_stack32_reg32(buf, stack_offset + copied as i32, tmp_reg);
|
||||
|
||||
copied += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if size - copied >= 2 {
|
||||
for _ in (0..(size - copied)).step_by(2) {
|
||||
ASM::mov_reg16_base32(buf, tmp_reg, base_offset + copied as i32);
|
||||
ASM::mov_stack32_reg16(buf, stack_offset + copied as i32, tmp_reg);
|
||||
|
||||
copied += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if size - copied >= 1 {
|
||||
for _ in (0..(size - copied)).step_by(1) {
|
||||
ASM::mov_reg8_base32(buf, tmp_reg, base_offset + copied as i32);
|
||||
ASM::mov_stack32_reg8(buf, stack_offset + copied as i32, tmp_reg);
|
||||
|
||||
copied += 1;
|
||||
}
|
||||
}
|
||||
|
||||
self.tmp_stack_offset += size as i32;
|
||||
}
|
||||
_ => {
|
||||
|
@ -1631,8 +1660,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
movsd_base64_offset32_freg64(buf, X86_64GeneralReg::RSP, offset, src)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64GeneralReg) {
|
||||
mov_base64_offset32_reg64(buf, X86_64GeneralReg::RSP, offset, src)
|
||||
fn mov_stack32_reg(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
register_width: RegisterWidth,
|
||||
offset: i32,
|
||||
src: X86_64GeneralReg,
|
||||
) {
|
||||
mov_base_offset32_reg(buf, register_width, X86_64GeneralReg::RSP, offset, src)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -2583,6 +2617,22 @@ fn mov_reg_reg(
|
|||
|
||||
// The following base and stack based operations could be optimized based on how many bytes the offset actually is.
|
||||
|
||||
#[inline(always)]
|
||||
fn mov_base_offset32_reg(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
register_width: RegisterWidth,
|
||||
base: X86_64GeneralReg,
|
||||
offset: i32,
|
||||
src: X86_64GeneralReg,
|
||||
) {
|
||||
match register_width {
|
||||
RegisterWidth::W8 => mov_base16_offset32_reg16(buf, base, offset, src),
|
||||
RegisterWidth::W16 => mov_base16_offset32_reg16(buf, base, offset, src),
|
||||
RegisterWidth::W32 => mov_base32_offset32_reg32(buf, base, offset, src),
|
||||
RegisterWidth::W64 => mov_base64_offset32_reg64(buf, base, offset, src),
|
||||
}
|
||||
}
|
||||
|
||||
/// `MOV r/m64,r64` -> Move r64 to r/m64, where m64 references a base + offset.
|
||||
#[inline(always)]
|
||||
fn mov_base64_offset32_reg64(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue