mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
fix argument passing for systemv
This commit is contained in:
parent
42d324299d
commit
82b96395e2
2 changed files with 142 additions and 13 deletions
|
@ -601,7 +601,7 @@ where
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_to_base_offset<GeneralReg, FloatReg, ASM>(
|
pub(crate) fn copy_to_base_offset<GeneralReg, FloatReg, ASM>(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
dst_base_offset: i32,
|
dst_base_offset: i32,
|
||||||
stack_size: u32,
|
stack_size: u32,
|
||||||
|
@ -727,12 +727,14 @@ impl X64_64SystemVStoreArgs {
|
||||||
lambda_set.runtime_representation(),
|
lambda_set.runtime_representation(),
|
||||||
),
|
),
|
||||||
LayoutRepr::Struct { .. } => {
|
LayoutRepr::Struct { .. } => {
|
||||||
let stack_offset = self.tmp_stack_offset;
|
let stack_size = layout_interner.stack_size(in_layout);
|
||||||
|
if stack_size <= 8 {
|
||||||
let size =
|
self.store_arg_64bit(buf, storage_manager, sym);
|
||||||
copy_symbol_to_stack_offset(buf, storage_manager, sym, tmp_reg, stack_offset);
|
} else if stack_size <= 16 {
|
||||||
|
self.store_arg_128bit(buf, storage_manager, sym);
|
||||||
self.tmp_stack_offset += size as i32;
|
} else {
|
||||||
|
unreachable!("covered by earlier branch");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
|
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
|
||||||
let stack_offset = self.tmp_stack_offset;
|
let stack_offset = self.tmp_stack_offset;
|
||||||
|
@ -796,6 +798,66 @@ impl X64_64SystemVStoreArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn store_arg_64bit<'a>(
|
||||||
|
&mut self,
|
||||||
|
buf: &mut Vec<'a, u8>,
|
||||||
|
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64SystemV>,
|
||||||
|
sym: Symbol,
|
||||||
|
) {
|
||||||
|
type ASM = X86_64Assembler;
|
||||||
|
|
||||||
|
let (offset, _) = storage_manager.stack_offset_and_size(&sym);
|
||||||
|
|
||||||
|
match Self::GENERAL_PARAM_REGS.get(self.general_i) {
|
||||||
|
Some(reg) => {
|
||||||
|
ASM::mov_reg64_base32(buf, *reg, offset);
|
||||||
|
|
||||||
|
self.general_i += 1;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Copy to stack using return reg as buffer.
|
||||||
|
let reg = X86_64GeneralReg::RAX;
|
||||||
|
|
||||||
|
ASM::mov_reg64_base32(buf, reg, offset);
|
||||||
|
ASM::mov_stack32_reg64(buf, self.tmp_stack_offset, reg);
|
||||||
|
|
||||||
|
self.tmp_stack_offset += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store_arg_128bit<'a>(
|
||||||
|
&mut self,
|
||||||
|
buf: &mut Vec<'a, u8>,
|
||||||
|
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64SystemV>,
|
||||||
|
sym: Symbol,
|
||||||
|
) {
|
||||||
|
type ASM = X86_64Assembler;
|
||||||
|
|
||||||
|
let (offset, _) = storage_manager.stack_offset_and_size(&sym);
|
||||||
|
|
||||||
|
if self.general_i + 1 < Self::GENERAL_PARAM_REGS.len() {
|
||||||
|
let reg1 = Self::GENERAL_PARAM_REGS[self.general_i];
|
||||||
|
let reg2 = Self::GENERAL_PARAM_REGS[self.general_i + 1];
|
||||||
|
|
||||||
|
ASM::mov_reg64_base32(buf, reg1, offset);
|
||||||
|
ASM::mov_reg64_base32(buf, reg2, offset + 8);
|
||||||
|
|
||||||
|
self.general_i += 2;
|
||||||
|
} else {
|
||||||
|
// Copy to stack using return reg as buffer.
|
||||||
|
let reg = X86_64GeneralReg::RAX;
|
||||||
|
|
||||||
|
ASM::mov_reg64_base32(buf, reg, offset);
|
||||||
|
ASM::mov_stack32_reg64(buf, self.tmp_stack_offset, reg);
|
||||||
|
|
||||||
|
ASM::mov_reg64_base32(buf, reg, offset + 8);
|
||||||
|
ASM::mov_stack32_reg64(buf, self.tmp_stack_offset + 8, reg);
|
||||||
|
|
||||||
|
self.tmp_stack_offset += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct X64_64WindowsFastCallStoreArgs {
|
struct X64_64WindowsFastCallStoreArgs {
|
||||||
|
@ -1001,15 +1063,31 @@ impl X64_64SystemVLoadArgs {
|
||||||
lambda_set.runtime_representation(),
|
lambda_set.runtime_representation(),
|
||||||
),
|
),
|
||||||
LayoutRepr::Struct { .. } => {
|
LayoutRepr::Struct { .. } => {
|
||||||
// for now, just also store this on the stack
|
if stack_size <= 8 {
|
||||||
storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size);
|
self.load_arg_general_64bit(
|
||||||
self.argument_offset += stack_size as i32;
|
buf,
|
||||||
|
storage_manager,
|
||||||
|
layout_interner,
|
||||||
|
sym,
|
||||||
|
in_layout,
|
||||||
|
);
|
||||||
|
} else if stack_size <= 16 {
|
||||||
|
self.load_arg_general_128bit(
|
||||||
|
buf,
|
||||||
|
storage_manager,
|
||||||
|
layout_interner,
|
||||||
|
sym,
|
||||||
|
in_layout,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unreachable!("covered by an earlier branch")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::U128 | IntWidth::I128)) => {
|
LayoutRepr::Builtin(Builtin::Int(IntWidth::U128 | IntWidth::I128)) => {
|
||||||
self.load_arg_general_128bit(buf, storage_manager, sym);
|
self.load_arg_general_128bit(buf, storage_manager, layout_interner, sym, in_layout);
|
||||||
}
|
}
|
||||||
LayoutRepr::Builtin(Builtin::Decimal) => {
|
LayoutRepr::Builtin(Builtin::Decimal) => {
|
||||||
self.load_arg_general_128bit(buf, storage_manager, sym);
|
self.load_arg_general_128bit(buf, storage_manager, layout_interner, sym, in_layout);
|
||||||
}
|
}
|
||||||
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
|
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
|
||||||
// for now, just also store this on the stack
|
// for now, just also store this on the stack
|
||||||
|
@ -1039,11 +1117,41 @@ impl X64_64SystemVLoadArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_arg_general_64bit(
|
||||||
|
&mut self,
|
||||||
|
buf: &mut Vec<u8>,
|
||||||
|
storage_manager: &mut X86_64StorageManager<'_, '_, X86_64SystemV>,
|
||||||
|
layout_interner: &mut STLayoutInterner<'_>,
|
||||||
|
sym: Symbol,
|
||||||
|
in_layout: InLayout<'_>,
|
||||||
|
) {
|
||||||
|
type ASM = X86_64Assembler;
|
||||||
|
|
||||||
|
let reg1 = X86_64SystemV::GENERAL_PARAM_REGS.get(self.general_i);
|
||||||
|
|
||||||
|
match reg1 {
|
||||||
|
Some(reg1) => {
|
||||||
|
let offset =
|
||||||
|
storage_manager.claim_stack_area_layout(layout_interner, sym, in_layout);
|
||||||
|
|
||||||
|
ASM::mov_base32_reg64(buf, offset, *reg1);
|
||||||
|
|
||||||
|
self.general_i += 1;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
storage_manager.complex_stack_arg(&sym, self.argument_offset, 8);
|
||||||
|
self.argument_offset += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn load_arg_general_128bit(
|
fn load_arg_general_128bit(
|
||||||
&mut self,
|
&mut self,
|
||||||
buf: &mut Vec<u8>,
|
buf: &mut Vec<u8>,
|
||||||
storage_manager: &mut X86_64StorageManager<'_, '_, X86_64SystemV>,
|
storage_manager: &mut X86_64StorageManager<'_, '_, X86_64SystemV>,
|
||||||
|
layout_interner: &mut STLayoutInterner<'_>,
|
||||||
sym: Symbol,
|
sym: Symbol,
|
||||||
|
in_layout: InLayout<'_>,
|
||||||
) {
|
) {
|
||||||
type ASM = X86_64Assembler;
|
type ASM = X86_64Assembler;
|
||||||
|
|
||||||
|
@ -1052,7 +1160,8 @@ impl X64_64SystemVLoadArgs {
|
||||||
|
|
||||||
match (reg1, reg2) {
|
match (reg1, reg2) {
|
||||||
(Some(reg1), Some(reg2)) => {
|
(Some(reg1), Some(reg2)) => {
|
||||||
let offset = storage_manager.claim_stack_area_with_alignment(sym, 16, 16);
|
let offset =
|
||||||
|
storage_manager.claim_stack_area_layout(layout_interner, sym, in_layout);
|
||||||
|
|
||||||
ASM::mov_base32_reg64(buf, offset, *reg1);
|
ASM::mov_base32_reg64(buf, offset, *reg1);
|
||||||
ASM::mov_base32_reg64(buf, offset + 8, *reg2);
|
ASM::mov_base32_reg64(buf, offset + 8, *reg2);
|
||||||
|
|
|
@ -87,6 +87,26 @@ fn f64_record() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn pass_bool_record() {
|
||||||
|
// found a bug there the register to use was not incremented correctly
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
true : Bool
|
||||||
|
true = Bool.true
|
||||||
|
|
||||||
|
f = \_, x -> x
|
||||||
|
|
||||||
|
f { x: true, y: true } 23
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
23,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn fn_record() {
|
fn fn_record() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue