diff --git a/compiler/gen_dev/src/generic64/mod.rs b/compiler/gen_dev/src/generic64/mod.rs index 07048a46de..66f7aa012c 100644 --- a/compiler/gen_dev/src/generic64/mod.rs +++ b/compiler/gen_dev/src/generic64/mod.rs @@ -1,7 +1,4 @@ -use crate::{ - single_register_floats, single_register_integers, single_register_layouts, Backend, Env, - Relocation, -}; +use crate::{single_register_floats, single_register_integers, Backend, Env, Relocation}; use bumpalo::collections::Vec; use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_collections::all::{MutMap, MutSet}; @@ -602,9 +599,6 @@ impl< let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst); ASM::mov_freg64_freg64(&mut self.buf, dst_reg, CC::FLOAT_RETURN_REGS[0]); } - Layout::Struct([]) => { - // Nothing needs to be done to load a returned empty struct. - } _ => { CC::load_returned_complex_symbol( &mut self.buf, diff --git a/compiler/gen_dev/src/generic64/storage.rs b/compiler/gen_dev/src/generic64/storage.rs index c4552e5761..effd454f5c 100644 --- a/compiler/gen_dev/src/generic64/storage.rs +++ b/compiler/gen_dev/src/generic64/storage.rs @@ -646,6 +646,29 @@ impl< } } + // gets the stack offset and size of the specified symbol. + // the symbol must already be stored on the stack. + pub fn stack_offset_and_size(&self, sym: &Symbol) -> (i32, u32) { + let storage = if let Some(storage) = self.symbol_storage_map.get(sym) { + storage + } else { + internal_error!("Unknown symbol: {}", sym); + }; + match storage { + Stack(Primitive { base_offset, .. }) => (*base_offset, 8), + Stack(ReferencedPrimitive { base_offset, size } | Complex { base_offset, size }) => { + (*base_offset, *size) + } + _ => { + internal_error!( + "Data no on the stack for sym ({}) with storage ({:?})", + sym, + storage + ) + } + } + } + /// 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 e333f02142..711f42da8f 100644 --- a/compiler/gen_dev/src/generic64/x86_64.rs +++ b/compiler/gen_dev/src/generic64/x86_64.rs @@ -442,85 +442,33 @@ impl CallConv for X86_64Syste } fn return_complex_symbol<'a>( - _buf: &mut Vec<'a, u8>, - _storage_manager: &mut StorageManager< + buf: &mut Vec<'a, u8>, + storage_manager: &mut StorageManager< 'a, X86_64GeneralReg, X86_64FloatReg, X86_64Assembler, X86_64SystemV, >, - _sym: &Symbol, - _layout: &Layout<'a>, + sym: &Symbol, + layout: &Layout<'a>, ) { - // Complex types. - // let val = self.symbol_storage_map.get(sym); - // match val { - // Some(SymbolStorage::GeneralReg(reg)) if *reg == CC::GENERAL_RETURN_REGS[0] => {} - // Some(SymbolStorage::GeneralReg(reg)) => { - // // If it fits in a general purpose register, just copy it over to. - // // Technically this can be optimized to produce shorter instructions if less than 64bits. - // ASM::mov_reg64_reg64(&mut self.buf, CC::GENERAL_RETURN_REGS[0], *reg); - // } - // Some(SymbolStorage::FloatReg(reg)) if *reg == CC::FLOAT_RETURN_REGS[0] => {} - // Some(SymbolStorage::FloatReg(reg)) => { - // ASM::mov_freg64_freg64(&mut self.buf, CC::FLOAT_RETURN_REGS[0], *reg); - // } - // Some(SymbolStorage::Base { offset, size, .. }) => match layout { - // Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => { - // ASM::mov_reg64_base32(&mut self.buf, CC::GENERAL_RETURN_REGS[0], *offset); - // } - // Layout::Builtin(Builtin::Float(FloatWidth::F64)) => { - // ASM::mov_freg64_base32(&mut self.buf, CC::FLOAT_RETURN_REGS[0], *offset); - // } - // Layout::Builtin(Builtin::Str) => { - // if self.symbol_storage_map.contains_key(&Symbol::RET_POINTER) { - // // This will happen on windows, return via pointer here. - // todo!("Returning strings via pointer"); - // } else { - // ASM::mov_reg64_base32(&mut self.buf, CC::GENERAL_RETURN_REGS[0], *offset); - // ASM::mov_reg64_base32( - // &mut self.buf, - // CC::GENERAL_RETURN_REGS[1], - // *offset + 8, - // ); - // } - // } - // Layout::Struct(field_layouts) => { - // let (offset, size) = (*offset, *size); - // // Nothing to do for empty struct - // if size > 0 { - // let ret_reg = if self.symbol_storage_map.contains_key(&Symbol::RET_POINTER) - // { - // Some( - // self.storage_manager - // .load_to_general_reg(&mut self.buf, &Symbol::RET_POINTER), - // ) - // } else { - // None - // }; - // CC::return_struct(&mut self.buf, offset, size, field_layouts, ret_reg); - // } - // } - // x => todo!("returning symbol with layout, {:?}", x), - // }, - // Some(x) => todo!("returning symbol storage, {:?}", x), - // None if layout == &Layout::Struct(&[]) => { - // // Empty struct is not defined and does nothing. - // } - // None => { - // internal_error!("Unknown return symbol: {:?}", sym); - // } - // } - // let inst_loc = self.buf.len() as u64; - // let offset = ASM::jmp_imm32(&mut self.buf, 0x1234_5678) as u64; - // self.relocs.push(Relocation::JmpToReturn { - // inst_loc, - // inst_size: self.buf.len() as u64 - inst_loc, - // offset, - // }); - // } - todo!("Returning complex symbols for X86_64"); + let (base_offset, size) = storage_manager.stack_offset_and_size(sym); + match layout { + single_register_layouts!() => { + internal_error!("single register layouts are not complex symbols"); + } + Layout::Struct([]) => {} + Layout::Builtin(Builtin::Str | Builtin::List(_)) => { + X86_64Assembler::mov_reg64_base32(buf, Self::GENERAL_RETURN_REGS[0], base_offset); + X86_64Assembler::mov_reg64_base32( + buf, + Self::GENERAL_RETURN_REGS[1], + base_offset + 8, + ); + } + x => todo!("returning complex type, {:?}", x), + } } fn load_returned_complex_symbol<'a>(