Add context-less writing

This commit is contained in:
Rerumu 2022-08-20 17:55:11 -04:00
parent 33bd235c0f
commit 369097c432
8 changed files with 260 additions and 230 deletions

View File

@ -10,7 +10,7 @@ use wasm_ast::node::{
use crate::analyzer::as_symbol::AsSymbol; use crate::analyzer::as_symbol::AsSymbol;
use super::manager::{write_cmp_op, write_condition, write_separated, Driver, Manager}; use super::manager::{write_separated, DriverNoContext};
macro_rules! impl_write_number { macro_rules! impl_write_number {
($name:tt, $numeric:ty) => { ($name:tt, $numeric:ty) => {
@ -26,40 +26,40 @@ macro_rules! impl_write_number {
}; };
} }
impl Driver for Select { impl DriverNoContext for Select {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "(")?; write!(w, "(")?;
write_condition(self.condition(), mng, w)?; Condition(self.condition()).write(w)?;
write!(w, "and ")?; write!(w, "and ")?;
self.on_true().write(mng, w)?; self.on_true().write(w)?;
write!(w, "or ")?; write!(w, "or ")?;
self.on_false().write(mng, w)?; self.on_false().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for GetTemporary { impl DriverNoContext for GetTemporary {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "reg_{} ", self.var()) write!(w, "reg_{} ", self.var())
} }
} }
impl Driver for GetLocal { impl DriverNoContext for GetLocal {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "loc_{} ", self.var()) write!(w, "loc_{} ", self.var())
} }
} }
impl Driver for GetGlobal { impl DriverNoContext for GetGlobal {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "GLOBAL_LIST[{}].value ", self.var()) write!(w, "GLOBAL_LIST[{}].value ", self.var())
} }
} }
impl Driver for LoadAt { impl DriverNoContext for LoadAt {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "load_{}(memory_at_0, ", self.load_type().as_name())?; write!(w, "load_{}(memory_at_0, ", self.load_type().as_name())?;
self.pointer().write(mng, w)?; self.pointer().write(w)?;
if self.offset() != 0 { if self.offset() != 0 {
write!(w, "+ {}", self.offset())?; write!(w, "+ {}", self.offset())?;
@ -69,8 +69,8 @@ impl Driver for LoadAt {
} }
} }
impl Driver for MemorySize { impl DriverNoContext for MemorySize {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "memory_at_{}.min ", self.memory()) write!(w, "memory_at_{}.min ", self.memory())
} }
} }
@ -78,8 +78,8 @@ impl Driver for MemorySize {
impl_write_number!(write_f32, f32); impl_write_number!(write_f32, f32);
impl_write_number!(write_f64, f64); impl_write_number!(write_f64, f64);
impl Driver for Value { impl DriverNoContext for Value {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
match self { match self {
Self::I32(i) => write!(w, "{i} "), Self::I32(i) => write!(w, "{i} "),
Self::I64(i) => write!(w, "{i}LL "), Self::I64(i) => write!(w, "{i}LL "),
@ -89,63 +89,98 @@ impl Driver for Value {
} }
} }
impl Driver for UnOp { impl DriverNoContext for UnOp {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
let (a, b) = self.op_type().as_name(); let (a, b) = self.op_type().as_name();
write!(w, "{a}_{b}(")?; write!(w, "{a}_{b}(")?;
self.rhs().write(mng, w)?; self.rhs().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for BinOp { impl DriverNoContext for BinOp {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
if let Some(symbol) = self.op_type().as_symbol() { if let Some(symbol) = self.op_type().as_symbol() {
write!(w, "(")?; write!(w, "(")?;
self.lhs().write(mng, w)?; self.lhs().write(w)?;
write!(w, "{symbol} ")?; write!(w, "{symbol} ")?;
self.rhs().write(mng, w)?; self.rhs().write(w)?;
write!(w, ")") write!(w, ")")
} else { } else {
let (head, tail) = self.op_type().as_name(); let (head, tail) = self.op_type().as_name();
write!(w, "{head}_{tail}(")?; write!(w, "{head}_{tail}(")?;
self.lhs().write(mng, w)?; self.lhs().write(w)?;
write!(w, ", ")?; write!(w, ", ")?;
self.rhs().write(mng, w)?; self.rhs().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
} }
impl Driver for CmpOp { struct CmpOpBoolean<'a>(&'a CmpOp);
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
write!(w, "(")?;
write_cmp_op(self, mng, w)?;
write!(w, "and 1 or 0)")
}
}
impl Driver for Expression { impl DriverNoContext for CmpOpBoolean<'_> {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
match self { let cmp = self.0;
Self::Select(e) => e.write(mng, w),
Self::GetTemporary(e) => e.write(mng, w), if let Some(symbol) = cmp.op_type().as_symbol() {
Self::GetLocal(e) => e.write(mng, w), cmp.lhs().write(w)?;
Self::GetGlobal(e) => e.write(mng, w), write!(w, "{symbol} ")?;
Self::LoadAt(e) => e.write(mng, w), cmp.rhs().write(w)
Self::MemorySize(e) => e.write(mng, w), } else {
Self::Value(e) => e.write(mng, w), let (head, tail) = cmp.op_type().as_name();
Self::UnOp(e) => e.write(mng, w),
Self::BinOp(e) => e.write(mng, w), write!(w, "{head}_{tail}(")?;
Self::CmpOp(e) => e.write(mng, w), cmp.lhs().write(w)?;
write!(w, ", ")?;
cmp.rhs().write(w)?;
write!(w, ")")
} }
} }
} }
impl Driver for &[Expression] { impl DriverNoContext for CmpOp {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write_separated(self.iter(), |e, w| e.write(mng, w), w) write!(w, "(")?;
CmpOpBoolean(self).write(w)?;
write!(w, "and 1 or 0)")
}
}
pub struct Condition<'a>(pub &'a Expression);
impl DriverNoContext for Condition<'_> {
fn write(&self, w: &mut dyn Write) -> Result<()> {
if let Expression::CmpOp(node) = self.0 {
CmpOpBoolean(node).write(w)
} else {
self.0.write(w)?;
write!(w, "~= 0 ")
}
}
}
impl DriverNoContext for Expression {
fn write(&self, w: &mut dyn Write) -> Result<()> {
match self {
Self::Select(e) => e.write(w),
Self::GetTemporary(e) => e.write(w),
Self::GetLocal(e) => e.write(w),
Self::GetGlobal(e) => e.write(w),
Self::LoadAt(e) => e.write(w),
Self::MemorySize(e) => e.write(w),
Self::Value(e) => e.write(w),
Self::UnOp(e) => e.write(w),
Self::BinOp(e) => e.write(w),
Self::CmpOp(e) => e.write(w),
}
}
}
impl DriverNoContext for &[Expression] {
fn write(&self, w: &mut dyn Write) -> Result<()> {
write_separated(self.iter(), |e, w| e.write(w), w)
} }
} }

View File

@ -4,9 +4,7 @@ use std::{
ops::Range, ops::Range,
}; };
use wasm_ast::node::{BrTable, CmpOp, Expression}; use wasm_ast::node::BrTable;
use crate::analyzer::as_symbol::AsSymbol;
#[derive(Default)] #[derive(Default)]
pub struct Manager { pub struct Manager {
@ -46,6 +44,10 @@ pub trait Driver {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()>; fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()>;
} }
pub trait DriverNoContext {
fn write(&self, w: &mut dyn Write) -> Result<()>;
}
pub fn write_separated<I, T, M>(mut iter: I, mut func: M, w: &mut dyn Write) -> Result<()> pub fn write_separated<I, T, M>(mut iter: I, mut func: M, w: &mut dyn Write) -> Result<()>
where where
M: FnMut(T, &mut dyn Write) -> Result<()>, M: FnMut(T, &mut dyn Write) -> Result<()>,
@ -65,28 +67,3 @@ where
pub fn write_ascending(prefix: &str, range: Range<usize>, w: &mut dyn Write) -> Result<()> { pub fn write_ascending(prefix: &str, range: Range<usize>, w: &mut dyn Write) -> Result<()> {
write_separated(range, |i, w| write!(w, "{prefix}_{i}"), w) write_separated(range, |i, w| write!(w, "{prefix}_{i}"), w)
} }
pub fn write_cmp_op(cmp: &CmpOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
if let Some(symbol) = cmp.op_type().as_symbol() {
cmp.lhs().write(mng, w)?;
write!(w, "{symbol} ")?;
cmp.rhs().write(mng, w)
} else {
let (head, tail) = cmp.op_type().as_name();
write!(w, "{head}_{tail}(")?;
cmp.lhs().write(mng, w)?;
write!(w, ", ")?;
cmp.rhs().write(mng, w)?;
write!(w, ")")
}
}
pub fn write_condition(data: &Expression, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
if let Expression::CmpOp(node) = data {
write_cmp_op(node, mng, w)
} else {
data.write(mng, w)?;
write!(w, "~= 0 ")
}
}

View File

@ -11,7 +11,10 @@ use wasmparser::ValType;
use crate::analyzer::br_table; use crate::analyzer::br_table;
use super::manager::{write_ascending, write_condition, write_separated, Driver, Manager}; use super::{
expression::Condition,
manager::{write_ascending, write_separated, Driver, DriverNoContext, Manager},
};
impl Driver for Br { impl Driver for Br {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
@ -82,7 +85,7 @@ fn write_table_setup(table: &BrTable, mng: &mut Manager, w: &mut dyn Write) -> R
write!(w, "end ")?; write!(w, "end ")?;
write!(w, "temp = br_map[{id}][")?; write!(w, "temp = br_map[{id}][")?;
table.condition().write(mng, w)?; table.condition().write(w)?;
write!(w, "] or {} ", table.default().target()) write!(w, "] or {} ", table.default().target())
} }
@ -156,7 +159,7 @@ impl Driver for Block {
impl Driver for BrIf { impl Driver for BrIf {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
write!(w, "if ")?; write!(w, "if ")?;
write_condition(self.condition(), mng, w)?; Condition(self.condition()).write(w)?;
write!(w, "then ")?; write!(w, "then ")?;
self.target().write(mng, w)?; self.target().write(mng, w)?;
write!(w, "end ") write!(w, "end ")
@ -166,7 +169,7 @@ impl Driver for BrIf {
impl Driver for If { impl Driver for If {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
write!(w, "if ")?; write!(w, "if ")?;
write_condition(self.condition(), mng, w)?; Condition(self.condition()).write(w)?;
write!(w, "then ")?; write!(w, "then ")?;
self.on_true().write(mng, w)?; self.on_true().write(mng, w)?;
@ -190,71 +193,71 @@ fn write_call_store(result: Range<usize>, w: &mut dyn Write) -> Result<()> {
write!(w, " = ") write!(w, " = ")
} }
impl Driver for Call { impl DriverNoContext for Call {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write_call_store(self.result(), w)?; write_call_store(self.result(), w)?;
write!(w, "FUNC_LIST[{}](", self.function())?; write!(w, "FUNC_LIST[{}](", self.function())?;
self.param_list().write(mng, w)?; self.param_list().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for CallIndirect { impl DriverNoContext for CallIndirect {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write_call_store(self.result(), w)?; write_call_store(self.result(), w)?;
write!(w, "TABLE_LIST[{}].data[", self.table())?; write!(w, "TABLE_LIST[{}].data[", self.table())?;
self.index().write(mng, w)?; self.index().write(w)?;
write!(w, "](")?; write!(w, "](")?;
self.param_list().write(mng, w)?; self.param_list().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for SetTemporary { impl DriverNoContext for SetTemporary {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "reg_{} = ", self.var())?; write!(w, "reg_{} = ", self.var())?;
self.value().write(mng, w) self.value().write(w)
} }
} }
impl Driver for SetLocal { impl DriverNoContext for SetLocal {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "loc_{} = ", self.var())?; write!(w, "loc_{} = ", self.var())?;
self.value().write(mng, w) self.value().write(w)
} }
} }
impl Driver for SetGlobal { impl DriverNoContext for SetGlobal {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "GLOBAL_LIST[{}].value = ", self.var())?; write!(w, "GLOBAL_LIST[{}].value = ", self.var())?;
self.value().write(mng, w) self.value().write(w)
} }
} }
impl Driver for StoreAt { impl DriverNoContext for StoreAt {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "store_{}(memory_at_0, ", self.store_type().as_name())?; write!(w, "store_{}(memory_at_0, ", self.store_type().as_name())?;
self.pointer().write(mng, w)?; self.pointer().write(w)?;
if self.offset() != 0 { if self.offset() != 0 {
write!(w, "+ {}", self.offset())?; write!(w, "+ {}", self.offset())?;
} }
write!(w, ", ")?; write!(w, ", ")?;
self.value().write(mng, w)?; self.value().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for MemoryGrow { impl DriverNoContext for MemoryGrow {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
let result = self.result(); let result = self.result();
let memory = self.memory(); let memory = self.memory();
write!(w, "reg_{result} = rt.allocator.grow(memory_at_{memory}, ")?; write!(w, "reg_{result} = rt.allocator.grow(memory_at_{memory}, ")?;
self.size().write(mng, w)?; self.size().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
@ -265,13 +268,13 @@ impl Driver for Statement {
Self::Block(s) => s.write(mng, w), Self::Block(s) => s.write(mng, w),
Self::BrIf(s) => s.write(mng, w), Self::BrIf(s) => s.write(mng, w),
Self::If(s) => s.write(mng, w), Self::If(s) => s.write(mng, w),
Self::Call(s) => s.write(mng, w), Self::Call(s) => s.write(w),
Self::CallIndirect(s) => s.write(mng, w), Self::CallIndirect(s) => s.write(w),
Self::SetTemporary(s) => s.write(mng, w), Self::SetTemporary(s) => s.write(w),
Self::SetLocal(s) => s.write(mng, w), Self::SetLocal(s) => s.write(w),
Self::SetGlobal(s) => s.write(mng, w), Self::SetGlobal(s) => s.write(w),
Self::StoreAt(s) => s.write(mng, w), Self::StoreAt(s) => s.write(w),
Self::MemoryGrow(s) => s.write(mng, w), Self::MemoryGrow(s) => s.write(w),
} }
} }
} }

View File

@ -15,7 +15,7 @@ use wasmparser::{
use crate::{ use crate::{
analyzer::localize, analyzer::localize,
backend::manager::{Driver, Manager}, backend::manager::{Driver, DriverNoContext, Manager},
}; };
trait AsIEName { trait AsIEName {
@ -54,7 +54,7 @@ fn write_constant(init: &InitExpr, type_info: &TypeInfo, w: &mut dyn Write) -> R
let func = Factory::from_type_info(type_info).create_anonymous(&code); let func = Factory::from_type_info(type_info).create_anonymous(&code);
if let Some(Statement::SetTemporary(stat)) = func.code().code().last() { if let Some(Statement::SetTemporary(stat)) = func.code().code().last() {
stat.value().write(&mut Manager::default(), w) stat.value().write(w)
} else { } else {
write!(w, r#"error("Valueless constant")"#) write!(w, r#"error("Valueless constant")"#)
} }

View File

@ -10,7 +10,7 @@ use wasm_ast::node::{
use crate::analyzer::as_symbol::AsSymbol; use crate::analyzer::as_symbol::AsSymbol;
use super::manager::{write_cmp_op, write_condition, write_separated, Driver, Manager}; use super::manager::{write_separated, DriverNoContext};
macro_rules! impl_write_number { macro_rules! impl_write_number {
($name:tt, $numeric:ty) => { ($name:tt, $numeric:ty) => {
@ -26,40 +26,40 @@ macro_rules! impl_write_number {
}; };
} }
impl Driver for Select { impl DriverNoContext for Select {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "(")?; write!(w, "(")?;
write_condition(self.condition(), mng, w)?; Condition(self.condition()).write(w)?;
write!(w, "and ")?; write!(w, "and ")?;
self.on_true().write(mng, w)?; self.on_true().write(w)?;
write!(w, "or ")?; write!(w, "or ")?;
self.on_false().write(mng, w)?; self.on_false().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for GetTemporary { impl DriverNoContext for GetTemporary {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "reg_{} ", self.var()) write!(w, "reg_{} ", self.var())
} }
} }
impl Driver for GetLocal { impl DriverNoContext for GetLocal {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "loc_{} ", self.var()) write!(w, "loc_{} ", self.var())
} }
} }
impl Driver for GetGlobal { impl DriverNoContext for GetGlobal {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "GLOBAL_LIST[{}].value ", self.var()) write!(w, "GLOBAL_LIST[{}].value ", self.var())
} }
} }
impl Driver for LoadAt { impl DriverNoContext for LoadAt {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "load_{}(memory_at_0, ", self.load_type().as_name())?; write!(w, "load_{}(memory_at_0, ", self.load_type().as_name())?;
self.pointer().write(mng, w)?; self.pointer().write(w)?;
if self.offset() != 0 { if self.offset() != 0 {
write!(w, "+ {}", self.offset())?; write!(w, "+ {}", self.offset())?;
@ -69,8 +69,8 @@ impl Driver for LoadAt {
} }
} }
impl Driver for MemorySize { impl DriverNoContext for MemorySize {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "memory_at_{}.min ", self.memory()) write!(w, "memory_at_{}.min ", self.memory())
} }
} }
@ -98,8 +98,8 @@ fn write_i64(number: i64, w: &mut dyn Write) -> Result<()> {
impl_write_number!(write_f32, f32); impl_write_number!(write_f32, f32);
impl_write_number!(write_f64, f64); impl_write_number!(write_f64, f64);
impl Driver for Value { impl DriverNoContext for Value {
fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
match self { match self {
Self::I32(i) => write_i32(*i, w), Self::I32(i) => write_i32(*i, w),
Self::I64(i) => write_i64(*i, w), Self::I64(i) => write_i64(*i, w),
@ -109,63 +109,98 @@ impl Driver for Value {
} }
} }
impl Driver for UnOp { impl DriverNoContext for UnOp {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
let (a, b) = self.op_type().as_name(); let (a, b) = self.op_type().as_name();
write!(w, "{a}_{b}(")?; write!(w, "{a}_{b}(")?;
self.rhs().write(mng, w)?; self.rhs().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for BinOp { impl DriverNoContext for BinOp {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
if let Some(symbol) = self.op_type().as_symbol() { if let Some(symbol) = self.op_type().as_symbol() {
write!(w, "(")?; write!(w, "(")?;
self.lhs().write(mng, w)?; self.lhs().write(w)?;
write!(w, "{symbol} ")?; write!(w, "{symbol} ")?;
self.rhs().write(mng, w)?; self.rhs().write(w)?;
write!(w, ")") write!(w, ")")
} else { } else {
let (head, tail) = self.op_type().as_name(); let (head, tail) = self.op_type().as_name();
write!(w, "{head}_{tail}(")?; write!(w, "{head}_{tail}(")?;
self.lhs().write(mng, w)?; self.lhs().write(w)?;
write!(w, ", ")?; write!(w, ", ")?;
self.rhs().write(mng, w)?; self.rhs().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
} }
impl Driver for CmpOp { struct CmpOpBoolean<'a>(&'a CmpOp);
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
write!(w, "(")?;
write_cmp_op(self, mng, w)?;
write!(w, "and 1 or 0)")
}
}
impl Driver for Expression { impl DriverNoContext for CmpOpBoolean<'_> {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
match self { let cmp = self.0;
Self::Select(e) => e.write(mng, w),
Self::GetTemporary(e) => e.write(mng, w), if let Some(symbol) = cmp.op_type().as_symbol() {
Self::GetLocal(e) => e.write(mng, w), cmp.lhs().write(w)?;
Self::GetGlobal(e) => e.write(mng, w), write!(w, "{symbol} ")?;
Self::LoadAt(e) => e.write(mng, w), cmp.rhs().write(w)
Self::MemorySize(e) => e.write(mng, w), } else {
Self::Value(e) => e.write(mng, w), let (head, tail) = cmp.op_type().as_name();
Self::UnOp(e) => e.write(mng, w),
Self::BinOp(e) => e.write(mng, w), write!(w, "{head}_{tail}(")?;
Self::CmpOp(e) => e.write(mng, w), cmp.lhs().write(w)?;
write!(w, ", ")?;
cmp.rhs().write(w)?;
write!(w, ")")
} }
} }
} }
impl Driver for &[Expression] { impl DriverNoContext for CmpOp {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write_separated(self.iter(), |e, w| e.write(mng, w), w) write!(w, "(")?;
CmpOpBoolean(self).write(w)?;
write!(w, "and 1 or 0)")
}
}
pub struct Condition<'a>(pub &'a Expression);
impl DriverNoContext for Condition<'_> {
fn write(&self, w: &mut dyn Write) -> Result<()> {
if let Expression::CmpOp(node) = self.0 {
CmpOpBoolean(node).write(w)
} else {
self.0.write(w)?;
write!(w, "~= 0 ")
}
}
}
impl DriverNoContext for Expression {
fn write(&self, w: &mut dyn Write) -> Result<()> {
match self {
Self::Select(e) => e.write(w),
Self::GetTemporary(e) => e.write(w),
Self::GetLocal(e) => e.write(w),
Self::GetGlobal(e) => e.write(w),
Self::LoadAt(e) => e.write(w),
Self::MemorySize(e) => e.write(w),
Self::Value(e) => e.write(w),
Self::UnOp(e) => e.write(w),
Self::BinOp(e) => e.write(w),
Self::CmpOp(e) => e.write(w),
}
}
}
impl DriverNoContext for &[Expression] {
fn write(&self, w: &mut dyn Write) -> Result<()> {
write_separated(self.iter(), |e, w| e.write(w), w)
} }
} }

View File

@ -4,9 +4,7 @@ use std::{
ops::Range, ops::Range,
}; };
use wasm_ast::node::{BrTable, CmpOp, Expression, LabelType}; use wasm_ast::node::{BrTable, LabelType};
use crate::analyzer::as_symbol::AsSymbol;
#[derive(Default)] #[derive(Default)]
pub struct Manager { pub struct Manager {
@ -42,6 +40,10 @@ pub trait Driver {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()>; fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()>;
} }
pub trait DriverNoContext {
fn write(&self, w: &mut dyn Write) -> Result<()>;
}
pub fn write_separated<I, T, M>(mut iter: I, mut func: M, w: &mut dyn Write) -> Result<()> pub fn write_separated<I, T, M>(mut iter: I, mut func: M, w: &mut dyn Write) -> Result<()>
where where
M: FnMut(T, &mut dyn Write) -> Result<()>, M: FnMut(T, &mut dyn Write) -> Result<()>,
@ -61,28 +63,3 @@ where
pub fn write_ascending(prefix: &str, range: Range<usize>, w: &mut dyn Write) -> Result<()> { pub fn write_ascending(prefix: &str, range: Range<usize>, w: &mut dyn Write) -> Result<()> {
write_separated(range, |i, w| write!(w, "{prefix}_{i}"), w) write_separated(range, |i, w| write!(w, "{prefix}_{i}"), w)
} }
pub fn write_cmp_op(cmp: &CmpOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
if let Some(symbol) = cmp.op_type().as_symbol() {
cmp.lhs().write(mng, w)?;
write!(w, "{symbol} ")?;
cmp.rhs().write(mng, w)
} else {
let (head, tail) = cmp.op_type().as_name();
write!(w, "{head}_{tail}(")?;
cmp.lhs().write(mng, w)?;
write!(w, ", ")?;
cmp.rhs().write(mng, w)?;
write!(w, ")")
}
}
pub fn write_condition(data: &Expression, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
if let Expression::CmpOp(node) = data {
write_cmp_op(node, mng, w)
} else {
data.write(mng, w)?;
write!(w, "~= 0 ")
}
}

View File

@ -11,7 +11,10 @@ use wasmparser::ValType;
use crate::analyzer::br_target; use crate::analyzer::br_target;
use super::manager::{write_ascending, write_condition, write_separated, Driver, Manager}; use super::{
expression::Condition,
manager::{write_ascending, write_separated, Driver, DriverNoContext, Manager},
};
impl Driver for Br { impl Driver for Br {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
@ -90,7 +93,7 @@ fn write_table_setup(table: &BrTable, mng: &mut Manager, w: &mut dyn Write) -> R
write!(w, "end ")?; write!(w, "end ")?;
write!(w, "local temp = br_map[{id}][")?; write!(w, "local temp = br_map[{id}][")?;
table.condition().write(mng, w)?; table.condition().write(w)?;
write!(w, "] or {} ", table.default().target()) write!(w, "] or {} ", table.default().target())
} }
@ -170,7 +173,7 @@ impl Driver for Block {
impl Driver for BrIf { impl Driver for BrIf {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
write!(w, "if ")?; write!(w, "if ")?;
write_condition(self.condition(), mng, w)?; Condition(self.condition()).write(w)?;
write!(w, "then ")?; write!(w, "then ")?;
self.target().write(mng, w)?; self.target().write(mng, w)?;
write!(w, "end ") write!(w, "end ")
@ -180,7 +183,7 @@ impl Driver for BrIf {
impl Driver for If { impl Driver for If {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
write!(w, "if ")?; write!(w, "if ")?;
write_condition(self.condition(), mng, w)?; Condition(self.condition()).write(w)?;
write!(w, "then ")?; write!(w, "then ")?;
self.on_true().write(mng, w)?; self.on_true().write(mng, w)?;
@ -204,71 +207,71 @@ fn write_call_store(result: Range<usize>, w: &mut dyn Write) -> Result<()> {
write!(w, " = ") write!(w, " = ")
} }
impl Driver for Call { impl DriverNoContext for Call {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write_call_store(self.result(), w)?; write_call_store(self.result(), w)?;
write!(w, "FUNC_LIST[{}](", self.function())?; write!(w, "FUNC_LIST[{}](", self.function())?;
self.param_list().write(mng, w)?; self.param_list().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for CallIndirect { impl DriverNoContext for CallIndirect {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write_call_store(self.result(), w)?; write_call_store(self.result(), w)?;
write!(w, "TABLE_LIST[{}].data[", self.table())?; write!(w, "TABLE_LIST[{}].data[", self.table())?;
self.index().write(mng, w)?; self.index().write(w)?;
write!(w, "](")?; write!(w, "](")?;
self.param_list().write(mng, w)?; self.param_list().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for SetTemporary { impl DriverNoContext for SetTemporary {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "reg_{} = ", self.var())?; write!(w, "reg_{} = ", self.var())?;
self.value().write(mng, w) self.value().write(w)
} }
} }
impl Driver for SetLocal { impl DriverNoContext for SetLocal {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "loc_{} = ", self.var())?; write!(w, "loc_{} = ", self.var())?;
self.value().write(mng, w) self.value().write(w)
} }
} }
impl Driver for SetGlobal { impl DriverNoContext for SetGlobal {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "GLOBAL_LIST[{}].value = ", self.var())?; write!(w, "GLOBAL_LIST[{}].value = ", self.var())?;
self.value().write(mng, w) self.value().write(w)
} }
} }
impl Driver for StoreAt { impl DriverNoContext for StoreAt {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
write!(w, "store_{}(memory_at_0, ", self.store_type().as_name())?; write!(w, "store_{}(memory_at_0, ", self.store_type().as_name())?;
self.pointer().write(mng, w)?; self.pointer().write(w)?;
if self.offset() != 0 { if self.offset() != 0 {
write!(w, "+ {}", self.offset())?; write!(w, "+ {}", self.offset())?;
} }
write!(w, ", ")?; write!(w, ", ")?;
self.value().write(mng, w)?; self.value().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
impl Driver for MemoryGrow { impl DriverNoContext for MemoryGrow {
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write(&self, w: &mut dyn Write) -> Result<()> {
let result = self.result(); let result = self.result();
let memory = self.memory(); let memory = self.memory();
write!(w, "reg_{result} = rt.allocator.grow(memory_at_{memory}, ")?; write!(w, "reg_{result} = rt.allocator.grow(memory_at_{memory}, ")?;
self.size().write(mng, w)?; self.size().write(w)?;
write!(w, ")") write!(w, ")")
} }
} }
@ -279,13 +282,13 @@ impl Driver for Statement {
Self::Block(s) => s.write(mng, w), Self::Block(s) => s.write(mng, w),
Self::BrIf(s) => s.write(mng, w), Self::BrIf(s) => s.write(mng, w),
Self::If(s) => s.write(mng, w), Self::If(s) => s.write(mng, w),
Self::Call(s) => s.write(mng, w), Self::Call(s) => s.write(w),
Self::CallIndirect(s) => s.write(mng, w), Self::CallIndirect(s) => s.write(w),
Self::SetTemporary(s) => s.write(mng, w), Self::SetTemporary(s) => s.write(w),
Self::SetLocal(s) => s.write(mng, w), Self::SetLocal(s) => s.write(w),
Self::SetGlobal(s) => s.write(mng, w), Self::SetGlobal(s) => s.write(w),
Self::StoreAt(s) => s.write(mng, w), Self::StoreAt(s) => s.write(w),
Self::MemoryGrow(s) => s.write(mng, w), Self::MemoryGrow(s) => s.write(w),
} }
} }
} }

View File

@ -15,7 +15,7 @@ use wasmparser::{
use crate::{ use crate::{
analyzer::localize, analyzer::localize,
backend::manager::{Driver, Manager}, backend::manager::{Driver, DriverNoContext, Manager},
}; };
trait AsIEName { trait AsIEName {
@ -54,7 +54,7 @@ fn write_constant(init: &InitExpr, type_info: &TypeInfo, w: &mut dyn Write) -> R
let func = Factory::from_type_info(type_info).create_anonymous(&code); let func = Factory::from_type_info(type_info).create_anonymous(&code);
if let Some(Statement::SetTemporary(stat)) = func.code().code().last() { if let Some(Statement::SetTemporary(stat)) = func.code().code().last() {
stat.value().write(&mut Manager::default(), w) stat.value().write(w)
} else { } else {
write!(w, r#"error("Valueless constant")"#) write!(w, r#"error("Valueless constant")"#)
} }