dev backend: Box.unbox and List.get str

This commit is contained in:
Folkert 2023-02-09 16:28:12 +01:00
parent 4d1a6b17a8
commit 8df8c19ae2
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
3 changed files with 87 additions and 16 deletions

View file

@ -1510,34 +1510,34 @@ impl<
|storage_manager, buf, list_ptr| {
ASM::mov_reg64_base32(buf, list_ptr, base_offset as i32);
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp| {
// calculate `element_width * index`
ASM::mov_reg64_imm64(buf, tmp, ret_stack_size as i64);
ASM::imul_reg64_reg64_reg64(buf, tmp, tmp, index_reg);
// add the offset to the list pointer, store in `tmp`
ASM::add_reg64_reg64_reg64(buf, tmp, tmp, list_ptr);
let element_ptr = tmp;
match *ret_layout {
single_register_integers!() if ret_stack_size == 8 => {
let dst_reg = storage_manager.claim_general_reg(buf, dst);
ASM::mov_reg64_mem64_offset32(buf, dst_reg, tmp, 0);
ASM::mov_reg64_mem64_offset32(buf, dst_reg, element_ptr, 0);
}
single_register_floats!() => {
let dst_reg = storage_manager.claim_float_reg(buf, dst);
ASM::mov_freg64_freg64(buf, dst_reg, CC::FLOAT_RETURN_REGS[0]);
}
Layout::STR => {
let dst_reg = storage_manager.claim_general_reg(buf, dst);
// the `list_ptr` register is now unused, and we can use it as scratch space
let tmp_reg = list_ptr;
let base_offset = storage_manager.claim_stack_area(dst, 24);
// move 1 into a register
ASM::mov_mem64_offset32_reg64(buf, dst_reg, 0, tmp);
ASM::mov_base32_reg64(buf, base_offset + 0, dst_reg);
// word 2
ASM::mov_mem64_offset32_reg64(buf, dst_reg, 8, tmp);
ASM::mov_base32_reg64(buf, base_offset + 8, dst_reg);
// word 3
ASM::mov_mem64_offset32_reg64(buf, dst_reg, 16, tmp);
ASM::mov_base32_reg64(buf, base_offset + 16, dst_reg);
Self::unbox_str_or_list(
buf,
storage_manager,
*dst,
element_ptr,
tmp_reg,
);
}
other => {
//
@ -2056,6 +2056,14 @@ impl<
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, &dst);
ASM::mov_reg64_mem64_offset32(&mut self.buf, dst_reg, ptr_reg, 0);
}
Layout::STR => {
self.storage_manager.with_tmp_general_reg(
&mut self.buf,
|storage_manager, buf, tmp_reg| {
Self::unbox_str_or_list(buf, storage_manager, dst, ptr_reg, tmp_reg);
},
);
}
_ => {
todo!("unboxing of {:?}", self.layout_interner.dbg(element_layout))
}
@ -2418,6 +2426,25 @@ impl<
);
}
fn unbox_str_or_list(
buf: &mut Vec<'a, u8>,
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
dst: Symbol,
ptr_reg: GeneralReg,
tmp_reg: GeneralReg,
) {
let base_offset = storage_manager.claim_stack_area(&dst, 24);
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, 0);
ASM::mov_base32_reg64(buf, base_offset + 0, tmp_reg);
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, 8);
ASM::mov_base32_reg64(buf, base_offset + 8, tmp_reg);
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, 16);
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg);
}
/// Updates a jump instruction to a new offset and returns the number of bytes written.
fn update_jmp_imm32_offset(
&mut self,