diff --git a/crates/compiler/gen_dev/src/generic64/aarch64.rs b/crates/compiler/gen_dev/src/generic64/aarch64.rs index 518d15ba71..9e3ebcfba8 100644 --- a/crates/compiler/gen_dev/src/generic64/aarch64.rs +++ b/crates/compiler/gen_dev/src/generic64/aarch64.rs @@ -752,9 +752,33 @@ impl AArch64CallLoadArgs { storage_manager.no_data(&sym); } _ if stack_size > 16 => { - // TODO: Double check this. - storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size); - self.argument_offset += stack_size as i32; + match AArch64Call::GENERAL_PARAM_REGS.get(self.general_i) { + Some(ptr_reg) => { + // if there is a general purpose register available, use it to store a pointer to the value + let base_offset = storage_manager.claim_stack_area_layout( + layout_interner, + sym, + in_layout, + ); + let tmp_reg = AArch64Call::GENERAL_RETURN_REGS[0]; + + super::x86_64::copy_to_base_offset::<_, _, AArch64Assembler>( + buf, + base_offset, + stack_size, + *ptr_reg, + tmp_reg, + 0, + ); + + self.general_i += 1; + } + None => { + // else, pass the value implicitly by copying to the stack (of the new frame) + storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size); + self.argument_offset += stack_size as i32; + } + } } LayoutRepr::LambdaSet(lambda_set) => self.load_arg( buf, @@ -897,19 +921,30 @@ impl AArch64CallStoreArgs { } _ if layout_interner.stack_size(in_layout) == 0 => {} _ if layout_interner.stack_size(in_layout) > 16 => { - // TODO: Double check this. - // Just copy onto the stack. - let stack_offset = self.tmp_stack_offset; + match Self::GENERAL_PARAM_REGS.get(self.general_i) { + Some(reg) => { + // if there is a general purpose register available, use it to store a pointer to the value + let (base_offset, _size) = storage_manager.stack_offset_and_size(&sym); - let size = copy_symbol_to_stack_offset::( - buf, - storage_manager, - sym, - tmp_reg, - stack_offset, - ); + ASM::add_reg64_reg64_imm32(buf, *reg, AArch64GeneralReg::FP, base_offset); - self.tmp_stack_offset += size as i32; + self.general_i += 1; + } + None => { + // else, pass the value implicitly by copying to the stack (of the new frame) + let stack_offset = self.tmp_stack_offset; + + let size = copy_symbol_to_stack_offset::( + buf, + storage_manager, + sym, + tmp_reg, + stack_offset, + ); + + self.tmp_stack_offset += size as i32; + } + } } LayoutRepr::LambdaSet(lambda_set) => self.store_arg( buf, diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index 68f7c68590..9f95e3acbe 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -601,7 +601,7 @@ where size } -fn copy_to_base_offset( +pub(crate) fn copy_to_base_offset( buf: &mut Vec<'_, u8>, dst_base_offset: i32, stack_size: u32, diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 6d47398614..0eb2beef16 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -3332,6 +3332,16 @@ fn box_num() { assert_evals_to!("Box.box 123u64", RocBox::new(123), RocBox) } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_record() { + assert_evals_to!( + "Box.box { x: 1u64, y: 2u64 }", + RocBox::new((1u64, 2u64)), + RocBox<(u64, u64)> + ); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn box_str() {