mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
convert loading args to storage manager
This commit is contained in:
parent
76f03c722f
commit
907050ceaa
@ -249,11 +249,16 @@ impl CallConv<AArch64GeneralReg, AArch64FloatReg, AArch64Assembler> for AArch64C
|
||||
#[inline(always)]
|
||||
fn load_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
_symbol_map: &mut MutMap<Symbol, SymbolStorage<AArch64GeneralReg, AArch64FloatReg>>,
|
||||
_storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
AArch64GeneralReg,
|
||||
AArch64FloatReg,
|
||||
AArch64Assembler,
|
||||
AArch64Call,
|
||||
>,
|
||||
_args: &'a [(Layout<'a>, Symbol)],
|
||||
_ret_layout: &Layout<'a>,
|
||||
mut _stack_size: u32,
|
||||
) -> u32 {
|
||||
) {
|
||||
todo!("Loading args for AArch64");
|
||||
}
|
||||
|
||||
|
@ -72,12 +72,11 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
||||
// It returns the total stack space after loading the args.
|
||||
fn load_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &mut MutMap<Symbol, SymbolStorage<GeneralReg, FloatReg>>,
|
||||
storage_manager: &mut StorageManager<'a, GeneralReg, FloatReg, ASM, Self>,
|
||||
args: &'a [(Layout<'a>, Symbol)],
|
||||
// ret_layout is needed because if it is a complex type, we pass a pointer as the first arg.
|
||||
ret_layout: &Layout<'a>,
|
||||
stack_size: u32,
|
||||
) -> u32;
|
||||
);
|
||||
|
||||
// store_args stores the args in registers and on the stack for function calling.
|
||||
// It returns the amount of stack space needed to temporarily store the args.
|
||||
@ -262,7 +261,7 @@ pub enum SymbolStorage<GeneralReg: RegTrait, FloatReg: RegTrait> {
|
||||
},
|
||||
}
|
||||
|
||||
pub trait RegTrait: Copy + Eq + std::hash::Hash + std::fmt::Debug + 'static {
|
||||
pub trait RegTrait: Copy + PartialEq + Eq + std::hash::Hash + std::fmt::Debug + 'static {
|
||||
fn value(&self) -> u8;
|
||||
}
|
||||
|
||||
@ -525,27 +524,7 @@ impl<
|
||||
}
|
||||
|
||||
fn load_args(&mut self, args: &'a [(Layout<'a>, Symbol)], ret_layout: &Layout<'a>) {
|
||||
self.stack_size = CC::load_args(
|
||||
&mut self.buf,
|
||||
&mut self.symbol_storage_map,
|
||||
args,
|
||||
ret_layout,
|
||||
self.stack_size,
|
||||
);
|
||||
// Update used and free regs.
|
||||
for (sym, storage) in &self.symbol_storage_map {
|
||||
match storage {
|
||||
SymbolStorage::GeneralReg(reg) | SymbolStorage::BaseAndGeneralReg { reg, .. } => {
|
||||
self.general_free_regs.retain(|r| *r != *reg);
|
||||
self.general_used_regs.push((*reg, *sym));
|
||||
}
|
||||
SymbolStorage::FloatReg(reg) | SymbolStorage::BaseAndFloatReg { reg, .. } => {
|
||||
self.float_free_regs.retain(|r| *r != *reg);
|
||||
self.float_used_regs.push((*reg, *sym));
|
||||
}
|
||||
SymbolStorage::Base { .. } => {}
|
||||
}
|
||||
}
|
||||
CC::load_args(&mut self.buf, &mut self.storage_manager, args, ret_layout);
|
||||
}
|
||||
|
||||
/// Used for generating wrappers for malloc/realloc/free
|
||||
|
@ -669,6 +669,37 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
// Specifies a symbol is loaded at the specified general register.
|
||||
pub fn general_reg_arg(&mut self, sym: &Symbol, reg: GeneralReg) {
|
||||
self.symbol_storage_map.insert(*sym, Reg(General(reg)));
|
||||
self.general_free_regs.retain(|r| *r != reg);
|
||||
self.general_used_regs.push((reg, *sym));
|
||||
}
|
||||
|
||||
// Specifies a symbol is loaded at the specified float register.
|
||||
pub fn float_reg_arg(&mut self, sym: &Symbol, reg: FloatReg) {
|
||||
self.symbol_storage_map.insert(*sym, Reg(Float(reg)));
|
||||
self.float_free_regs.retain(|r| *r != reg);
|
||||
self.float_used_regs.push((reg, *sym));
|
||||
}
|
||||
|
||||
// Specifies a primitive is loaded at the specific base offset.
|
||||
pub fn primitive_stack_arg(&mut self, sym: &Symbol, base_offset: i32) {
|
||||
self.symbol_storage_map.insert(
|
||||
*sym,
|
||||
Stack(Primitive {
|
||||
base_offset,
|
||||
reg: None,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// Loads the arg pointer symbol to the specified general reg.
|
||||
pub fn ret_pionter_arg(&mut self, reg: GeneralReg) {
|
||||
self.symbol_storage_map
|
||||
.insert(Symbol::RET_POINTER, Reg(General(reg)));
|
||||
}
|
||||
|
||||
/// 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.
|
||||
|
@ -194,81 +194,54 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
||||
#[inline(always)]
|
||||
fn load_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &mut MutMap<Symbol, SymbolStorage<X86_64GeneralReg, X86_64FloatReg>>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
X86_64SystemV,
|
||||
>,
|
||||
args: &'a [(Layout<'a>, Symbol)],
|
||||
ret_layout: &Layout<'a>,
|
||||
mut stack_size: u32,
|
||||
) -> u32 {
|
||||
let mut arg_offset = Self::SHADOW_SPACE_SIZE as i32 + 8; // 8 is the size of the pushed base pointer.
|
||||
) {
|
||||
let mut arg_offset = Self::SHADOW_SPACE_SIZE as i32 + 16; // 16 is the size of the pushed return address and base pointer.
|
||||
let mut general_i = 0;
|
||||
let mut float_i = 0;
|
||||
if X86_64SystemV::returns_via_arg_pointer(ret_layout) {
|
||||
symbol_map.insert(
|
||||
Symbol::RET_POINTER,
|
||||
SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[general_i]),
|
||||
);
|
||||
storage_manager.ret_pionter_arg(Self::GENERAL_PARAM_REGS[0]);
|
||||
general_i += 1;
|
||||
}
|
||||
for (layout, sym) in args.iter() {
|
||||
match layout {
|
||||
single_register_integers!() => {
|
||||
if general_i < Self::GENERAL_PARAM_REGS.len() {
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[general_i]),
|
||||
);
|
||||
storage_manager.general_reg_arg(sym, Self::GENERAL_PARAM_REGS[general_i]);
|
||||
general_i += 1;
|
||||
} else {
|
||||
storage_manager.primitive_stack_arg(sym, arg_offset);
|
||||
arg_offset += 8;
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::Base {
|
||||
offset: arg_offset,
|
||||
size: 8,
|
||||
owned: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
single_register_floats!() => {
|
||||
if float_i < Self::FLOAT_PARAM_REGS.len() {
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::FloatReg(Self::FLOAT_PARAM_REGS[float_i]),
|
||||
);
|
||||
storage_manager.float_reg_arg(sym, Self::FLOAT_PARAM_REGS[float_i]);
|
||||
float_i += 1;
|
||||
} else {
|
||||
storage_manager.primitive_stack_arg(sym, arg_offset);
|
||||
arg_offset += 8;
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::Base {
|
||||
offset: arg_offset,
|
||||
size: 8,
|
||||
owned: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
Layout::Builtin(Builtin::Str | Builtin::List(_)) => {
|
||||
if general_i + 1 < Self::GENERAL_PARAM_REGS.len() {
|
||||
// Load the value from the param reg into a useable base offset.
|
||||
let src1 = Self::GENERAL_PARAM_REGS[general_i];
|
||||
let src2 = Self::GENERAL_PARAM_REGS[general_i + 1];
|
||||
stack_size += 16;
|
||||
let offset = -(stack_size as i32);
|
||||
X86_64Assembler::mov_base32_reg64(buf, offset, src1);
|
||||
X86_64Assembler::mov_base32_reg64(buf, offset + 8, src2);
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::Base {
|
||||
offset,
|
||||
size: 16,
|
||||
owned: true,
|
||||
},
|
||||
);
|
||||
let base_offset = storage_manager.claim_stack_area(sym, 16);
|
||||
X86_64Assembler::mov_base32_reg64(buf, base_offset, src1);
|
||||
X86_64Assembler::mov_base32_reg64(buf, base_offset + 8, src2);
|
||||
general_i += 2;
|
||||
} else {
|
||||
todo!("loading strings args on the stack");
|
||||
todo!("loading lists and strings args on the stack");
|
||||
}
|
||||
}
|
||||
Layout::Struct(&[]) => {}
|
||||
@ -277,7 +250,6 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
||||
}
|
||||
}
|
||||
}
|
||||
stack_size
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -625,30 +597,31 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
||||
#[inline(always)]
|
||||
fn load_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
symbol_map: &mut MutMap<Symbol, SymbolStorage<X86_64GeneralReg, X86_64FloatReg>>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
X86_64WindowsFastcall,
|
||||
>,
|
||||
args: &'a [(Layout<'a>, Symbol)],
|
||||
ret_layout: &Layout<'a>,
|
||||
stack_size: u32,
|
||||
) -> u32 {
|
||||
let mut arg_offset = Self::SHADOW_SPACE_SIZE as i32 + 8; // 8 is the size of the pushed base pointer.
|
||||
) {
|
||||
let mut arg_offset = Self::SHADOW_SPACE_SIZE as i32 + 16; // 16 is the size of the pushed return address and base pointer.
|
||||
let mut i = 0;
|
||||
if X86_64WindowsFastcall::returns_via_arg_pointer(ret_layout) {
|
||||
symbol_map.insert(
|
||||
Symbol::RET_POINTER,
|
||||
SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[i]),
|
||||
);
|
||||
storage_manager.ret_pionter_arg(Self::GENERAL_PARAM_REGS[i]);
|
||||
i += 1;
|
||||
}
|
||||
for (layout, sym) in args.iter() {
|
||||
if i < Self::GENERAL_PARAM_REGS.len() {
|
||||
match layout {
|
||||
single_register_integers!() => {
|
||||
symbol_map
|
||||
.insert(*sym, SymbolStorage::GeneralReg(Self::GENERAL_PARAM_REGS[i]));
|
||||
storage_manager.general_reg_arg(sym, Self::GENERAL_PARAM_REGS[i]);
|
||||
i += 1;
|
||||
}
|
||||
single_register_floats!() => {
|
||||
symbol_map.insert(*sym, SymbolStorage::FloatReg(Self::FLOAT_PARAM_REGS[i]));
|
||||
storage_manager.float_reg_arg(sym, Self::FLOAT_PARAM_REGS[i]);
|
||||
i += 1;
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
@ -661,23 +634,17 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
||||
}
|
||||
}
|
||||
} else {
|
||||
arg_offset += match layout {
|
||||
single_register_layouts!() => 8,
|
||||
match layout {
|
||||
single_register_layouts!() => {
|
||||
storage_manager.primitive_stack_arg(sym, arg_offset);
|
||||
arg_offset += 8;
|
||||
}
|
||||
x => {
|
||||
todo!("Loading args with layout {:?}", x);
|
||||
}
|
||||
};
|
||||
symbol_map.insert(
|
||||
*sym,
|
||||
SymbolStorage::Base {
|
||||
offset: arg_offset,
|
||||
size: 8,
|
||||
owned: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
stack_size
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
Loading…
Reference in New Issue
Block a user