Add naive local and temporary spills

This commit is contained in:
Rerumu
2023-06-25 22:49:29 -04:00
parent 5622aa661e
commit d33e4a6b3e
14 changed files with 589 additions and 402 deletions
+15 -15
View File
@@ -1,10 +1,10 @@
use wasmparser::{BlockType, FunctionBody, MemArg, Operator, Result};
use crate::{
module::{read_checked, TypeInfo},
module::{read_checked, read_checked_locals, TypeInfo},
node::{
BinOp, BinOpType, Block, Br, BrIf, BrTable, Call, CallIndirect, CmpOp, CmpOpType,
Expression, FuncData, GetGlobal, GetLocal, If, LabelType, LoadAt, LoadType, MemoryArgument,
Expression, FuncData, GetGlobal, If, LabelType, LoadAt, LoadType, Local, MemoryArgument,
MemoryCopy, MemoryFill, MemoryGrow, MemorySize, Select, SetGlobal, SetLocal, Statement,
StoreAt, StoreType, Terminator, UnOp, UnOpType, Value,
},
@@ -253,13 +253,13 @@ impl<'a> Factory<'a> {
/// Returns an error if the function is malformed.
pub fn create_indexed(&mut self, index: usize, func: &FunctionBody) -> Result<FuncData> {
let code = read_checked(func.get_operators_reader()?)?;
let local = read_checked(func.get_locals_reader()?)?;
let local_data = read_checked_locals(func.get_locals_reader()?)?;
let (num_param, num_result) = self.type_info.by_func_index(index);
let data = self.build_stat_list(&code, num_result);
Ok(FuncData {
local_data: local,
local_data,
num_result,
num_param,
num_stack: data.stack.capacity,
@@ -279,7 +279,7 @@ impl<'a> Factory<'a> {
BlockVariant::If => BlockData::If { num_result, ty },
BlockVariant::Else => {
old.stack.pop_len(num_result).for_each(drop);
old.stack.push_temporary(num_param);
old.stack.push_temporaries(num_param);
BlockData::Else { num_result }
}
@@ -287,7 +287,7 @@ impl<'a> Factory<'a> {
self.target.stack = old.stack.split_last(num_param, num_result);
old.stack.push_temporary(num_result);
old.stack.push_temporaries(num_result);
self.pending.push(old);
}
@@ -358,12 +358,12 @@ impl<'a> Factory<'a> {
self.target.leak_pre_call();
let result = self.target.stack.push_temporary(num_result);
let result_list = self.target.stack.push_temporaries(num_result);
let data = Statement::Call(Call {
function,
result,
param_list,
result_list,
});
self.target.code.push(data);
@@ -376,13 +376,13 @@ impl<'a> Factory<'a> {
self.target.leak_pre_call();
let result = self.target.stack.push_temporary(num_result);
let result_list = self.target.stack.push_temporaries(num_result);
let data = Statement::CallIndirect(CallIndirect {
table,
index,
result,
param_list,
result_list,
});
self.target.code.push(data);
@@ -521,14 +521,14 @@ impl<'a> Factory<'a> {
}
Operator::LocalGet { local_index } => {
let var = local_index.try_into().unwrap();
let data = Expression::GetLocal(GetLocal { var });
let data = Expression::GetLocal(Local { var });
self.target.stack.push_with_single(data);
}
Operator::LocalSet { local_index } => {
let var = local_index.try_into().unwrap();
let data = Statement::SetLocal(SetLocal {
var,
var: Local { var },
value: self.target.stack.pop().into(),
});
@@ -537,9 +537,9 @@ impl<'a> Factory<'a> {
}
Operator::LocalTee { local_index } => {
let var = local_index.try_into().unwrap();
let get = Expression::GetLocal(GetLocal { var });
let get = Expression::GetLocal(Local { var });
let set = Statement::SetLocal(SetLocal {
var,
var: Local { var },
value: self.target.stack.pop().into(),
});
@@ -594,7 +594,7 @@ impl<'a> Factory<'a> {
}
Operator::MemoryGrow { mem, .. } => {
let size = self.target.stack.pop().into();
let result = self.target.stack.push_temporary(1).start;
let result = self.target.stack.push_temporary();
let memory = mem.try_into().unwrap();
let data = Statement::MemoryGrow(MemoryGrow {
+11 -2
View File
@@ -1,8 +1,9 @@
use std::collections::HashMap;
use wasmparser::{
BlockType, Data, Element, Export, ExternalKind, FunctionBody, Global, Import, MemoryType, Name,
NameSectionReader, Parser, Payload, Result, TableType, Type, TypeRef,
BlockType, Data, Element, Export, ExternalKind, FunctionBody, Global, Import, LocalsReader,
MemoryType, Name, NameSectionReader, Parser, Payload, Result, TableType, Type, TypeRef,
ValType,
};
#[derive(PartialEq, Eq, Clone, Copy)]
@@ -45,6 +46,14 @@ where
reader.into_iter().collect()
}
pub(crate) fn read_checked_locals(reader: LocalsReader) -> Result<Vec<ValType>> {
read_checked(reader).map(|locals| {
let convert = |(a, b)| std::iter::repeat(b).take(usize::try_from(a).unwrap());
locals.into_iter().flat_map(convert).collect()
})
}
pub struct Module<'a> {
type_section: Vec<Type>,
import_section: Vec<Import<'a>>,
+53 -33
View File
@@ -1,5 +1,3 @@
use std::ops::Range;
use wasmparser::{Operator, ValType};
#[allow(non_camel_case_types)]
@@ -627,22 +625,22 @@ impl Select {
}
}
pub struct GetTemporary {
pub struct Temporary {
pub(crate) var: usize,
}
impl GetTemporary {
impl Temporary {
#[must_use]
pub const fn var(&self) -> usize {
self.var
}
}
pub struct GetLocal {
pub struct Local {
pub(crate) var: usize,
}
impl GetLocal {
impl Local {
#[must_use]
pub const fn var(&self) -> usize {
self.var
@@ -797,8 +795,8 @@ impl CmpOp {
pub enum Expression {
Select(Select),
GetTemporary(GetTemporary),
GetLocal(GetLocal),
GetTemporary(Temporary),
GetLocal(Local),
GetGlobal(GetGlobal),
LoadAt(LoadAt),
MemorySize(MemorySize),
@@ -808,6 +806,28 @@ pub enum Expression {
CmpOp(CmpOp),
}
#[derive(Clone, Copy)]
pub struct ResultList {
start: usize,
end: usize,
}
impl ResultList {
#[must_use]
pub const fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.start == self.end
}
pub fn iter(self) -> impl Iterator<Item = Temporary> {
(self.start..self.end).map(|var| Temporary { var })
}
}
pub struct Align {
pub(crate) new: usize,
pub(crate) old: usize,
@@ -821,13 +841,13 @@ impl Align {
}
#[must_use]
pub const fn new_range(&self) -> Range<usize> {
self.new..self.new + self.length
pub const fn new_range(&self) -> ResultList {
ResultList::new(self.new, self.new + self.length)
}
#[must_use]
pub const fn old_range(&self) -> Range<usize> {
self.old..self.old + self.length
pub const fn old_range(&self) -> ResultList {
ResultList::new(self.old, self.old + self.length)
}
}
@@ -949,8 +969,8 @@ impl If {
pub struct Call {
pub(crate) function: usize,
pub(crate) result: Range<usize>,
pub(crate) param_list: Vec<Expression>,
pub(crate) result_list: ResultList,
}
impl Call {
@@ -960,21 +980,21 @@ impl Call {
}
#[must_use]
pub fn result(&self) -> Range<usize> {
self.result.clone()
pub fn param_list(&self) -> &[Expression] {
&self.param_list
}
#[must_use]
pub fn param_list(&self) -> &[Expression] {
&self.param_list
pub const fn result_list(&self) -> ResultList {
self.result_list
}
}
pub struct CallIndirect {
pub(crate) table: usize,
pub(crate) index: Box<Expression>,
pub(crate) result: Range<usize>,
pub(crate) param_list: Vec<Expression>,
pub(crate) result_list: ResultList,
}
impl CallIndirect {
@@ -989,25 +1009,25 @@ impl CallIndirect {
}
#[must_use]
pub fn result(&self) -> Range<usize> {
self.result.clone()
pub fn param_list(&self) -> &[Expression] {
&self.param_list
}
#[must_use]
pub fn param_list(&self) -> &[Expression] {
&self.param_list
pub const fn result_list(&self) -> ResultList {
self.result_list
}
}
pub struct SetTemporary {
pub(crate) var: usize,
pub(crate) var: Temporary,
pub(crate) value: Box<Expression>,
}
impl SetTemporary {
#[must_use]
pub const fn var(&self) -> usize {
self.var
pub const fn var(&self) -> &Temporary {
&self.var
}
#[must_use]
@@ -1017,14 +1037,14 @@ impl SetTemporary {
}
pub struct SetLocal {
pub(crate) var: usize,
pub(crate) var: Local,
pub(crate) value: Box<Expression>,
}
impl SetLocal {
#[must_use]
pub const fn var(&self) -> usize {
self.var
pub const fn var(&self) -> &Local {
&self.var
}
#[must_use]
@@ -1087,7 +1107,7 @@ impl StoreAt {
pub struct MemoryGrow {
pub(crate) memory: usize,
pub(crate) result: usize,
pub(crate) result: Temporary,
pub(crate) size: Box<Expression>,
}
@@ -1098,8 +1118,8 @@ impl MemoryGrow {
}
#[must_use]
pub const fn result(&self) -> usize {
self.result
pub const fn result(&self) -> &Temporary {
&self.result
}
#[must_use]
@@ -1187,7 +1207,7 @@ pub enum Statement {
}
pub struct FuncData {
pub(crate) local_data: Vec<(u32, ValType)>,
pub(crate) local_data: Vec<ValType>,
pub(crate) num_result: usize,
pub(crate) num_param: usize,
pub(crate) num_stack: usize,
@@ -1196,7 +1216,7 @@ pub struct FuncData {
impl FuncData {
#[must_use]
pub fn local_data(&self) -> &[(u32, ValType)] {
pub fn local_data(&self) -> &[ValType] {
&self.local_data
}
+12 -8
View File
@@ -1,7 +1,7 @@
use std::{collections::HashSet, ops::Range};
use std::collections::HashSet;
use crate::node::{
Align, Expression, GetGlobal, GetLocal, GetTemporary, LoadAt, SetTemporary, Statement,
Align, Expression, GetGlobal, LoadAt, Local, ResultList, SetTemporary, Statement, Temporary,
};
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
@@ -68,7 +68,7 @@ impl Stack {
pub fn push_with_single(&mut self, data: Expression) {
let mut read = HashSet::new();
let elem = match data {
Expression::GetLocal(GetLocal { var }) => ReadType::Local(var),
Expression::GetLocal(Local { var }) => ReadType::Local(var),
Expression::GetGlobal(GetGlobal { var }) => ReadType::Global(var),
Expression::LoadAt(LoadAt { memory, .. }) => ReadType::Memory(memory),
_ => unreachable!(),
@@ -94,19 +94,23 @@ impl Stack {
self.var_list.drain(desired..).map(|v| v.data)
}
pub fn push_temporary(&mut self, num: usize) -> Range<usize> {
pub fn push_temporaries(&mut self, num: usize) -> ResultList {
let start = self.previous + self.len();
let range = start..start + num;
self.capacity = self.capacity.max(range.end);
for var in range.clone() {
let data = Expression::GetTemporary(GetTemporary { var });
let data = Expression::GetTemporary(Temporary { var });
self.push(data);
}
range
ResultList::new(range.start, range.end)
}
pub fn push_temporary(&mut self) -> Temporary {
self.push_temporaries(1).iter().next().unwrap()
}
// Return the alignment necessary for this block to branch out to a
@@ -136,9 +140,9 @@ impl Stack {
old.read.clear();
let get = Expression::GetTemporary(GetTemporary { var });
let get = Expression::GetTemporary(Temporary { var });
let set = Statement::SetTemporary(SetTemporary {
var,
var: Temporary { var },
value: std::mem::replace(&mut old.data, get).into(),
});
+6 -6
View File
@@ -1,15 +1,15 @@
use crate::node::{
BinOp, Block, Br, BrIf, BrTable, Call, CallIndirect, CmpOp, Expression, FuncData, GetGlobal,
GetLocal, GetTemporary, If, LoadAt, MemoryCopy, MemoryFill, MemoryGrow, MemorySize, Select,
SetGlobal, SetLocal, SetTemporary, Statement, StoreAt, Terminator, UnOp, Value,
If, LoadAt, Local, MemoryCopy, MemoryFill, MemoryGrow, MemorySize, Select, SetGlobal, SetLocal,
SetTemporary, Statement, StoreAt, Temporary, Terminator, UnOp, Value,
};
pub trait Visitor {
fn visit_select(&mut self, _: &Select) {}
fn visit_get_temporary(&mut self, _: &GetTemporary) {}
fn visit_get_temporary(&mut self, _: &Temporary) {}
fn visit_get_local(&mut self, _: &GetLocal) {}
fn visit_get_local(&mut self, _: &Local) {}
fn visit_get_global(&mut self, _: &GetGlobal) {}
@@ -76,13 +76,13 @@ impl<T: Visitor> Driver<T> for Select {
}
}
impl<T: Visitor> Driver<T> for GetTemporary {
impl<T: Visitor> Driver<T> for Temporary {
fn accept(&self, visitor: &mut T) {
visitor.visit_get_temporary(self);
}
}
impl<T: Visitor> Driver<T> for GetLocal {
impl<T: Visitor> Driver<T> for Local {
fn accept(&self, visitor: &mut T) {
visitor.visit_get_local(self);
}