move freeing symbols to the storage manager

This commit is contained in:
Brendan Hansknecht 2022-02-17 15:28:54 -08:00
parent 89b6a6cf91
commit fa8d7f78b2
2 changed files with 96 additions and 92 deletions

View file

@ -16,10 +16,11 @@ pub mod x86_64;
// TODO: StorageManager is still not fully integrated. // TODO: StorageManager is still not fully integrated.
// General pieces needed: // General pieces needed:
// - loading and Storing args iwht storage manager // - loading and Storing args into storage manager
// - returning data (note: remove return struct send everything to CC) // - returning data (note: remove return struct send everything to CC)
// - function call stack? (maybe can stay here) // - function call stack? (maybe can stay here)
// - re-enabling some commented out things // - re-enabling some commented out things
// - remove data that is duplicated here and in storage manager
// - ensure storage map doesn't leak out of storage, try to make it clean and generic // - ensure storage map doesn't leak out of storage, try to make it clean and generic
// - Look into Complex values on the stack and reference. They may not work well. // - Look into Complex values on the stack and reference. They may not work well.
// - look into fixing join to no longer use multiple backends??? // - look into fixing join to no longer use multiple backends???
@ -1120,97 +1121,7 @@ impl<
} }
fn free_symbol(&mut self, sym: &Symbol) { fn free_symbol(&mut self, sym: &Symbol) {
match self.symbol_storage_map.remove(sym) { self.storage_manager.free_symbol(sym);
Some(
SymbolStorage::Base {
offset,
size,
owned: true,
}
| SymbolStorage::BaseAndGeneralReg {
offset,
size,
owned: true,
..
}
| SymbolStorage::BaseAndFloatReg {
offset,
size,
owned: true,
..
},
) => {
let loc = (offset, size);
// Note: this position current points to the offset following the specified location.
// If loc was inserted at this position, it would shift the data at this position over by 1.
let pos = self
.free_stack_chunks
.binary_search(&loc)
.unwrap_or_else(|e| e);
// Check for overlap with previous and next free chunk.
let merge_with_prev = if pos > 0 {
if let Some((prev_offset, prev_size)) = self.free_stack_chunks.get(pos - 1) {
let prev_end = *prev_offset + *prev_size as i32;
if prev_end > offset {
internal_error!("Double free? A previously freed stack location overlaps with the currently freed stack location.");
}
prev_end == offset
} else {
false
}
} else {
false
};
let merge_with_next = if let Some((next_offset, _)) =
self.free_stack_chunks.get(pos)
{
let current_end = offset + size as i32;
if current_end > *next_offset {
internal_error!("Double free? A previously freed stack location overlaps with the currently freed stack location.");
}
current_end == *next_offset
} else {
false
};
match (merge_with_prev, merge_with_next) {
(true, true) => {
let (prev_offset, prev_size) = self.free_stack_chunks[pos - 1];
let (_, next_size) = self.free_stack_chunks[pos];
self.free_stack_chunks[pos - 1] =
(prev_offset, prev_size + size + next_size);
self.free_stack_chunks.remove(pos);
}
(true, false) => {
let (prev_offset, prev_size) = self.free_stack_chunks[pos - 1];
self.free_stack_chunks[pos - 1] = (prev_offset, prev_size + size);
}
(false, true) => {
let (_, next_size) = self.free_stack_chunks[pos];
self.free_stack_chunks[pos] = (offset, next_size + size);
}
(false, false) => self.free_stack_chunks.insert(pos, loc),
}
}
Some(_) | None => {}
}
for i in 0..self.general_used_regs.len() {
let (reg, saved_sym) = self.general_used_regs[i];
if saved_sym == *sym {
self.general_free_regs.push(reg);
self.general_used_regs.remove(i);
break;
}
}
for i in 0..self.float_used_regs.len() {
let (reg, saved_sym) = self.float_used_regs[i];
if saved_sym == *sym {
self.float_free_regs.push(reg);
self.float_used_regs.remove(i);
break;
}
}
} }
fn return_symbol(&mut self, sym: &Symbol, layout: &Layout<'a>) { fn return_symbol(&mut self, sym: &Symbol, layout: &Layout<'a>) {

View file

@ -527,6 +527,99 @@ impl<
} }
} }
pub fn free_symbol(&mut self, sym: &Symbol) {
let storage = if let Some(storage) = self.symbol_storage_map.remove(sym) {
storage
} else {
internal_error!("Unknown symbol: {}", sym);
};
let rc_sym = if let Some(rc_sym) = self.reference_map.remove(sym) {
rc_sym
} else {
internal_error!("Unknown symbol: {}", sym);
};
match storage {
// Free stack chunck if this is the last reference to the chunk.
Stack(Primitive { base_offset, .. }) if Rc::strong_count(&rc_sym) == 1 => {
self.free_stack_chunk(base_offset, 8);
}
Stack(Complex {
base_offset, size, ..
}) if Rc::strong_count(&rc_sym) == 1 => {
self.free_stack_chunk(base_offset, size);
}
_ => {}
}
for i in 0..self.general_used_regs.len() {
let (reg, saved_sym) = self.general_used_regs[i];
if saved_sym == *sym {
self.general_free_regs.push(reg);
self.general_used_regs.remove(i);
break;
}
}
for i in 0..self.float_used_regs.len() {
let (reg, saved_sym) = self.float_used_regs[i];
if saved_sym == *sym {
self.float_free_regs.push(reg);
self.float_used_regs.remove(i);
break;
}
}
}
fn free_stack_chunk(&mut self, base_offset: i32, size: u32) {
let loc = (base_offset, size);
// Note: this position current points to the offset following the specified location.
// If loc was inserted at this position, it would shift the data at this position over by 1.
let pos = self
.free_stack_chunks
.binary_search(&loc)
.unwrap_or_else(|e| e);
// Check for overlap with previous and next free chunk.
let merge_with_prev = if pos > 0 {
if let Some((prev_offset, prev_size)) = self.free_stack_chunks.get(pos - 1) {
let prev_end = *prev_offset + *prev_size as i32;
if prev_end > base_offset {
internal_error!("Double free? A previously freed stack location overlaps with the currently freed stack location.");
}
prev_end == base_offset
} else {
false
}
} else {
false
};
let merge_with_next = if let Some((next_offset, _)) = self.free_stack_chunks.get(pos) {
let current_end = base_offset + size as i32;
if current_end > *next_offset {
internal_error!("Double free? A previously freed stack location overlaps with the currently freed stack location.");
}
current_end == *next_offset
} else {
false
};
match (merge_with_prev, merge_with_next) {
(true, true) => {
let (prev_offset, prev_size) = self.free_stack_chunks[pos - 1];
let (_, next_size) = self.free_stack_chunks[pos];
self.free_stack_chunks[pos - 1] = (prev_offset, prev_size + size + next_size);
self.free_stack_chunks.remove(pos);
}
(true, false) => {
let (prev_offset, prev_size) = self.free_stack_chunks[pos - 1];
self.free_stack_chunks[pos - 1] = (prev_offset, prev_size + size);
}
(false, true) => {
let (_, next_size) = self.free_stack_chunks[pos];
self.free_stack_chunks[pos] = (base_offset, next_size + size);
}
(false, false) => self.free_stack_chunks.insert(pos, loc),
}
}
pub fn push_used_caller_saved_regs_to_stack(&mut self, buf: &mut Vec<'a, u8>) { pub fn push_used_caller_saved_regs_to_stack(&mut self, buf: &mut Vec<'a, u8>) {
let old_general_used_regs = std::mem::replace( let old_general_used_regs = std::mem::replace(
&mut self.general_used_regs, &mut self.general_used_regs,