mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
move storing args to use storage manager
This commit is contained in:
parent
d578dae3ef
commit
9fa420f871
4 changed files with 141 additions and 244 deletions
|
@ -1,8 +1,7 @@
|
|||
use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait, SymbolStorage};
|
||||
use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait};
|
||||
use crate::Relocation;
|
||||
use bumpalo::collections::Vec;
|
||||
use packed_struct::prelude::*;
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::Layout;
|
||||
|
@ -265,11 +264,17 @@ impl CallConv<AArch64GeneralReg, AArch64FloatReg, AArch64Assembler> for AArch64C
|
|||
#[inline(always)]
|
||||
fn store_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
_symbol_map: &MutMap<Symbol, SymbolStorage<AArch64GeneralReg, AArch64FloatReg>>,
|
||||
_storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
AArch64GeneralReg,
|
||||
AArch64FloatReg,
|
||||
AArch64Assembler,
|
||||
AArch64Call,
|
||||
>,
|
||||
_args: &'a [Symbol],
|
||||
_arg_layouts: &[Layout<'a>],
|
||||
_ret_layout: &Layout<'a>,
|
||||
) -> u32 {
|
||||
) {
|
||||
todo!("Storing args for AArch64");
|
||||
}
|
||||
|
||||
|
|
|
@ -82,12 +82,12 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
|||
// It returns the amount of stack space needed to temporarily store the args.
|
||||
fn store_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &MutMap<Symbol, SymbolStorage<GeneralReg, FloatReg>>,
|
||||
storage_manager: &mut StorageManager<'a, GeneralReg, FloatReg, ASM, Self>,
|
||||
args: &'a [Symbol],
|
||||
arg_layouts: &[Layout<'a>],
|
||||
// ret_layout is needed because if it is a complex type, we pass a pointer as the first arg.
|
||||
ret_layout: &Layout<'a>,
|
||||
) -> u32;
|
||||
);
|
||||
|
||||
/// return_complex_symbol returns the specified complex/non-primative symbol.
|
||||
/// It uses the layout to determine how the data should be returned.
|
||||
|
@ -553,14 +553,13 @@ impl<
|
|||
.push_used_caller_saved_regs_to_stack(&mut self.buf);
|
||||
|
||||
// Put values in param regs or on top of the stack.
|
||||
let tmp_stack_size = CC::store_args(
|
||||
CC::store_args(
|
||||
&mut self.buf,
|
||||
&self.symbol_storage_map,
|
||||
&mut self.storage_manager,
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
);
|
||||
self.fn_call_stack_size = std::cmp::max(self.fn_call_stack_size, tmp_stack_size);
|
||||
|
||||
// Call function and generate reloc.
|
||||
ASM::call(&mut self.buf, &mut self.relocs, fn_name);
|
||||
|
@ -754,14 +753,13 @@ impl<
|
|||
self.storage_manager
|
||||
.push_used_caller_saved_regs_to_stack(&mut self.buf);
|
||||
|
||||
let tmp_stack_size = CC::store_args(
|
||||
CC::store_args(
|
||||
&mut self.buf,
|
||||
&self.symbol_storage_map,
|
||||
&mut self.storage_manager,
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
);
|
||||
self.fn_call_stack_size = std::cmp::max(self.fn_call_stack_size, tmp_stack_size);
|
||||
|
||||
let jmp_location = self.buf.len();
|
||||
let start_offset = ASM::jmp_imm32(&mut self.buf, 0x1234_5678);
|
||||
|
|
|
@ -9,6 +9,7 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout};
|
||||
use roc_target::TargetInfo;
|
||||
use std::cmp::max;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -105,6 +106,9 @@ pub struct StorageManager<
|
|||
|
||||
free_stack_chunks: Vec<'a, (i32, u32)>,
|
||||
stack_size: u32,
|
||||
|
||||
// The amount of extra stack space needed to pass args for function calling.
|
||||
fn_call_stack_size: u32,
|
||||
}
|
||||
|
||||
pub fn new_storage_manager<
|
||||
|
@ -132,6 +136,7 @@ pub fn new_storage_manager<
|
|||
float_used_callee_saved_regs: MutSet::default(),
|
||||
free_stack_chunks: bumpalo::vec![in env.arena],
|
||||
stack_size: 0,
|
||||
fn_call_stack_size: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,6 +163,7 @@ impl<
|
|||
.extend_from_slice(CC::FLOAT_DEFAULT_FREE_REGS);
|
||||
self.free_stack_chunks.clear();
|
||||
self.stack_size = 0;
|
||||
self.fn_call_stack_size = 0;
|
||||
}
|
||||
|
||||
// Returns true if the symbol is storing a primitive value.
|
||||
|
@ -734,6 +740,11 @@ impl<
|
|||
.insert(Symbol::RET_POINTER, Reg(General(reg)));
|
||||
}
|
||||
|
||||
// updates the function call stack size to the max of its current value and the size need for this call.
|
||||
pub fn update_fn_call_stack_size(&mut self, tmp_size: u32) {
|
||||
self.fn_call_stack_size = max(self.fn_call_stack_size, tmp_size);
|
||||
}
|
||||
|
||||
/// claim_stack_area is the public wrapper around claim_stack_size.
|
||||
/// It also deals with updating symbol storage.
|
||||
/// It returns the base offset of the stack area.
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait, SymbolStorage};
|
||||
use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait};
|
||||
use crate::{
|
||||
single_register_floats, single_register_integers, single_register_layouts, Relocation,
|
||||
};
|
||||
use bumpalo::collections::Vec;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout};
|
||||
|
@ -255,150 +254,88 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
#[inline(always)]
|
||||
fn store_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &MutMap<Symbol, SymbolStorage<X86_64GeneralReg, X86_64FloatReg>>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
X86_64SystemV,
|
||||
>,
|
||||
args: &'a [Symbol],
|
||||
arg_layouts: &[Layout<'a>],
|
||||
ret_layout: &Layout<'a>,
|
||||
) -> u32 {
|
||||
let mut stack_offset = Self::SHADOW_SPACE_SIZE as i32;
|
||||
) {
|
||||
let mut tmp_stack_offset = Self::SHADOW_SPACE_SIZE as i32;
|
||||
if Self::returns_via_arg_pointer(ret_layout) {
|
||||
// Save space on the stack for the arg we will return.
|
||||
storage_manager
|
||||
.claim_stack_area(&Symbol::RET_POINTER, ret_layout.stack_size(TARGET_INFO));
|
||||
todo!("claim first parama reg for the address");
|
||||
}
|
||||
let mut general_i = 0;
|
||||
let mut float_i = 0;
|
||||
// For most return layouts we will do nothing.
|
||||
// In some cases, we need to put the return address as the first arg.
|
||||
match ret_layout {
|
||||
single_register_layouts!() | Layout::Builtin(Builtin::Str) | Layout::Struct([]) => {
|
||||
// Nothing needs to be done for any of these cases.
|
||||
}
|
||||
x => {
|
||||
todo!("receiving return type, {:?}", x);
|
||||
}
|
||||
}
|
||||
for (i, layout) in arg_layouts.iter().enumerate() {
|
||||
for (i, (sym, layout)) in args.iter().zip(arg_layouts.iter()).enumerate() {
|
||||
match layout {
|
||||
single_register_integers!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
internal_error!("function argument does not reference any symbol")
|
||||
}
|
||||
};
|
||||
if general_i < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst = Self::GENERAL_PARAM_REGS[general_i];
|
||||
match storage {
|
||||
SymbolStorage::GeneralReg(reg)
|
||||
| SymbolStorage::BaseAndGeneralReg { reg, .. } => {
|
||||
X86_64Assembler::mov_reg64_reg64(buf, dst, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst, *offset);
|
||||
}
|
||||
SymbolStorage::FloatReg(_) | SymbolStorage::BaseAndFloatReg { .. } => {
|
||||
internal_error!("Cannot load floating point symbol into GeneralReg")
|
||||
}
|
||||
}
|
||||
storage_manager.load_to_specified_general_reg(
|
||||
buf,
|
||||
sym,
|
||||
Self::GENERAL_PARAM_REGS[i],
|
||||
);
|
||||
general_i += 1;
|
||||
} else {
|
||||
// Load the value to the stack.
|
||||
match storage {
|
||||
SymbolStorage::GeneralReg(reg)
|
||||
| SymbolStorage::BaseAndGeneralReg { reg, .. } => {
|
||||
X86_64Assembler::mov_stack32_reg64(buf, stack_offset, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
// Use RAX as a tmp reg because it will be free before function calls.
|
||||
X86_64Assembler::mov_reg64_base32(
|
||||
// Copy to stack using return reg as buffer.
|
||||
storage_manager.load_to_specified_general_reg(
|
||||
buf,
|
||||
X86_64GeneralReg::RAX,
|
||||
*offset,
|
||||
sym,
|
||||
Self::GENERAL_RETURN_REGS[0],
|
||||
);
|
||||
X86_64Assembler::mov_stack32_reg64(
|
||||
buf,
|
||||
stack_offset,
|
||||
X86_64GeneralReg::RAX,
|
||||
tmp_stack_offset,
|
||||
Self::GENERAL_RETURN_REGS[0],
|
||||
);
|
||||
}
|
||||
SymbolStorage::FloatReg(_) | SymbolStorage::BaseAndFloatReg { .. } => {
|
||||
internal_error!("Cannot load floating point symbol into GeneralReg")
|
||||
}
|
||||
}
|
||||
stack_offset += 8;
|
||||
tmp_stack_offset += 8;
|
||||
}
|
||||
}
|
||||
single_register_floats!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
internal_error!("function argument does not reference any symbol")
|
||||
}
|
||||
};
|
||||
if float_i < Self::FLOAT_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst = Self::FLOAT_PARAM_REGS[float_i];
|
||||
match storage {
|
||||
SymbolStorage::FloatReg(reg)
|
||||
| SymbolStorage::BaseAndFloatReg { reg, .. } => {
|
||||
X86_64Assembler::mov_freg64_freg64(buf, dst, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
X86_64Assembler::mov_freg64_base32(buf, dst, *offset);
|
||||
}
|
||||
SymbolStorage::GeneralReg(_)
|
||||
| SymbolStorage::BaseAndGeneralReg { .. } => {
|
||||
internal_error!("Cannot load general symbol into FloatReg")
|
||||
}
|
||||
}
|
||||
storage_manager.load_to_specified_float_reg(
|
||||
buf,
|
||||
sym,
|
||||
Self::FLOAT_PARAM_REGS[i],
|
||||
);
|
||||
float_i += 1;
|
||||
} else {
|
||||
// Load the value to the stack.
|
||||
match storage {
|
||||
SymbolStorage::FloatReg(reg)
|
||||
| SymbolStorage::BaseAndFloatReg { reg, .. } => {
|
||||
X86_64Assembler::mov_stack32_freg64(buf, stack_offset, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
// Use XMM0 as a tmp reg because it will be free before function calls.
|
||||
X86_64Assembler::mov_freg64_base32(
|
||||
// Copy to stack using return reg as buffer.
|
||||
storage_manager.load_to_specified_float_reg(
|
||||
buf,
|
||||
X86_64FloatReg::XMM0,
|
||||
*offset,
|
||||
sym,
|
||||
Self::FLOAT_RETURN_REGS[0],
|
||||
);
|
||||
X86_64Assembler::mov_stack32_freg64(
|
||||
buf,
|
||||
stack_offset,
|
||||
X86_64FloatReg::XMM0,
|
||||
tmp_stack_offset,
|
||||
Self::FLOAT_RETURN_REGS[0],
|
||||
);
|
||||
}
|
||||
SymbolStorage::GeneralReg(_)
|
||||
| SymbolStorage::BaseAndGeneralReg { .. } => {
|
||||
internal_error!("Cannot load general symbol into FloatReg")
|
||||
}
|
||||
}
|
||||
stack_offset += 8;
|
||||
tmp_stack_offset += 8;
|
||||
}
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
internal_error!("function argument does not reference any symbol")
|
||||
}
|
||||
};
|
||||
if general_i + 1 < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst1 = Self::GENERAL_PARAM_REGS[general_i];
|
||||
let dst2 = Self::GENERAL_PARAM_REGS[general_i + 1];
|
||||
match storage {
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst1, *offset);
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst2, *offset + 8);
|
||||
}
|
||||
_ => {
|
||||
internal_error!(
|
||||
"Strings only support being loaded from base offsets"
|
||||
let (base_offset, _size) = storage_manager.stack_offset_and_size(sym);
|
||||
debug_assert_eq!(base_offset % 8, 0);
|
||||
X86_64Assembler::mov_reg64_base32(
|
||||
buf,
|
||||
Self::GENERAL_PARAM_REGS[general_i],
|
||||
base_offset,
|
||||
);
|
||||
X86_64Assembler::mov_reg64_base32(
|
||||
buf,
|
||||
Self::GENERAL_PARAM_REGS[general_i + 1],
|
||||
base_offset + 8,
|
||||
);
|
||||
}
|
||||
}
|
||||
general_i += 2;
|
||||
} else {
|
||||
todo!("calling functions with strings on the stack");
|
||||
|
@ -410,7 +347,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
}
|
||||
}
|
||||
stack_offset as u32
|
||||
storage_manager.update_fn_call_stack_size(tmp_stack_offset as u32);
|
||||
}
|
||||
|
||||
fn return_complex_symbol<'a>(
|
||||
|
@ -431,7 +368,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
Layout::Struct([]) => {}
|
||||
Layout::Builtin(Builtin::Str | Builtin::List(_)) => {
|
||||
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);
|
||||
X86_64Assembler::mov_reg64_base32(buf, Self::GENERAL_RETURN_REGS[0], base_offset);
|
||||
X86_64Assembler::mov_reg64_base32(
|
||||
|
@ -650,122 +587,68 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
#[inline(always)]
|
||||
fn store_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &MutMap<Symbol, SymbolStorage<X86_64GeneralReg, X86_64FloatReg>>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
X86_64WindowsFastcall,
|
||||
>,
|
||||
args: &'a [Symbol],
|
||||
arg_layouts: &[Layout<'a>],
|
||||
ret_layout: &Layout<'a>,
|
||||
) -> u32 {
|
||||
let mut stack_offset = Self::SHADOW_SPACE_SIZE as i32;
|
||||
// For most return layouts we will do nothing.
|
||||
// In some cases, we need to put the return address as the first arg.
|
||||
match ret_layout {
|
||||
single_register_layouts!() | Layout::Struct([]) => {
|
||||
// Nothing needs to be done for any of these cases.
|
||||
) {
|
||||
let mut tmp_stack_offset = Self::SHADOW_SPACE_SIZE as i32;
|
||||
if Self::returns_via_arg_pointer(ret_layout) {
|
||||
// Save space on the stack for the arg we will return.
|
||||
storage_manager
|
||||
.claim_stack_area(&Symbol::RET_POINTER, ret_layout.stack_size(TARGET_INFO));
|
||||
todo!("claim first parama reg for the address");
|
||||
}
|
||||
x => {
|
||||
todo!("receiving return type, {:?}", x);
|
||||
}
|
||||
}
|
||||
for (i, layout) in arg_layouts.iter().enumerate() {
|
||||
for (i, (sym, layout)) in args.iter().zip(arg_layouts.iter()).enumerate() {
|
||||
match layout {
|
||||
single_register_integers!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
internal_error!("function argument does not reference any symbol")
|
||||
}
|
||||
};
|
||||
if i < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst = Self::GENERAL_PARAM_REGS[i];
|
||||
match storage {
|
||||
SymbolStorage::GeneralReg(reg)
|
||||
| SymbolStorage::BaseAndGeneralReg { reg, .. } => {
|
||||
X86_64Assembler::mov_reg64_reg64(buf, dst, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
X86_64Assembler::mov_reg64_base32(buf, dst, *offset);
|
||||
}
|
||||
SymbolStorage::FloatReg(_) | SymbolStorage::BaseAndFloatReg { .. } => {
|
||||
internal_error!("Cannot load floating point symbol into GeneralReg")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Load the value to the stack.
|
||||
match storage {
|
||||
SymbolStorage::GeneralReg(reg)
|
||||
| SymbolStorage::BaseAndGeneralReg { reg, .. } => {
|
||||
X86_64Assembler::mov_stack32_reg64(buf, stack_offset, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
// Use RAX as a tmp reg because it will be free before function calls.
|
||||
X86_64Assembler::mov_reg64_base32(
|
||||
storage_manager.load_to_specified_general_reg(
|
||||
buf,
|
||||
X86_64GeneralReg::RAX,
|
||||
*offset,
|
||||
sym,
|
||||
Self::GENERAL_PARAM_REGS[i],
|
||||
);
|
||||
} else {
|
||||
// Copy to stack using return reg as buffer.
|
||||
storage_manager.load_to_specified_general_reg(
|
||||
buf,
|
||||
sym,
|
||||
Self::GENERAL_RETURN_REGS[0],
|
||||
);
|
||||
X86_64Assembler::mov_stack32_reg64(
|
||||
buf,
|
||||
stack_offset,
|
||||
X86_64GeneralReg::RAX,
|
||||
tmp_stack_offset,
|
||||
Self::GENERAL_RETURN_REGS[0],
|
||||
);
|
||||
}
|
||||
SymbolStorage::FloatReg(_) | SymbolStorage::BaseAndFloatReg { .. } => {
|
||||
internal_error!("Cannot load floating point symbol into GeneralReg")
|
||||
}
|
||||
}
|
||||
stack_offset += 8;
|
||||
tmp_stack_offset += 8;
|
||||
}
|
||||
}
|
||||
single_register_floats!() => {
|
||||
let storage = match symbol_map.get(&args[i]) {
|
||||
Some(storage) => storage,
|
||||
None => {
|
||||
internal_error!("function argument does not reference any symbol")
|
||||
}
|
||||
};
|
||||
if i < Self::FLOAT_PARAM_REGS.len() {
|
||||
// Load the value to the param reg.
|
||||
let dst = Self::FLOAT_PARAM_REGS[i];
|
||||
match storage {
|
||||
SymbolStorage::FloatReg(reg)
|
||||
| SymbolStorage::BaseAndFloatReg { reg, .. } => {
|
||||
X86_64Assembler::mov_freg64_freg64(buf, dst, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
X86_64Assembler::mov_freg64_base32(buf, dst, *offset);
|
||||
}
|
||||
SymbolStorage::GeneralReg(_)
|
||||
| SymbolStorage::BaseAndGeneralReg { .. } => {
|
||||
internal_error!("Cannot load general symbol into FloatReg")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Load the value to the stack.
|
||||
match storage {
|
||||
SymbolStorage::FloatReg(reg)
|
||||
| SymbolStorage::BaseAndFloatReg { reg, .. } => {
|
||||
X86_64Assembler::mov_stack32_freg64(buf, stack_offset, *reg);
|
||||
}
|
||||
SymbolStorage::Base { offset, .. } => {
|
||||
// Use XMM0 as a tmp reg because it will be free before function calls.
|
||||
X86_64Assembler::mov_freg64_base32(
|
||||
storage_manager.load_to_specified_float_reg(
|
||||
buf,
|
||||
X86_64FloatReg::XMM0,
|
||||
*offset,
|
||||
sym,
|
||||
Self::FLOAT_PARAM_REGS[i],
|
||||
);
|
||||
} else {
|
||||
// Copy to stack using return reg as buffer.
|
||||
storage_manager.load_to_specified_float_reg(
|
||||
buf,
|
||||
sym,
|
||||
Self::FLOAT_RETURN_REGS[0],
|
||||
);
|
||||
X86_64Assembler::mov_stack32_freg64(
|
||||
buf,
|
||||
stack_offset,
|
||||
X86_64FloatReg::XMM0,
|
||||
tmp_stack_offset,
|
||||
Self::FLOAT_RETURN_REGS[0],
|
||||
);
|
||||
}
|
||||
SymbolStorage::GeneralReg(_)
|
||||
| SymbolStorage::BaseAndGeneralReg { .. } => {
|
||||
internal_error!("Cannot load general symbol into FloatReg")
|
||||
}
|
||||
}
|
||||
stack_offset += 8;
|
||||
tmp_stack_offset += 8;
|
||||
}
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
|
@ -778,7 +661,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
}
|
||||
}
|
||||
}
|
||||
stack_offset as u32
|
||||
storage_manager.update_fn_call_stack_size(tmp_stack_offset as u32);
|
||||
}
|
||||
|
||||
fn return_complex_symbol<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue