add returning str and list

This commit is contained in:
Brendan Hansknecht 2022-02-17 21:17:56 -08:00
parent cb64543476
commit d65a971508
3 changed files with 44 additions and 79 deletions

View file

@ -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,

View file

@ -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.

View file

@ -442,85 +442,33 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> 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>(