diff --git a/codegen-luajit/src/analyzer/localize.rs b/codegen-luajit/src/analyzer/localize.rs index 5f1a255..ce13f44 100644 --- a/codegen-luajit/src/analyzer/localize.rs +++ b/codegen-luajit/src/analyzer/localize.rs @@ -5,6 +5,8 @@ use wasm_ast::{ visit::{Driver, Visitor}, }; +use super::operator::{bin_symbol_of, cmp_symbol_of}; + struct Visit { result: BTreeSet<(&'static str, &'static str)>, } @@ -29,7 +31,7 @@ impl Visitor for Visit { } fn visit_bin_op(&mut self, v: &BinOp) { - if v.op.as_operator().is_some() { + if bin_symbol_of(v.op).is_some() { return; } @@ -39,7 +41,7 @@ impl Visitor for Visit { } fn visit_cmp_op(&mut self, v: &CmpOp) { - if v.op.as_operator().is_some() { + if cmp_symbol_of(v.op).is_some() { return; } diff --git a/codegen-luajit/src/analyzer/mod.rs b/codegen-luajit/src/analyzer/mod.rs index 6e4ed64..4d05603 100644 --- a/codegen-luajit/src/analyzer/mod.rs +++ b/codegen-luajit/src/analyzer/mod.rs @@ -1,2 +1,3 @@ pub mod localize; pub mod memory; +pub mod operator; diff --git a/codegen-luajit/src/analyzer/operator.rs b/codegen-luajit/src/analyzer/operator.rs new file mode 100644 index 0000000..2660ac6 --- /dev/null +++ b/codegen-luajit/src/analyzer/operator.rs @@ -0,0 +1,30 @@ +use wasm_ast::node::{BinOpType, CmpOpType}; + +pub fn bin_symbol_of(op: BinOpType) -> Option<&'static str> { + let result = match op { + BinOpType::Add_I64 | BinOpType::Add_FN => "+", + BinOpType::Sub_I64 | BinOpType::Sub_FN => "-", + BinOpType::Mul_I64 | BinOpType::Mul_FN => "*", + BinOpType::DivS_I64 | BinOpType::Div_FN => "/", + BinOpType::RemS_I32 | BinOpType::RemU_I32 | BinOpType::RemS_I64 | BinOpType::RemU_I64 => { + "%" + } + _ => return None, + }; + + Some(result) +} + +pub fn cmp_symbol_of(op: CmpOpType) -> Option<&'static str> { + let result = match op { + CmpOpType::Eq_I32 | CmpOpType::Eq_I64 | CmpOpType::Eq_FN => "==", + CmpOpType::Ne_I32 | CmpOpType::Ne_I64 | CmpOpType::Ne_FN => "~=", + CmpOpType::LtS_I32 | CmpOpType::LtS_I64 | CmpOpType::Lt_FN => "<", + CmpOpType::GtS_I32 | CmpOpType::GtS_I64 | CmpOpType::Gt_FN => ">", + CmpOpType::LeS_I32 | CmpOpType::LeS_I64 | CmpOpType::Le_FN => "<=", + CmpOpType::GeS_I32 | CmpOpType::GeS_I64 | CmpOpType::Ge_FN => ">=", + _ => return None, + }; + + Some(result) +} diff --git a/codegen-luajit/src/backend/expression.rs b/codegen-luajit/src/backend/expression.rs index 6acab54..703c331 100644 --- a/codegen-luajit/src/backend/expression.rs +++ b/codegen-luajit/src/backend/expression.rs @@ -5,9 +5,11 @@ use wasm_ast::node::{ UnOp, Value, }; +use crate::analyzer::operator::bin_symbol_of; + use super::manager::{ - write_bin_call, write_cmp_op, write_condition, write_f32, write_f64, write_separated, - write_variable, Driver, Manager, + write_cmp_op, write_condition, write_f32, write_f64, write_separated, write_variable, Driver, + Manager, }; impl Driver for Recall { @@ -73,6 +75,7 @@ impl Driver for Value { } } +// TODO: Implement context dependent infix comparisons impl Driver for UnOp { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { let (a, b) = self.op.as_name(); @@ -85,14 +88,20 @@ impl Driver for UnOp { impl Driver for BinOp { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { - if let Some(op) = self.op.as_operator() { + if let Some(symbol) = bin_symbol_of(self.op) { write!(w, "(")?; self.lhs.write(mng, w)?; - write!(w, "{op} ")?; + write!(w, "{symbol} ")?; self.rhs.write(mng, w)?; write!(w, ")") } else { - write_bin_call(self.op.as_name(), &self.lhs, &self.rhs, mng, w) + let (head, tail) = self.op.as_name(); + + write!(w, "{head}_{tail}(")?; + self.lhs.write(mng, w)?; + write!(w, ", ")?; + self.rhs.write(mng, w)?; + write!(w, ")") } } } diff --git a/codegen-luajit/src/backend/manager.rs b/codegen-luajit/src/backend/manager.rs index e863d2d..562183f 100644 --- a/codegen-luajit/src/backend/manager.rs +++ b/codegen-luajit/src/backend/manager.rs @@ -5,6 +5,8 @@ use std::{ use wasm_ast::node::{CmpOp, Expression}; +use crate::analyzer::operator::cmp_symbol_of; + #[derive(Default)] pub struct Manager { label_list: Vec, @@ -85,27 +87,19 @@ pub fn write_variable(var: usize, mng: &Manager, w: &mut dyn Write) -> Result<() } } -pub fn write_bin_call( - name: (&str, &str), - lhs: &Expression, - rhs: &Expression, - mng: &mut Manager, - w: &mut dyn Write, -) -> Result<()> { - write!(w, "{}_{}(", name.0, name.1)?; - lhs.write(mng, w)?; - write!(w, ", ")?; - rhs.write(mng, w)?; - write!(w, ")") -} - pub fn write_cmp_op(cmp: &CmpOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { - if let Some(op) = cmp.op.as_operator() { + if let Some(symbol) = cmp_symbol_of(cmp.op) { cmp.lhs.write(mng, w)?; - write!(w, "{op} ")?; + write!(w, "{symbol} ")?; cmp.rhs.write(mng, w) } else { - write_bin_call(cmp.op.as_name(), &cmp.lhs, &cmp.rhs, mng, w) + let (head, tail) = cmp.op.as_name(); + + write!(w, "{head}_{tail}(")?; + cmp.lhs.write(mng, w)?; + write!(w, ", ")?; + cmp.rhs.write(mng, w)?; + write!(w, ")") } } diff --git a/codegen-luajit/src/backend/statement.rs b/codegen-luajit/src/backend/statement.rs index 27a8c60..336b09b 100644 --- a/codegen-luajit/src/backend/statement.rs +++ b/codegen-luajit/src/backend/statement.rs @@ -3,6 +3,7 @@ use std::{ ops::Range, }; +use parity_wasm::elements::ValueType; use wasm_ast::node::{ Backward, Br, BrIf, BrTable, Call, CallIndirect, Else, Forward, If, Intermediate, Memorize, Return, SetGlobal, SetLocal, Statement, StoreAt, @@ -247,14 +248,20 @@ fn write_variable_list(ir: &Intermediate, w: &mut dyn Write) -> Result<()> { for data in &ir.local_data { let range = total..total + usize::try_from(data.count()).unwrap(); - let typed = data.value_type(); + let typed = if data.value_type() == ValueType::I64 { + "0LL" + } else { + "0" + } + .as_bytes(); total = range.end; write!(w, "local ")?; write_ascending("loc", range.clone(), w)?; write!(w, " = ")?; - write_separated(range, |_, w| write!(w, "ZERO_{typed} "), w)?; + write_separated(range, |_, w| w.write_all(typed), w)?; + write!(w, " ")?; } if ir.num_stack != 0 { diff --git a/codegen-luajit/src/translator.rs b/codegen-luajit/src/translator.rs index 5580ba5..80c14ca 100644 --- a/codegen-luajit/src/translator.rs +++ b/codegen-luajit/src/translator.rs @@ -309,11 +309,6 @@ pub fn translate(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Resu write_localize_used(&func_list, w)?; - write!(w, "local ZERO_i32 = 0 ")?; - write!(w, "local ZERO_i64 = 0LL ")?; - write!(w, "local ZERO_f32 = 0.0 ")?; - write!(w, "local ZERO_f64 = 0.0 ")?; - write!(w, "local table_new = require(\"table.new\")")?; write_named_array("FUNC_LIST", wasm.functions_space(), w)?; write_named_array("TABLE_LIST", wasm.table_space(), w)?; diff --git a/codegen-luau/src/analyzer/localize.rs b/codegen-luau/src/analyzer/localize.rs index 5f1a255..ce13f44 100644 --- a/codegen-luau/src/analyzer/localize.rs +++ b/codegen-luau/src/analyzer/localize.rs @@ -5,6 +5,8 @@ use wasm_ast::{ visit::{Driver, Visitor}, }; +use super::operator::{bin_symbol_of, cmp_symbol_of}; + struct Visit { result: BTreeSet<(&'static str, &'static str)>, } @@ -29,7 +31,7 @@ impl Visitor for Visit { } fn visit_bin_op(&mut self, v: &BinOp) { - if v.op.as_operator().is_some() { + if bin_symbol_of(v.op).is_some() { return; } @@ -39,7 +41,7 @@ impl Visitor for Visit { } fn visit_cmp_op(&mut self, v: &CmpOp) { - if v.op.as_operator().is_some() { + if cmp_symbol_of(v.op).is_some() { return; } diff --git a/codegen-luau/src/analyzer/mod.rs b/codegen-luau/src/analyzer/mod.rs index 6e4ed64..4d05603 100644 --- a/codegen-luau/src/analyzer/mod.rs +++ b/codegen-luau/src/analyzer/mod.rs @@ -1,2 +1,3 @@ pub mod localize; pub mod memory; +pub mod operator; diff --git a/codegen-luau/src/analyzer/operator.rs b/codegen-luau/src/analyzer/operator.rs new file mode 100644 index 0000000..7c3eda9 --- /dev/null +++ b/codegen-luau/src/analyzer/operator.rs @@ -0,0 +1,30 @@ +use wasm_ast::node::{BinOpType, CmpOpType}; + +pub fn bin_symbol_of(op: BinOpType) -> Option<&'static str> { + let result = match op { + BinOpType::Add_I32 | BinOpType::Add_I64 | BinOpType::Add_FN => "+", + BinOpType::Sub_I32 | BinOpType::Sub_I64 | BinOpType::Sub_FN => "-", + BinOpType::Mul_I32 | BinOpType::Mul_I64 | BinOpType::Mul_FN => "*", + BinOpType::DivS_I32 | BinOpType::DivS_I64 | BinOpType::Div_FN => "/", + BinOpType::RemS_I32 | BinOpType::RemU_I32 | BinOpType::RemS_I64 | BinOpType::RemU_I64 => { + "%" + } + _ => return None, + }; + + Some(result) +} + +pub fn cmp_symbol_of(op: CmpOpType) -> Option<&'static str> { + let result = match op { + CmpOpType::Eq_I32 | CmpOpType::Eq_I64 | CmpOpType::Eq_FN => "==", + CmpOpType::Ne_I32 | CmpOpType::Ne_I64 | CmpOpType::Ne_FN => "~=", + CmpOpType::LtS_I32 | CmpOpType::LtS_I64 | CmpOpType::Lt_FN => "<", + CmpOpType::GtS_I32 | CmpOpType::GtS_I64 | CmpOpType::Gt_FN => ">", + CmpOpType::LeS_I32 | CmpOpType::LeS_I64 | CmpOpType::Le_FN => "<=", + CmpOpType::GeS_I32 | CmpOpType::GeS_I64 | CmpOpType::Ge_FN => ">=", + _ => return None, + }; + + Some(result) +} diff --git a/codegen-luau/src/backend/expression.rs b/codegen-luau/src/backend/expression.rs index 358b833..17477cd 100644 --- a/codegen-luau/src/backend/expression.rs +++ b/codegen-luau/src/backend/expression.rs @@ -5,6 +5,8 @@ use wasm_ast::node::{ UnOp, Value, }; +use crate::analyzer::operator::bin_symbol_of; + use super::manager::{write_f32, write_f64, write_separated, write_variable, Driver, Manager}; impl Driver for Recall { @@ -80,32 +82,22 @@ impl Driver for UnOp { } } -fn write_bin_op(bin_op: &BinOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { - let op = bin_op.op.as_operator().unwrap(); - - write!(w, "(")?; - bin_op.lhs.write(mng, w)?; - write!(w, "{op} ")?; - bin_op.rhs.write(mng, w)?; - write!(w, ")") -} - -fn write_bin_op_call(bin_op: &BinOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { - let (a, b) = bin_op.op.as_name(); - - write!(w, "{a}_{b}(")?; - bin_op.lhs.write(mng, w)?; - write!(w, ", ")?; - bin_op.rhs.write(mng, w)?; - write!(w, ")") -} - impl Driver for BinOp { fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { - if self.op.as_operator().is_some() { - write_bin_op(self, mng, w) + if let Some(symbol) = bin_symbol_of(self.op) { + write!(w, "(")?; + self.lhs.write(mng, w)?; + write!(w, "{symbol} ")?; + self.rhs.write(mng, w)?; + write!(w, ")") } else { - write_bin_op_call(self, mng, w) + let (head, tail) = self.op.as_name(); + + write!(w, "{head}_{tail}(")?; + self.lhs.write(mng, w)?; + write!(w, ", ")?; + self.rhs.write(mng, w)?; + write!(w, ")") } } } diff --git a/codegen-luau/src/backend/statement.rs b/codegen-luau/src/backend/statement.rs index c87f11e..8f4bd6c 100644 --- a/codegen-luau/src/backend/statement.rs +++ b/codegen-luau/src/backend/statement.rs @@ -259,14 +259,14 @@ fn write_variable_list(ir: &Intermediate, w: &mut dyn Write) -> Result<()> { for data in &ir.local_data { let range = total..total + usize::try_from(data.count()).unwrap(); - let typed = data.value_type(); total = range.end; write!(w, "local ")?; write_ascending("loc", range.clone(), w)?; write!(w, " = ")?; - write_separated(range, |_, w| write!(w, "ZERO_{typed} "), w)?; + write_separated(range, |_, w| w.write_all(b"0"), w)?; + write!(w, " ")?; } if ir.num_stack != 0 { diff --git a/codegen-luau/src/translator.rs b/codegen-luau/src/translator.rs index 68f877b..bedf0cd 100644 --- a/codegen-luau/src/translator.rs +++ b/codegen-luau/src/translator.rs @@ -308,11 +308,6 @@ pub fn translate(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Resu write_localize_used(&func_list, w)?; - write!(w, "local ZERO_i32 = 0 ")?; - write!(w, "local ZERO_i64 = 0 ")?; - write!(w, "local ZERO_f32 = 0.0 ")?; - write!(w, "local ZERO_f64 = 0.0 ")?; - write_named_array("FUNC_LIST", wasm.functions_space(), w)?; write_named_array("TABLE_LIST", wasm.table_space(), w)?; write_named_array("MEMORY_LIST", wasm.memory_space(), w)?; diff --git a/wasm-ast/src/node.rs b/wasm-ast/src/node.rs index 72b0a02..2cd3d85 100644 --- a/wasm-ast/src/node.rs +++ b/wasm-ast/src/node.rs @@ -326,20 +326,6 @@ pub enum BinOpType { } impl BinOpType { - #[must_use] - pub fn as_operator(self) -> Option<&'static str> { - let op = match self { - Self::Add_FN => "+", - Self::Sub_FN => "-", - Self::Mul_FN => "*", - Self::Div_FN => "/", - Self::RemS_I32 | Self::RemU_I32 | Self::RemS_I64 | Self::RemU_I64 => "%", - _ => return None, - }; - - Some(op) - } - #[must_use] pub fn as_name(self) -> (&'static str, &'static str) { match self { @@ -469,21 +455,6 @@ pub enum CmpOpType { } impl CmpOpType { - #[must_use] - pub fn as_operator(self) -> Option<&'static str> { - let op = match self { - Self::Eq_I32 | Self::Eq_I64 | Self::Eq_FN => "==", - Self::Ne_I32 | Self::Ne_I64 | Self::Ne_FN => "~=", - Self::LtS_I32 | Self::LtS_I64 | Self::Lt_FN => "<", - Self::GtS_I32 | Self::GtS_I64 | Self::Gt_FN => ">", - Self::LeS_I32 | Self::LeS_I64 | Self::Le_FN => "<=", - Self::GeS_I32 | Self::GeS_I64 | Self::Ge_FN => ">=", - _ => return None, - }; - - Some(op) - } - #[must_use] pub fn as_name(self) -> (&'static str, &'static str) { match self {