mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
refactor out loading values from storage or internal error
This commit is contained in:
parent
b00ef5ea4f
commit
554db4556b
1 changed files with 30 additions and 54 deletions
|
@ -100,6 +100,7 @@ pub struct StorageManager<
|
||||||
general_used_regs: Vec<'a, (GeneralReg, Symbol)>,
|
general_used_regs: Vec<'a, (GeneralReg, Symbol)>,
|
||||||
float_used_regs: Vec<'a, (FloatReg, Symbol)>,
|
float_used_regs: Vec<'a, (FloatReg, Symbol)>,
|
||||||
|
|
||||||
|
// TODO: it probably would be faster to make these a list that linearly scans rather than hashing.
|
||||||
// used callee saved regs must be tracked for pushing and popping at the beginning/end of the function.
|
// used callee saved regs must be tracked for pushing and popping at the beginning/end of the function.
|
||||||
general_used_callee_saved_regs: MutSet<GeneralReg>,
|
general_used_callee_saved_regs: MutSet<GeneralReg>,
|
||||||
float_used_callee_saved_regs: MutSet<FloatReg>,
|
float_used_callee_saved_regs: MutSet<FloatReg>,
|
||||||
|
@ -168,13 +169,8 @@ impl<
|
||||||
|
|
||||||
// Returns true if the symbol is storing a primitive value.
|
// Returns true if the symbol is storing a primitive value.
|
||||||
pub fn is_stored_primitive(&self, sym: &Symbol) -> bool {
|
pub fn is_stored_primitive(&self, sym: &Symbol) -> bool {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.get(sym) {
|
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
matches!(
|
matches!(
|
||||||
storage,
|
self.get_storage_for_sym(sym),
|
||||||
Reg(_) | Stack(Primitive { .. } | ReferencedPrimitive { .. })
|
Reg(_) | Stack(Primitive { .. } | ReferencedPrimitive { .. })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -262,11 +258,7 @@ impl<
|
||||||
// Will fail on values stored in float regs.
|
// Will fail on values stored in float regs.
|
||||||
// Will fail for values that don't fit in a single register.
|
// Will fail for values that don't fit in a single register.
|
||||||
pub fn load_to_general_reg(&mut self, buf: &mut Vec<'a, u8>, sym: &Symbol) -> GeneralReg {
|
pub fn load_to_general_reg(&mut self, buf: &mut Vec<'a, u8>, sym: &Symbol) -> GeneralReg {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.remove(sym) {
|
let storage = self.remove_storage_for_sym(sym);
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
match storage {
|
||||||
Reg(General(reg))
|
Reg(General(reg))
|
||||||
| Stack(Primitive {
|
| Stack(Primitive {
|
||||||
|
@ -328,11 +320,7 @@ impl<
|
||||||
// Will fail on values stored in general regs.
|
// Will fail on values stored in general regs.
|
||||||
// Will fail for values that don't fit in a single register.
|
// Will fail for values that don't fit in a single register.
|
||||||
pub fn load_to_float_reg(&mut self, buf: &mut Vec<'a, u8>, sym: &Symbol) -> FloatReg {
|
pub fn load_to_float_reg(&mut self, buf: &mut Vec<'a, u8>, sym: &Symbol) -> FloatReg {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.remove(sym) {
|
let storage = self.remove_storage_for_sym(sym);
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
match storage {
|
||||||
Reg(Float(reg))
|
Reg(Float(reg))
|
||||||
| Stack(Primitive {
|
| Stack(Primitive {
|
||||||
|
@ -400,12 +388,7 @@ impl<
|
||||||
sym: &Symbol,
|
sym: &Symbol,
|
||||||
reg: GeneralReg,
|
reg: GeneralReg,
|
||||||
) {
|
) {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.get(sym) {
|
match self.get_storage_for_sym(sym) {
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
|
||||||
Reg(General(old_reg))
|
Reg(General(old_reg))
|
||||||
| Stack(Primitive {
|
| Stack(Primitive {
|
||||||
reg: Some(General(old_reg)),
|
reg: Some(General(old_reg)),
|
||||||
|
@ -454,12 +437,7 @@ impl<
|
||||||
// It will not try to free the register first.
|
// It will not try to free the register first.
|
||||||
// This will not track the symbol change (it makes no assumptions about the new reg).
|
// This will not track the symbol change (it makes no assumptions about the new reg).
|
||||||
pub fn load_to_specified_float_reg(&self, buf: &mut Vec<'a, u8>, sym: &Symbol, reg: FloatReg) {
|
pub fn load_to_specified_float_reg(&self, buf: &mut Vec<'a, u8>, sym: &Symbol, reg: FloatReg) {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.get(sym) {
|
match self.get_storage_for_sym(sym) {
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
|
||||||
Reg(Float(old_reg))
|
Reg(Float(old_reg))
|
||||||
| Stack(Primitive {
|
| Stack(Primitive {
|
||||||
reg: Some(Float(old_reg)),
|
reg: Some(Float(old_reg)),
|
||||||
|
@ -512,11 +490,6 @@ impl<
|
||||||
field_layouts: &'a [Layout<'a>],
|
field_layouts: &'a [Layout<'a>],
|
||||||
) {
|
) {
|
||||||
debug_assert!(index < field_layouts.len() as u64);
|
debug_assert!(index < field_layouts.len() as u64);
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.get(structure) {
|
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", structure);
|
|
||||||
};
|
|
||||||
// This must be removed and reinserted for ownership and mutability reasons.
|
// This must be removed and reinserted for ownership and mutability reasons.
|
||||||
let owned_data = if let Some(owned_data) = self.allocation_map.remove(structure) {
|
let owned_data = if let Some(owned_data) = self.allocation_map.remove(structure) {
|
||||||
owned_data
|
owned_data
|
||||||
|
@ -525,7 +498,7 @@ impl<
|
||||||
};
|
};
|
||||||
self.allocation_map
|
self.allocation_map
|
||||||
.insert(*structure, Rc::clone(&owned_data));
|
.insert(*structure, Rc::clone(&owned_data));
|
||||||
match storage {
|
match self.get_storage_for_sym(structure) {
|
||||||
Stack(Complex { base_offset, size }) => {
|
Stack(Complex { base_offset, size }) => {
|
||||||
let (base_offset, size) = (*base_offset, *size);
|
let (base_offset, size) = (*base_offset, *size);
|
||||||
let mut data_offset = base_offset;
|
let mut data_offset = base_offset;
|
||||||
|
@ -552,7 +525,7 @@ impl<
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
storage => {
|
||||||
internal_error!(
|
internal_error!(
|
||||||
"Cannot load field from data with storage type: {:?}",
|
"Cannot load field from data with storage type: {:?}",
|
||||||
storage
|
storage
|
||||||
|
@ -645,12 +618,7 @@ impl<
|
||||||
sym: &Symbol,
|
sym: &Symbol,
|
||||||
wanted_reg: RegStorage<GeneralReg, FloatReg>,
|
wanted_reg: RegStorage<GeneralReg, FloatReg>,
|
||||||
) {
|
) {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.remove(sym) {
|
match self.remove_storage_for_sym(sym) {
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
|
||||||
Reg(reg_storage) => {
|
Reg(reg_storage) => {
|
||||||
debug_assert_eq!(reg_storage, wanted_reg);
|
debug_assert_eq!(reg_storage, wanted_reg);
|
||||||
let base_offset = self.claim_stack_size(8);
|
let base_offset = self.claim_stack_size(8);
|
||||||
|
@ -689,17 +657,12 @@ impl<
|
||||||
// gets the stack offset and size of the specified symbol.
|
// gets the stack offset and size of the specified symbol.
|
||||||
// the symbol must already be stored on the stack.
|
// the symbol must already be stored on the stack.
|
||||||
pub fn stack_offset_and_size(&self, sym: &Symbol) -> (i32, u32) {
|
pub fn stack_offset_and_size(&self, sym: &Symbol) -> (i32, u32) {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.get(sym) {
|
match self.get_storage_for_sym(sym) {
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
|
||||||
Stack(Primitive { base_offset, .. }) => (*base_offset, 8),
|
Stack(Primitive { base_offset, .. }) => (*base_offset, 8),
|
||||||
Stack(ReferencedPrimitive { base_offset, size } | Complex { base_offset, size }) => {
|
Stack(ReferencedPrimitive { base_offset, size } | Complex { base_offset, size }) => {
|
||||||
(*base_offset, *size)
|
(*base_offset, *size)
|
||||||
}
|
}
|
||||||
_ => {
|
storage => {
|
||||||
internal_error!(
|
internal_error!(
|
||||||
"Data not on the stack for sym ({}) with storage ({:?})",
|
"Data not on the stack for sym ({}) with storage ({:?})",
|
||||||
sym,
|
sym,
|
||||||
|
@ -800,12 +763,7 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn free_symbol(&mut self, sym: &Symbol) {
|
pub fn free_symbol(&mut self, sym: &Symbol) {
|
||||||
let storage = if let Some(storage) = self.symbol_storage_map.remove(sym) {
|
match self.remove_storage_for_sym(sym) {
|
||||||
storage
|
|
||||||
} else {
|
|
||||||
internal_error!("Unknown symbol: {}", sym);
|
|
||||||
};
|
|
||||||
match storage {
|
|
||||||
// Free stack chunck if this is the last reference to the chunk.
|
// Free stack chunck if this is the last reference to the chunk.
|
||||||
Stack(Primitive { base_offset, .. }) => {
|
Stack(Primitive { base_offset, .. }) => {
|
||||||
self.free_stack_chunk(base_offset, 8);
|
self.free_stack_chunk(base_offset, 8);
|
||||||
|
@ -921,6 +879,24 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a value from storage. They index symbol must be defined.
|
||||||
|
fn get_storage_for_sym(&self, sym: &Symbol) -> &Storage<GeneralReg, FloatReg> {
|
||||||
|
if let Some(storage) = self.symbol_storage_map.get(sym) {
|
||||||
|
storage
|
||||||
|
} else {
|
||||||
|
internal_error!("Unknown symbol: {}", sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes and returns a value from storage. They index symbol must be defined.
|
||||||
|
fn remove_storage_for_sym(&mut self, sym: &Symbol) -> Storage<GeneralReg, FloatReg> {
|
||||||
|
if let Some(storage) = self.symbol_storage_map.remove(sym) {
|
||||||
|
storage
|
||||||
|
} else {
|
||||||
|
internal_error!("Unknown symbol: {}", sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_primitive(layout: &Layout<'_>) -> bool {
|
fn is_primitive(layout: &Layout<'_>) -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue