mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
centralize writing a stack value to a pointer
This commit is contained in:
parent
ee79a311f9
commit
b31edead54
1 changed files with 76 additions and 85 deletions
|
@ -1851,10 +1851,11 @@ impl<
|
|||
fn create_array(
|
||||
&mut self,
|
||||
sym: &Symbol,
|
||||
element_layout: &InLayout<'a>,
|
||||
element_in_layout: &InLayout<'a>,
|
||||
elements: &'a [ListLiteralElement<'a>],
|
||||
) {
|
||||
let element_width = self.layout_interner.stack_size(*element_layout) as u64;
|
||||
let element_layout = self.layout_interner.get(*element_in_layout);
|
||||
let element_width = self.layout_interner.stack_size(*element_in_layout) as u64;
|
||||
|
||||
// load the total size of the data we want to store (excludes refcount)
|
||||
let data_bytes_symbol = Symbol::DEV_TMP;
|
||||
|
@ -1884,54 +1885,34 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3);
|
||||
|
||||
// Copy everything into output array.
|
||||
let mut elem_offset = 0;
|
||||
let mut element_offset = 0;
|
||||
for elem in elements {
|
||||
// TODO: this could be a lot faster when loading large lists
|
||||
// if we move matching on the element layout to outside this loop.
|
||||
// It also greatly bloats the code here.
|
||||
// Refactor this and switch to one external match.
|
||||
// We also could make loadining indivitual literals much faster
|
||||
let elem_sym = match elem {
|
||||
ListLiteralElement::Symbol(sym) => sym,
|
||||
let element_symbol = match elem {
|
||||
ListLiteralElement::Symbol(sym) => *sym,
|
||||
ListLiteralElement::Literal(lit) => {
|
||||
self.load_literal(&Symbol::DEV_TMP, element_layout, lit);
|
||||
&Symbol::DEV_TMP
|
||||
self.load_literal(&Symbol::DEV_TMP, element_in_layout, lit);
|
||||
Symbol::DEV_TMP
|
||||
}
|
||||
};
|
||||
// TODO: Expand to all types.
|
||||
match self.layout_interner.get(*element_layout) {
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64) | Builtin::Bool) => {
|
||||
let sym_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, elem_sym);
|
||||
ASM::mov_mem64_offset32_reg64(&mut self.buf, ptr_reg, elem_offset, sym_reg);
|
||||
}
|
||||
_ if element_width == 0 => {}
|
||||
_ if element_width > 8 => {
|
||||
let (from_offset, size) = self.storage_manager.stack_offset_and_size(elem_sym);
|
||||
debug_assert!(from_offset % 8 == 0);
|
||||
debug_assert!(size % 8 == 0);
|
||||
debug_assert_eq!(size as u64, element_width);
|
||||
self.storage_manager.with_tmp_general_reg(
|
||||
&mut self.buf,
|
||||
|_storage_manager, buf, tmp_reg| {
|
||||
for i in (0..size as i32).step_by(8) {
|
||||
ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i);
|
||||
ASM::mov_mem64_offset32_reg64(
|
||||
buf,
|
||||
ptr_reg,
|
||||
elem_offset + i,
|
||||
tmp_reg,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
x => todo!("copying data to list with layout, {:?}", x),
|
||||
}
|
||||
elem_offset += element_width as i32;
|
||||
if elem_sym == &Symbol::DEV_TMP {
|
||||
self.free_symbol(elem_sym);
|
||||
|
||||
Self::ptr_write(
|
||||
&mut self.buf,
|
||||
&mut self.storage_manager,
|
||||
ptr_reg,
|
||||
element_offset,
|
||||
element_width,
|
||||
element_layout,
|
||||
element_symbol,
|
||||
);
|
||||
|
||||
element_offset += element_width as i32;
|
||||
if element_symbol == Symbol::DEV_TMP {
|
||||
self.free_symbol(&element_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2029,49 +2010,15 @@ impl<
|
|||
let element_width = self.layout_interner.stack_size(element_layout) as u64;
|
||||
let element_offset = 0;
|
||||
|
||||
// TODO: Expand to all types.
|
||||
let storage_manager = &mut self.storage_manager;
|
||||
match self.layout_interner.get(element_layout) {
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(&mut self.buf, &value);
|
||||
ASM::mov_mem64_offset32_reg64(&mut self.buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::U32)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(&mut self.buf, &value);
|
||||
ASM::mov_mem32_offset32_reg32(&mut self.buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I16 | IntWidth::U16)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(&mut self.buf, &value);
|
||||
ASM::mov_mem16_offset32_reg16(&mut self.buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8) | Builtin::Bool) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(&mut self.buf, &value);
|
||||
ASM::mov_mem8_offset32_reg8(&mut self.buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
_ if element_width == 0 => {}
|
||||
_ if element_width > 8 => {
|
||||
let (from_offset, size) = self.storage_manager.stack_offset_and_size(&value);
|
||||
debug_assert!(from_offset % 8 == 0);
|
||||
debug_assert!(size % 8 == 0);
|
||||
debug_assert_eq!(size as u64, element_width);
|
||||
self.storage_manager.with_tmp_general_reg(
|
||||
&mut self.buf,
|
||||
|_storage_manager, buf, tmp_reg| {
|
||||
// a crude memcpy
|
||||
for i in (0..size as i32).step_by(8) {
|
||||
ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i);
|
||||
ASM::mov_mem64_offset32_reg64(
|
||||
buf,
|
||||
ptr_reg,
|
||||
element_offset + i,
|
||||
tmp_reg,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
x => todo!("copying data to list with layout, {:?}", x),
|
||||
}
|
||||
Self::ptr_write(
|
||||
&mut self.buf,
|
||||
&mut self.storage_manager,
|
||||
ptr_reg,
|
||||
element_offset,
|
||||
element_width,
|
||||
self.layout_interner.get(element_layout),
|
||||
value,
|
||||
);
|
||||
|
||||
if value == Symbol::DEV_TMP {
|
||||
self.free_symbol(&value);
|
||||
|
@ -2092,7 +2039,7 @@ impl<
|
|||
let ret_stack_size = self.layout_interner.stack_size(element_layout);
|
||||
|
||||
match element_layout {
|
||||
single_register_integers!() if ret_stack_size == 8 => {
|
||||
Layout::U64 | Layout::I64 => {
|
||||
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);
|
||||
}
|
||||
|
@ -2497,6 +2444,50 @@ impl<
|
|||
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg);
|
||||
}
|
||||
|
||||
fn ptr_write(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
ptr_reg: GeneralReg,
|
||||
element_offset: i32,
|
||||
element_width: u64,
|
||||
element_layout: Layout<'a>,
|
||||
value: Symbol,
|
||||
) {
|
||||
match element_layout {
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::U32)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||
ASM::mov_mem32_offset32_reg32(buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I16 | IntWidth::U16)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||
ASM::mov_mem16_offset32_reg16(buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8) | Builtin::Bool) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||
ASM::mov_mem8_offset32_reg8(buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
_ if element_width == 0 => {}
|
||||
_ if element_width > 8 => {
|
||||
let (from_offset, size) = storage_manager.stack_offset_and_size(&value);
|
||||
debug_assert!(from_offset % 8 == 0);
|
||||
debug_assert!(size % 8 == 0);
|
||||
debug_assert_eq!(size as u64, element_width);
|
||||
storage_manager.with_tmp_general_reg(buf, |_storage_manager, buf, tmp_reg| {
|
||||
// a crude memcpy
|
||||
for i in (0..size as i32).step_by(8) {
|
||||
ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i);
|
||||
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset + i, tmp_reg);
|
||||
}
|
||||
});
|
||||
}
|
||||
x => todo!("copying data to list with layout, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates a jump instruction to a new offset and returns the number of bytes written.
|
||||
fn update_jmp_imm32_offset(
|
||||
&mut self,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue