diff --git a/compiler/gen_dev/src/generic64/aarch64.rs b/compiler/gen_dev/src/generic64/aarch64.rs index caa675617c..018bd36245 100644 --- a/compiler/gen_dev/src/generic64/aarch64.rs +++ b/compiler/gen_dev/src/generic64/aarch64.rs @@ -249,11 +249,16 @@ impl CallConv for AArch64C #[inline(always)] fn load_args<'a>( _buf: &mut Vec<'a, u8>, - _symbol_map: &mut MutMap>, + _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"); } diff --git a/compiler/gen_dev/src/generic64/mod.rs b/compiler/gen_dev/src/generic64/mod.rs index 7b31f0178f..cff59e83a5 100644 --- a/compiler/gen_dev/src/generic64/mod.rs +++ b/compiler/gen_dev/src/generic64/mod.rs @@ -72,12 +72,11 @@ pub trait CallConv( buf: &mut Vec<'a, u8>, - symbol_map: &mut MutMap>, + 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 { }, } -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 diff --git a/compiler/gen_dev/src/generic64/storage.rs b/compiler/gen_dev/src/generic64/storage.rs index effd454f5c..0bb48abd2f 100644 --- a/compiler/gen_dev/src/generic64/storage.rs +++ b/compiler/gen_dev/src/generic64/storage.rs @@ -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. diff --git a/compiler/gen_dev/src/generic64/x86_64.rs b/compiler/gen_dev/src/generic64/x86_64.rs index 275b08b05b..07c00fe694 100644 --- a/compiler/gen_dev/src/generic64/x86_64.rs +++ b/compiler/gen_dev/src/generic64/x86_64.rs @@ -194,81 +194,54 @@ impl CallConv for X86_64Syste #[inline(always)] fn load_args<'a>( buf: &mut Vec<'a, u8>, - symbol_map: &mut MutMap>, + 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 for X86_64Syste } } } - stack_size } #[inline(always)] @@ -625,30 +597,31 @@ impl CallConv for X86_64Windo #[inline(always)] fn load_args<'a>( _buf: &mut Vec<'a, u8>, - symbol_map: &mut MutMap>, + 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 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)]