mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
fix register logic bug in reset/reuse
This commit is contained in:
parent
0ace44ae8c
commit
4af9788b51
1 changed files with 42 additions and 22 deletions
|
@ -2691,21 +2691,18 @@ impl<
|
|||
let element_alignment_symbol = Symbol::DEV_TMP2;
|
||||
self.load_layout_alignment(Layout::U32, element_alignment_symbol);
|
||||
|
||||
let allocation = match reuse {
|
||||
let allocation = self.debug_symbol("allocation");
|
||||
|
||||
match reuse {
|
||||
None => {
|
||||
self.allocate_with_refcount(
|
||||
Symbol::DEV_TMP3,
|
||||
allocation,
|
||||
element_width_symbol,
|
||||
element_alignment_symbol,
|
||||
);
|
||||
|
||||
Symbol::DEV_TMP3
|
||||
}
|
||||
Some(reuse) => {
|
||||
// check for null
|
||||
self.allocate_with_refcount_if_null(reuse, element_layout);
|
||||
|
||||
reuse
|
||||
self.allocate_with_refcount_if_null(allocation, reuse, element_layout);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2714,9 +2711,7 @@ impl<
|
|||
|
||||
self.build_ptr_write(sym, allocation, value, element_layout);
|
||||
|
||||
if allocation == Symbol::DEV_TMP3 {
|
||||
self.free_symbol(&Symbol::DEV_TMP3);
|
||||
}
|
||||
self.free_symbol(&allocation);
|
||||
}
|
||||
|
||||
fn expr_unbox(&mut self, dst: Symbol, ptr: Symbol, element_layout: InLayout<'a>) {
|
||||
|
@ -3441,34 +3436,59 @@ impl<
|
|||
);
|
||||
}
|
||||
|
||||
fn allocate_with_refcount_if_null(&mut self, dst: Symbol, layout: InLayout) {
|
||||
let reg = self
|
||||
fn allocate_with_refcount_if_null(&mut self, dst: Symbol, src: Symbol, layout: InLayout) {
|
||||
let src_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, &dst);
|
||||
.load_to_general_reg(&mut self.buf, &src);
|
||||
|
||||
// dummy mov that is supposed to move src into dst, and is filled in later because don't know yet which
|
||||
// register the other branch will pick for dst. We must pass two different registers here
|
||||
// otherwise the whole instruction is skipped!
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, &dst);
|
||||
let mov_start_index = self.buf.len();
|
||||
ASM::mov_reg64_reg64(&mut self.buf, dst_reg, src_reg);
|
||||
|
||||
// jump to where the pointer is valid, because it is already valid if non-zero
|
||||
let jmp_index = ASM::jne_reg64_imm64_imm32(&mut self.buf, reg, 0x0, 0);
|
||||
let jmp_start_index = self.buf.len();
|
||||
let jmp_end_index = ASM::jne_reg64_imm64_imm32(&mut self.buf, src_reg, 0x0, 0);
|
||||
|
||||
self.free_symbol(&dst);
|
||||
|
||||
// so, the pointer is NULL, allocate
|
||||
|
||||
let data_bytes = Symbol::DEV_TMP;
|
||||
let data_bytes = self.debug_symbol("data_bytes");
|
||||
self.load_layout_stack_size(layout, data_bytes);
|
||||
|
||||
// Load allocation alignment (u32)
|
||||
let element_alignment = Symbol::DEV_TMP2;
|
||||
self.load_layout_alignment(Layout::U32, element_alignment);
|
||||
let element_alignment = self.debug_symbol("element_alignment");
|
||||
self.load_layout_alignment(layout, element_alignment);
|
||||
|
||||
self.allocate_with_refcount(dst, data_bytes, element_alignment);
|
||||
|
||||
self.free_symbol(&data_bytes);
|
||||
self.free_symbol(&element_alignment);
|
||||
|
||||
let mut tmp = bumpalo::vec![in self.env.arena];
|
||||
|
||||
// update the jump
|
||||
let destination_index = self.buf.len();
|
||||
let mut tmp = bumpalo::vec![in self.env.arena];
|
||||
ASM::jne_reg64_imm64_imm32(&mut tmp, reg, 0x0, (destination_index - jmp_index) as i32);
|
||||
ASM::jne_reg64_imm64_imm32(
|
||||
&mut tmp,
|
||||
src_reg,
|
||||
0x0,
|
||||
(destination_index - jmp_end_index) as i32,
|
||||
);
|
||||
|
||||
self.buf[jmp_index..][..tmp.len()].copy_from_slice(tmp.as_slice());
|
||||
self.buf[jmp_start_index..][..tmp.len()].copy_from_slice(tmp.as_slice());
|
||||
|
||||
// figure out what register was actually used
|
||||
let dst_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, &dst);
|
||||
|
||||
tmp.clear();
|
||||
ASM::mov_reg64_reg64(&mut tmp, dst_reg, src_reg);
|
||||
|
||||
self.buf[mov_start_index..][..tmp.len()].copy_from_slice(tmp.as_slice());
|
||||
}
|
||||
|
||||
fn unbox_str_or_list(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue