Unify integer types and simplify some code

This commit is contained in:
Rerumu 2022-04-22 21:57:43 -04:00
parent 233aee2c5e
commit e7b36a7d94
6 changed files with 101 additions and 90 deletions

View File

@ -6,7 +6,7 @@ use wasm_ast::{
}; };
struct Visit { struct Visit {
result: BTreeSet<u8>, result: BTreeSet<usize>,
} }
impl Visitor for Visit { impl Visitor for Visit {
@ -27,7 +27,7 @@ impl Visitor for Visit {
} }
} }
pub fn visit(func: &Function) -> BTreeSet<u8> { pub fn visit(func: &Function) -> BTreeSet<usize> {
let mut visit = Visit { let mut visit = Visit {
result: BTreeSet::new(), result: BTreeSet::new(),
}; };

View File

@ -58,7 +58,7 @@ fn write_func_name(wasm: &Module, index: u32, offset: u32, w: Writer) -> Result<
write!(w, "[{}] =", index + offset) write!(w, "[{}] =", index + offset)
} }
fn write_in_order(prefix: &str, len: u32, w: Writer) -> Result<()> { fn write_in_order(prefix: &str, len: usize, w: Writer) -> Result<()> {
if len == 0 { if len == 0 {
return Ok(()); return Ok(());
} }
@ -104,7 +104,7 @@ fn write_parameter_list(func: &Function, w: Writer) -> Result<()> {
write!(w, ")") write!(w, ")")
} }
fn write_result_list(range: Range<u32>, w: Writer) -> Result<()> { fn write_result_list(range: Range<usize>, w: Writer) -> Result<()> {
if range.is_empty() { if range.is_empty() {
return Ok(()); return Ok(());
} }
@ -123,7 +123,7 @@ fn write_result_list(range: Range<u32>, w: Writer) -> Result<()> {
fn write_variable_list(func: &Function, w: Writer) -> Result<()> { fn write_variable_list(func: &Function, w: Writer) -> Result<()> {
for data in &func.local_data { for data in &func.local_data {
write!(w, "local ")?; write!(w, "local ")?;
write_in_order("loc", data.count(), w)?; write_in_order("loc", data.count().try_into().unwrap(), w)?;
write!(w, " = ")?; write!(w, " = ")?;
for i in 0..data.count() { for i in 0..data.count() {
@ -190,7 +190,7 @@ fn condense_jump_table(list: &[u32]) -> Vec<(usize, usize, u32)> {
struct Visitor { struct Visitor {
label_list: Vec<usize>, label_list: Vec<usize>,
num_label: usize, num_label: usize,
num_param: u32, num_param: usize,
} }
impl Visitor { impl Visitor {
@ -204,12 +204,6 @@ impl Visitor {
fn pop_label(&mut self) { fn pop_label(&mut self) {
self.label_list.pop().unwrap(); self.label_list.pop().unwrap();
} }
fn get_label(&self, up: u32) -> usize {
let last = self.label_list.len() - 1;
self.label_list[last - up as usize]
}
} }
trait Driver { trait Driver {
@ -234,7 +228,7 @@ impl Driver for Select {
} }
} }
fn write_variable(var: u32, v: &Visitor, w: Writer) -> Result<()> { fn write_variable(var: usize, v: &Visitor, w: Writer) -> Result<()> {
if let Some(rem) = var.checked_sub(v.num_param) { if let Some(rem) = var.checked_sub(v.num_param) {
write!(w, "loc_{} ", rem) write!(w, "loc_{} ", rem)
} else { } else {
@ -451,8 +445,8 @@ impl Driver for If {
} }
} }
fn write_br_at(up: u32, v: &Visitor, w: Writer) -> Result<()> { fn write_br_at(up: usize, v: &Visitor, w: Writer) -> Result<()> {
let level = v.get_label(up); let level = v.label_list.iter().nth_back(up).unwrap();
write!(w, "goto continue_at_{} ", level) write!(w, "goto continue_at_{} ", level)
} }
@ -488,12 +482,12 @@ impl Driver for BrTable {
write!(w, "if temp >= {} and temp <= {} then ", start, end)?; write!(w, "if temp >= {} and temp <= {} then ", start, end)?;
} }
write_br_at(dest, v, w)?; write_br_at(dest.try_into().unwrap(), v, w)?;
write!(w, "else")?; write!(w, "else")?;
} }
write!(w, " ")?; write!(w, " ")?;
write_br_at(self.data.default, v, w)?; write_br_at(self.data.default.try_into().unwrap(), v, w)?;
write!(w, "end ") write!(w, "end ")
} }
} }

View File

@ -6,7 +6,7 @@ use wasm_ast::{
}; };
struct Visit { struct Visit {
result: BTreeSet<u8>, result: BTreeSet<usize>,
} }
impl Visitor for Visit { impl Visitor for Visit {
@ -27,7 +27,7 @@ impl Visitor for Visit {
} }
} }
pub fn visit(func: &Function) -> BTreeSet<u8> { pub fn visit(func: &Function) -> BTreeSet<usize> {
let mut visit = Visit { let mut visit = Visit {
result: BTreeSet::new(), result: BTreeSet::new(),
}; };

View File

@ -58,7 +58,7 @@ fn write_func_name(wasm: &Module, index: u32, offset: u32, w: Writer) -> Result<
write!(w, "[{}] =", index + offset) write!(w, "[{}] =", index + offset)
} }
fn write_in_order(prefix: &str, len: u32, w: Writer) -> Result<()> { fn write_in_order(prefix: &str, len: usize, w: Writer) -> Result<()> {
if len == 0 { if len == 0 {
return Ok(()); return Ok(());
} }
@ -103,7 +103,7 @@ fn write_parameter_list(func: &Function, w: Writer) -> Result<()> {
write!(w, ")") write!(w, ")")
} }
fn write_result_list(range: Range<u32>, w: Writer) -> Result<()> { fn write_result_list(range: Range<usize>, w: Writer) -> Result<()> {
if range.is_empty() { if range.is_empty() {
return Ok(()); return Ok(());
} }
@ -122,7 +122,7 @@ fn write_result_list(range: Range<u32>, w: Writer) -> Result<()> {
fn write_variable_list(func: &Function, w: Writer) -> Result<()> { fn write_variable_list(func: &Function, w: Writer) -> Result<()> {
for data in &func.local_data { for data in &func.local_data {
write!(w, "local ")?; write!(w, "local ")?;
write_in_order("loc", data.count(), w)?; write_in_order("loc", data.count().try_into().unwrap(), w)?;
write!(w, " = ")?; write!(w, " = ")?;
for i in 0..data.count() { for i in 0..data.count() {
@ -187,7 +187,7 @@ enum Label {
#[derive(Default)] #[derive(Default)]
struct Visitor { struct Visitor {
label_list: Vec<Label>, label_list: Vec<Label>,
num_param: u32, num_param: usize,
} }
impl Visitor { impl Visitor {
@ -198,6 +198,16 @@ impl Visitor {
None => Ok(()), None => Ok(()),
} }
} }
fn push_label(&mut self, label: Label) -> usize {
self.label_list.push(label);
self.label_list.len() - 1
}
fn pop_label(&mut self) {
self.label_list.pop().unwrap();
}
} }
trait Driver { trait Driver {
@ -222,7 +232,7 @@ impl Driver for Select {
} }
} }
fn write_variable(var: u32, v: &Visitor, w: Writer) -> Result<()> { fn write_variable(var: usize, v: &Visitor, w: Writer) -> Result<()> {
if let Some(rem) = var.checked_sub(v.num_param) { if let Some(rem) = var.checked_sub(v.num_param) {
write!(w, "loc_{} ", rem) write!(w, "loc_{} ", rem)
} else { } else {
@ -364,9 +374,7 @@ impl Driver for Memorize {
impl Driver for Forward { impl Driver for Forward {
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> { fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
let rem = v.label_list.len(); let rem = v.push_label(Label::Forward);
v.label_list.push(Label::Forward);
write!(w, "while true do ")?; write!(w, "while true do ")?;
@ -375,16 +383,14 @@ impl Driver for Forward {
write!(w, "break ")?; write!(w, "break ")?;
write!(w, "end ")?; write!(w, "end ")?;
v.label_list.pop().unwrap(); v.pop_label();
v.write_br_gadget(rem, w) v.write_br_gadget(rem, w)
} }
} }
impl Driver for Backward { impl Driver for Backward {
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> { fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
let rem = v.label_list.len(); let rem = v.push_label(Label::Backward);
v.label_list.push(Label::Backward);
write!(w, "while true do ")?; write!(w, "while true do ")?;
@ -393,7 +399,7 @@ impl Driver for Backward {
write!(w, "break ")?; write!(w, "break ")?;
write!(w, "end ")?; write!(w, "end ")?;
v.label_list.pop().unwrap(); v.pop_label();
v.write_br_gadget(rem, w) v.write_br_gadget(rem, w)
} }
} }
@ -408,9 +414,7 @@ impl Driver for Else {
impl Driver for If { impl Driver for If {
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> { fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
let rem = v.label_list.len(); let rem = v.push_label(Label::If);
v.label_list.push(Label::If);
write!(w, "while true do ")?; write!(w, "while true do ")?;
write!(w, "if ")?; write!(w, "if ")?;
@ -427,27 +431,24 @@ impl Driver for If {
write!(w, "break ")?; write!(w, "break ")?;
write!(w, "end ")?; write!(w, "end ")?;
v.label_list.pop().unwrap(); v.pop_label();
v.write_br_gadget(rem, w) v.write_br_gadget(rem, w)
} }
} }
fn write_br_at(up: u32, v: &Visitor, w: Writer) -> Result<()> { fn write_br_at(up: usize, v: &Visitor, w: Writer) -> Result<()> {
let up = up as usize;
let level = v.label_list.len() - 1;
write!(w, "do ")?; write!(w, "do ")?;
if up == 0 { if up == 0 {
let is_loop = v.label_list[level - up] == Label::Backward; if let Some(&Label::Backward) = v.label_list.last() {
if is_loop {
write!(w, "continue ")?; write!(w, "continue ")?;
} else { } else {
write!(w, "break ")?; write!(w, "break ")?;
} }
} else { } else {
write!(w, "desired = {} ", level - up)?; let level = v.label_list.len() - 1 - up;
write!(w, "desired = {} ", level)?;
write!(w, "break ")?; write!(w, "break ")?;
} }

View File

@ -11,26 +11,23 @@ use crate::node::{
}; };
struct Arity { struct Arity {
num_param: u32, num_param: usize,
num_result: u32, num_result: usize,
} }
impl Arity { impl Arity {
fn from_type(typ: &FunctionType) -> Self { fn from_type(typ: &FunctionType) -> Self {
let num_param = typ.params().len().try_into().unwrap();
let num_result = typ.results().len().try_into().unwrap();
Self { Self {
num_param, num_param: typ.params().len(),
num_result, num_result: typ.results().len(),
} }
} }
} }
pub struct TypeInfo<'a> { pub struct TypeInfo<'a> {
data: &'a [Type], data: &'a [Type],
func_ex: Vec<u32>, func_ex: Vec<usize>,
func_in: Vec<u32>, func_in: Vec<usize>,
} }
impl<'a> TypeInfo<'a> { impl<'a> TypeInfo<'a> {
@ -60,8 +57,8 @@ impl<'a> TypeInfo<'a> {
self.func_ex.len() self.func_ex.len()
} }
fn raw_arity_of(&self, index: u32) -> Arity { fn raw_arity_of(&self, index: usize) -> Arity {
let Type::Function(typ) = &self.data[index as usize]; let Type::Function(typ) = &self.data[index];
Arity::from_type(typ) Arity::from_type(typ)
} }
@ -77,15 +74,15 @@ impl<'a> TypeInfo<'a> {
self.raw_arity_of(*adjusted) self.raw_arity_of(*adjusted)
} }
fn func_of_import(import: &ImportEntry) -> Option<u32> { fn func_of_import(import: &ImportEntry) -> Option<usize> {
if let &External::Function(i) = import.external() { if let &External::Function(i) = import.external() {
Some(i) Some(i.try_into().unwrap())
} else { } else {
None None
} }
} }
fn new_ex_list(wasm: &Module) -> Vec<u32> { fn new_ex_list(wasm: &Module) -> Vec<usize> {
let list = wasm let list = wasm
.import_section() .import_section()
.map_or([].as_ref(), ImportSection::entries); .map_or([].as_ref(), ImportSection::entries);
@ -93,12 +90,15 @@ impl<'a> TypeInfo<'a> {
list.iter().filter_map(Self::func_of_import).collect() list.iter().filter_map(Self::func_of_import).collect()
} }
fn new_in_list(wasm: &Module) -> Vec<u32> { fn new_in_list(wasm: &Module) -> Vec<usize> {
let list = wasm let list = wasm
.function_section() .function_section()
.map_or([].as_ref(), FunctionSection::entries); .map_or([].as_ref(), FunctionSection::entries);
list.iter().map(Func::type_ref).collect() list.iter()
.map(Func::type_ref)
.map(|v| v.try_into().unwrap())
.collect()
} }
} }
@ -167,10 +167,10 @@ impl Stacked {
self.stack.push(value); self.stack.push(value);
} }
fn push_recall(&mut self, num: u32) { fn push_recall(&mut self, num: usize) {
let len = self.stack.len(); let len = self.stack.len();
for var in len..len + num as usize { for var in len..len + num {
self.stack.push(Expression::Recall(Recall { var })); self.stack.push(Expression::Recall(Recall { var }));
} }
} }
@ -263,7 +263,7 @@ impl Stacked {
pub struct Builder<'a> { pub struct Builder<'a> {
// target state // target state
type_info: &'a TypeInfo<'a>, type_info: &'a TypeInfo<'a>,
num_result: u32, num_result: usize,
// translation state // translation state
data: Stacked, data: Stacked,
@ -297,7 +297,7 @@ impl<'a> Builder<'a> {
self.num_result = arity.num_result; self.num_result = arity.num_result;
let code = self.new_forward(&mut func.code().elements()); let code = self.new_forward(&mut func.code().elements());
let num_stack = self.data.last_stack.try_into().unwrap(); let num_stack = self.data.last_stack;
Function { Function {
local_data: func.locals().to_vec(), local_data: func.locals().to_vec(),
@ -313,26 +313,29 @@ impl<'a> Builder<'a> {
return; return;
} }
BlockType::Value(_) => 1, BlockType::Value(_) => 1,
BlockType::TypeIndex(i) => self.type_info.raw_arity_of(i).num_result, BlockType::TypeIndex(i) => {
self.type_info
.raw_arity_of(i.try_into().unwrap())
.num_result
}
}; };
self.data.push_recall(num); self.data.push_recall(num);
} }
fn gen_return(&mut self, stat: &mut Vec<Statement>) { fn gen_return(&mut self, stat: &mut Vec<Statement>) {
let num = self.num_result as usize; let list = self.data.pop_many(self.num_result);
let list = self.data.pop_many(num);
self.data.gen_leak_pending(stat); self.data.gen_leak_pending(stat);
stat.push(Statement::Return(Return { list })); stat.push(Statement::Return(Return { list }));
} }
fn gen_call(&mut self, func: u32, stat: &mut Vec<Statement>) { fn gen_call(&mut self, func: usize, stat: &mut Vec<Statement>) {
let arity = self.type_info.arity_of(func as usize); let arity = self.type_info.arity_of(func);
let param_list = self.data.pop_many(arity.num_param as usize); let param_list = self.data.pop_many(arity.num_param);
let first = u32::try_from(self.data.stack.len()).unwrap(); let first = self.data.stack.len();
let result = first..first + arity.num_result; let result = first..first + arity.num_result;
self.data.push_recall(arity.num_result); self.data.push_recall(arity.num_result);
@ -345,12 +348,12 @@ impl<'a> Builder<'a> {
})); }));
} }
fn gen_call_indirect(&mut self, typ: u32, table: u8, stat: &mut Vec<Statement>) { fn gen_call_indirect(&mut self, typ: usize, table: usize, stat: &mut Vec<Statement>) {
let arity = self.type_info.raw_arity_of(typ); let arity = self.type_info.raw_arity_of(typ);
let index = self.data.pop(); let index = self.data.pop();
let param_list = self.data.pop_many(arity.num_param as usize); let param_list = self.data.pop_many(arity.num_param);
let first = u32::try_from(self.data.stack.len()).unwrap(); let first = self.data.stack.len();
let result = first..first + arity.num_result; let result = first..first + arity.num_result;
self.data.push_recall(arity.num_result); self.data.push_recall(arity.num_result);
@ -458,10 +461,13 @@ impl<'a> Builder<'a> {
break; break;
} }
Inst::Br(target) => { Inst::Br(target) => {
let target = target.try_into().unwrap();
self.data.gen_leak_pending(&mut stat); self.data.gen_leak_pending(&mut stat);
stat.push(Statement::Br(Br { target })); stat.push(Statement::Br(Br { target }));
} }
Inst::BrIf(target) => { Inst::BrIf(target) => {
let target = target.try_into().unwrap();
let cond = self.data.pop(); let cond = self.data.pop();
self.data.gen_leak_pending(&mut stat); self.data.gen_leak_pending(&mut stat);
@ -480,10 +486,10 @@ impl<'a> Builder<'a> {
self.gen_return(&mut stat); self.gen_return(&mut stat);
} }
Inst::Call(i) => { Inst::Call(i) => {
self.gen_call(i, &mut stat); self.gen_call(i.try_into().unwrap(), &mut stat);
} }
Inst::CallIndirect(i, t) => { Inst::CallIndirect(i, t) => {
self.gen_call_indirect(i, t, &mut stat); self.gen_call_indirect(i.try_into().unwrap(), t.into(), &mut stat);
} }
Inst::Drop => { Inst::Drop => {
self.data.pop(); self.data.pop();
@ -496,9 +502,12 @@ impl<'a> Builder<'a> {
self.data.push(Expression::Select(Select { cond, a, b })); self.data.push(Expression::Select(Select { cond, a, b }));
} }
Inst::GetLocal(var) => { Inst::GetLocal(var) => {
let var = var.try_into().unwrap();
self.data.push(Expression::GetLocal(GetLocal { var })); self.data.push(Expression::GetLocal(GetLocal { var }));
} }
Inst::SetLocal(var) => { Inst::SetLocal(var) => {
let var = var.try_into().unwrap();
let value = self.data.pop(); let value = self.data.pop();
self.data.gen_leak_pending(&mut stat); self.data.gen_leak_pending(&mut stat);
@ -507,15 +516,19 @@ impl<'a> Builder<'a> {
Inst::TeeLocal(var) => { Inst::TeeLocal(var) => {
self.data.gen_leak_pending(&mut stat); self.data.gen_leak_pending(&mut stat);
let var = var.try_into().unwrap();
let value = self.data.pop(); let value = self.data.pop();
self.data.push(value.clone_recall()); self.data.push(value.clone_recall());
stat.push(Statement::SetLocal(SetLocal { var, value })); stat.push(Statement::SetLocal(SetLocal { var, value }));
} }
Inst::GetGlobal(var) => { Inst::GetGlobal(var) => {
let var = var.try_into().unwrap();
self.data.push(Expression::GetGlobal(GetGlobal { var })); self.data.push(Expression::GetGlobal(GetGlobal { var }));
} }
Inst::SetGlobal(var) => { Inst::SetGlobal(var) => {
let var = var.try_into().unwrap();
let value = self.data.pop(); let value = self.data.pop();
stat.push(Statement::SetGlobal(SetGlobal { var, value })); stat.push(Statement::SetGlobal(SetGlobal { var, value }));
@ -544,10 +557,13 @@ impl<'a> Builder<'a> {
Inst::I64Store16(_, o) => self.data.gen_store(Store::I64_N16, o, &mut stat), Inst::I64Store16(_, o) => self.data.gen_store(Store::I64_N16, o, &mut stat),
Inst::I64Store32(_, o) => self.data.gen_store(Store::I64_N32, o, &mut stat), Inst::I64Store32(_, o) => self.data.gen_store(Store::I64_N32, o, &mut stat),
Inst::CurrentMemory(memory) => { Inst::CurrentMemory(memory) => {
let memory = memory.try_into().unwrap();
self.data self.data
.push(Expression::MemorySize(MemorySize { memory })); .push(Expression::MemorySize(MemorySize { memory }));
} }
Inst::GrowMemory(memory) => { Inst::GrowMemory(memory) => {
let memory = memory.try_into().unwrap();
let value = Box::new(self.data.pop()); let value = Box::new(self.data.pop());
// `MemoryGrow` is an expression *but* it has side effects // `MemoryGrow` is an expression *but* it has side effects

View File

@ -575,11 +575,11 @@ pub struct Select {
} }
pub struct GetLocal { pub struct GetLocal {
pub var: u32, pub var: usize,
} }
pub struct GetGlobal { pub struct GetGlobal {
pub var: u32, pub var: usize,
} }
pub struct AnyLoad { pub struct AnyLoad {
@ -589,11 +589,11 @@ pub struct AnyLoad {
} }
pub struct MemorySize { pub struct MemorySize {
pub memory: u8, pub memory: usize,
} }
pub struct MemoryGrow { pub struct MemoryGrow {
pub memory: u8, pub memory: usize,
pub value: Box<Expression>, pub value: Box<Expression>,
} }
@ -702,12 +702,12 @@ pub struct If {
} }
pub struct Br { pub struct Br {
pub target: u32, pub target: usize,
} }
pub struct BrIf { pub struct BrIf {
pub cond: Expression, pub cond: Expression,
pub target: u32, pub target: usize,
} }
pub struct BrTable { pub struct BrTable {
@ -720,25 +720,25 @@ pub struct Return {
} }
pub struct Call { pub struct Call {
pub func: u32, pub func: usize,
pub result: Range<u32>, pub result: Range<usize>,
pub param_list: Vec<Expression>, pub param_list: Vec<Expression>,
} }
pub struct CallIndirect { pub struct CallIndirect {
pub table: u8, pub table: usize,
pub index: Expression, pub index: Expression,
pub result: Range<u32>, pub result: Range<usize>,
pub param_list: Vec<Expression>, pub param_list: Vec<Expression>,
} }
pub struct SetLocal { pub struct SetLocal {
pub var: u32, pub var: usize,
pub value: Expression, pub value: Expression,
} }
pub struct SetGlobal { pub struct SetGlobal {
pub var: u32, pub var: usize,
pub value: Expression, pub value: Expression,
} }
@ -768,7 +768,7 @@ pub enum Statement {
pub struct Function { pub struct Function {
pub local_data: Vec<Local>, pub local_data: Vec<Local>,
pub num_param: u32, pub num_param: usize,
pub num_stack: u32, pub num_stack: usize,
pub code: Forward, pub code: Forward,
} }