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,14 +980,26 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
todo!("saving floating point reg to stack for AArch64");
|
todo!("saving floating point reg to stack for AArch64");
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: AArch64GeneralReg) {
|
fn mov_stack32_reg(
|
||||||
if offset < 0 {
|
buf: &mut Vec<'_, u8>,
|
||||||
todo!("negative stack offsets for AArch64");
|
register_width: RegisterWidth,
|
||||||
} else if offset < (0xFFF << 8) {
|
offset: i32,
|
||||||
debug_assert!(offset % 8 == 0);
|
src: AArch64GeneralReg,
|
||||||
str_reg64_reg64_imm12(buf, src, AArch64GeneralReg::ZRSP, (offset as u16) >> 3);
|
) {
|
||||||
} else {
|
match register_width {
|
||||||
todo!("stack offsets over 32k for AArch64");
|
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) {
|
||||||
|
debug_assert!(offset % 8 == 0);
|
||||||
|
str_reg64_reg64_imm12(buf, src, AArch64GeneralReg::ZRSP, (offset as u16) >> 3);
|
||||||
|
} else {
|
||||||
|
todo!("stack offsets over 32k for AArch64");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -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_freg64_stack32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
|
||||||
fn mov_reg64_stack32(buf: &mut Vec<'_, u8>, dst: GeneralReg, 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_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_freg64_freg64(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
|
||||||
fn sqrt_freg32_freg32(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;
|
self.tmp_stack_offset += size as i32;
|
||||||
}
|
}
|
||||||
Layout::Union(UnionLayout::NonRecursive(_)) => {
|
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);
|
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) {
|
if size - copied >= 8 {
|
||||||
X86_64Assembler::mov_reg64_base32(
|
for _ in (0..(size - copied)).step_by(8) {
|
||||||
buf,
|
ASM::mov_reg64_base32(buf, tmp_reg, base_offset + copied as i32);
|
||||||
Self::GENERAL_RETURN_REGS[0],
|
ASM::mov_stack32_reg64(buf, stack_offset + copied as i32, tmp_reg);
|
||||||
base_offset + i,
|
|
||||||
);
|
copied += 8;
|
||||||
X86_64Assembler::mov_stack32_reg64(
|
}
|
||||||
buf,
|
|
||||||
self.tmp_stack_offset + i,
|
|
||||||
Self::GENERAL_RETURN_REGS[0],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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)
|
movsd_base64_offset32_freg64(buf, X86_64GeneralReg::RSP, offset, src)
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64GeneralReg) {
|
fn mov_stack32_reg(
|
||||||
mov_base64_offset32_reg64(buf, X86_64GeneralReg::RSP, offset, src)
|
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)]
|
#[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.
|
// 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.
|
/// `MOV r/m64,r64` -> Move r64 to r/m64, where m64 references a base + offset.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mov_base64_offset32_reg64(
|
fn mov_base64_offset32_reg64(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue