Add accessors for various stack operations

This commit is contained in:
Rerumu 2022-06-17 21:33:04 -04:00
parent b3c931a38e
commit 0e23793d72
3 changed files with 40 additions and 30 deletions

View File

@ -18,8 +18,8 @@ macro_rules! leak_on {
fn $name(&mut self, id: usize) { fn $name(&mut self, id: usize) {
let read = ReadType::$variant(id); let read = ReadType::$variant(id);
for i in 0..self.stack.var_list.len() { for i in 0..self.stack.len() {
if self.stack.var_list[i].read.contains(&read) { if self.stack.get(i).has_read(read) {
self.leak_at(i); self.leak_at(i);
} }
} }
@ -179,7 +179,7 @@ impl StatList {
} }
fn leak_all(&mut self) { fn leak_all(&mut self) {
for i in 0..self.stack.var_list.len() { for i in 0..self.stack.len() {
self.leak_at(i); self.leak_at(i);
} }
} }
@ -464,7 +464,7 @@ impl<'a> Builder<'a> {
let arity = self.type_info.rel_arity_of(func); let arity = self.type_info.rel_arity_of(func);
let param_list = self.target.stack.pop_len(arity.num_param).collect(); let param_list = self.target.stack.pop_len(arity.num_param).collect();
let first = self.target.stack.var_list.len(); let first = self.target.stack.len();
let result = first..first + arity.num_result; let result = first..first + arity.num_result;
self.target.leak_all(); self.target.leak_all();
@ -484,7 +484,7 @@ impl<'a> Builder<'a> {
let index = self.target.stack.pop(); let index = self.target.stack.pop();
let param_list = self.target.stack.pop_len(arity.num_param).collect(); let param_list = self.target.stack.pop_len(arity.num_param).collect();
let first = self.target.stack.var_list.len(); let first = self.target.stack.len();
let result = first..first + arity.num_result; let result = first..first + arity.num_result;
self.target.leak_all(); self.target.leak_all();
@ -607,9 +607,9 @@ impl<'a> Builder<'a> {
self.add_call_indirect(i.try_into().unwrap(), t.into()); self.add_call_indirect(i.try_into().unwrap(), t.into());
} }
Inst::Drop => { Inst::Drop => {
let last = self.target.stack.var_list.len() - 1; let last = self.target.stack.len() - 1;
if self.target.stack.var_list[last].data.has_side_effect() { if self.target.stack.get(last).has_side_effect() {
self.target.leak_at(last); self.target.leak_at(last);
} }

View File

@ -627,18 +627,6 @@ pub enum Expression {
CmpOp(CmpOp), CmpOp(CmpOp),
} }
impl Expression {
#[must_use]
pub fn has_side_effect(&self) -> bool {
matches!(self, Expression::MemorySize(_))
}
#[must_use]
pub fn is_temporary(&self, id: usize) -> bool {
matches!(self, Expression::GetTemporary(v) if v.var == id)
}
}
pub struct Align { pub struct Align {
pub new: usize, pub new: usize,
pub old: usize, pub old: usize,

View File

@ -4,7 +4,7 @@ use crate::node::{
Align, Expression, GetGlobal, GetLocal, GetTemporary, LoadAt, SetTemporary, Statement, Align, Expression, GetGlobal, GetLocal, GetTemporary, LoadAt, SetTemporary, Statement,
}; };
#[derive(PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum ReadType { pub enum ReadType {
Local(usize), Local(usize),
Global(usize), Global(usize),
@ -12,24 +12,46 @@ pub enum ReadType {
} }
pub struct Slot { pub struct Slot {
pub read: HashSet<ReadType>, read: HashSet<ReadType>,
pub data: Expression, data: Expression,
}
impl Slot {
pub fn has_read(&self, read: ReadType) -> bool {
self.read.contains(&read)
}
pub fn has_side_effect(&self) -> bool {
matches!(self.data, Expression::MemoryGrow(_))
}
pub fn is_temporary(&self, id: usize) -> bool {
matches!(self.data, Expression::GetTemporary(ref v) if v.var == id)
}
} }
#[derive(Default)] #[derive(Default)]
pub struct Stack { pub struct Stack {
pub var_list: Vec<Slot>, var_list: Vec<Slot>,
pub capacity: usize, pub capacity: usize,
pub previous: usize, pub previous: usize,
} }
impl Stack { impl Stack {
pub fn len(&self) -> usize {
self.var_list.len()
}
pub fn get(&self, index: usize) -> &Slot {
&self.var_list[index]
}
pub fn split_last(&mut self, len: usize) -> Self { pub fn split_last(&mut self, len: usize) -> Self {
let desired = self.var_list.len() - len; let desired = self.len() - len;
let content = self.var_list.split_off(desired); let var_list = self.var_list.split_off(desired);
Self { Self {
var_list: content, var_list,
capacity: self.capacity, capacity: self.capacity,
previous: self.previous + desired, previous: self.previous + desired,
} }
@ -67,13 +89,13 @@ impl Stack {
} }
pub fn pop_len(&'_ mut self, len: usize) -> impl Iterator<Item = Expression> + '_ { pub fn pop_len(&'_ mut self, len: usize) -> impl Iterator<Item = Expression> + '_ {
let desired = self.var_list.len() - len; let desired = self.len() - len;
self.var_list.drain(desired..).map(|v| v.data) self.var_list.drain(desired..).map(|v| v.data)
} }
pub fn push_temporary(&mut self, num: usize) { pub fn push_temporary(&mut self, num: usize) {
let len = self.var_list.len() + self.previous; let len = self.len() + self.previous;
for var in len..len + num { for var in len..len + num {
let data = Expression::GetTemporary(GetTemporary { var }); let data = Expression::GetTemporary(GetTemporary { var });
@ -90,7 +112,7 @@ impl Stack {
let old = &mut self.var_list[index]; let old = &mut self.var_list[index];
let var = self.previous + index; let var = self.previous + index;
if old.data.is_temporary(var) { if old.is_temporary(var) {
return None; return None;
} }
@ -110,7 +132,7 @@ impl Stack {
// Return the alignment necessary for this block to branch out to a // Return the alignment necessary for this block to branch out to a
// another given stack frame // another given stack frame
pub fn get_br_alignment(&self, par_start: usize, par_result: usize) -> Align { pub fn get_br_alignment(&self, par_start: usize, par_result: usize) -> Align {
let start = self.var_list.len() + self.previous - par_result; let start = self.len() + self.previous - par_result;
Align { Align {
new: par_start, new: par_start,