Factor out operator analysis and simplify output
This commit is contained in:
parent
2e5890f466
commit
7913dd507a
@ -5,6 +5,8 @@ use wasm_ast::{
|
|||||||
visit::{Driver, Visitor},
|
visit::{Driver, Visitor},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::operator::{bin_symbol_of, cmp_symbol_of};
|
||||||
|
|
||||||
struct Visit {
|
struct Visit {
|
||||||
result: BTreeSet<(&'static str, &'static str)>,
|
result: BTreeSet<(&'static str, &'static str)>,
|
||||||
}
|
}
|
||||||
@ -29,7 +31,7 @@ impl Visitor for Visit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bin_op(&mut self, v: &BinOp) {
|
fn visit_bin_op(&mut self, v: &BinOp) {
|
||||||
if v.op.as_operator().is_some() {
|
if bin_symbol_of(v.op).is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ impl Visitor for Visit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_cmp_op(&mut self, v: &CmpOp) {
|
fn visit_cmp_op(&mut self, v: &CmpOp) {
|
||||||
if v.op.as_operator().is_some() {
|
if cmp_symbol_of(v.op).is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod localize;
|
pub mod localize;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
pub mod operator;
|
||||||
|
30
codegen-luajit/src/analyzer/operator.rs
Normal file
30
codegen-luajit/src/analyzer/operator.rs
Normal file
@ -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)
|
||||||
|
}
|
@ -5,9 +5,11 @@ use wasm_ast::node::{
|
|||||||
UnOp, Value,
|
UnOp, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::analyzer::operator::bin_symbol_of;
|
||||||
|
|
||||||
use super::manager::{
|
use super::manager::{
|
||||||
write_bin_call, write_cmp_op, write_condition, write_f32, write_f64, write_separated,
|
write_cmp_op, write_condition, write_f32, write_f64, write_separated, write_variable, Driver,
|
||||||
write_variable, Driver, Manager,
|
Manager,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Driver for Recall {
|
impl Driver for Recall {
|
||||||
@ -73,6 +75,7 @@ impl Driver for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement context dependent infix comparisons
|
||||||
impl Driver for UnOp {
|
impl Driver for UnOp {
|
||||||
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
|
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
|
||||||
let (a, b) = self.op.as_name();
|
let (a, b) = self.op.as_name();
|
||||||
@ -85,14 +88,20 @@ impl Driver for UnOp {
|
|||||||
|
|
||||||
impl Driver for BinOp {
|
impl Driver for BinOp {
|
||||||
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
|
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, "(")?;
|
write!(w, "(")?;
|
||||||
self.lhs.write(mng, w)?;
|
self.lhs.write(mng, w)?;
|
||||||
write!(w, "{op} ")?;
|
write!(w, "{symbol} ")?;
|
||||||
self.rhs.write(mng, w)?;
|
self.rhs.write(mng, w)?;
|
||||||
write!(w, ")")
|
write!(w, ")")
|
||||||
} else {
|
} 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, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ use std::{
|
|||||||
|
|
||||||
use wasm_ast::node::{CmpOp, Expression};
|
use wasm_ast::node::{CmpOp, Expression};
|
||||||
|
|
||||||
|
use crate::analyzer::operator::cmp_symbol_of;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Manager {
|
pub struct Manager {
|
||||||
label_list: Vec<usize>,
|
label_list: Vec<usize>,
|
||||||
@ -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<()> {
|
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)?;
|
cmp.lhs.write(mng, w)?;
|
||||||
write!(w, "{op} ")?;
|
write!(w, "{symbol} ")?;
|
||||||
cmp.rhs.write(mng, w)
|
cmp.rhs.write(mng, w)
|
||||||
} else {
|
} 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, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ use std::{
|
|||||||
ops::Range,
|
ops::Range,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use parity_wasm::elements::ValueType;
|
||||||
use wasm_ast::node::{
|
use wasm_ast::node::{
|
||||||
Backward, Br, BrIf, BrTable, Call, CallIndirect, Else, Forward, If, Intermediate, Memorize,
|
Backward, Br, BrIf, BrTable, Call, CallIndirect, Else, Forward, If, Intermediate, Memorize,
|
||||||
Return, SetGlobal, SetLocal, Statement, StoreAt,
|
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 {
|
for data in &ir.local_data {
|
||||||
let range = total..total + usize::try_from(data.count()).unwrap();
|
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;
|
total = range.end;
|
||||||
|
|
||||||
write!(w, "local ")?;
|
write!(w, "local ")?;
|
||||||
write_ascending("loc", range.clone(), w)?;
|
write_ascending("loc", range.clone(), w)?;
|
||||||
write!(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 {
|
if ir.num_stack != 0 {
|
||||||
|
@ -309,11 +309,6 @@ pub fn translate(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Resu
|
|||||||
|
|
||||||
write_localize_used(&func_list, w)?;
|
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!(w, "local table_new = require(\"table.new\")")?;
|
||||||
write_named_array("FUNC_LIST", wasm.functions_space(), w)?;
|
write_named_array("FUNC_LIST", wasm.functions_space(), w)?;
|
||||||
write_named_array("TABLE_LIST", wasm.table_space(), w)?;
|
write_named_array("TABLE_LIST", wasm.table_space(), w)?;
|
||||||
|
@ -5,6 +5,8 @@ use wasm_ast::{
|
|||||||
visit::{Driver, Visitor},
|
visit::{Driver, Visitor},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::operator::{bin_symbol_of, cmp_symbol_of};
|
||||||
|
|
||||||
struct Visit {
|
struct Visit {
|
||||||
result: BTreeSet<(&'static str, &'static str)>,
|
result: BTreeSet<(&'static str, &'static str)>,
|
||||||
}
|
}
|
||||||
@ -29,7 +31,7 @@ impl Visitor for Visit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bin_op(&mut self, v: &BinOp) {
|
fn visit_bin_op(&mut self, v: &BinOp) {
|
||||||
if v.op.as_operator().is_some() {
|
if bin_symbol_of(v.op).is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ impl Visitor for Visit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_cmp_op(&mut self, v: &CmpOp) {
|
fn visit_cmp_op(&mut self, v: &CmpOp) {
|
||||||
if v.op.as_operator().is_some() {
|
if cmp_symbol_of(v.op).is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod localize;
|
pub mod localize;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
pub mod operator;
|
||||||
|
30
codegen-luau/src/analyzer/operator.rs
Normal file
30
codegen-luau/src/analyzer/operator.rs
Normal file
@ -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)
|
||||||
|
}
|
@ -5,6 +5,8 @@ use wasm_ast::node::{
|
|||||||
UnOp, Value,
|
UnOp, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::analyzer::operator::bin_symbol_of;
|
||||||
|
|
||||||
use super::manager::{write_f32, write_f64, write_separated, write_variable, Driver, Manager};
|
use super::manager::{write_f32, write_f64, write_separated, write_variable, Driver, Manager};
|
||||||
|
|
||||||
impl Driver for Recall {
|
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 {
|
impl Driver for BinOp {
|
||||||
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
|
fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
|
||||||
if self.op.as_operator().is_some() {
|
if let Some(symbol) = bin_symbol_of(self.op) {
|
||||||
write_bin_op(self, mng, w)
|
write!(w, "(")?;
|
||||||
|
self.lhs.write(mng, w)?;
|
||||||
|
write!(w, "{symbol} ")?;
|
||||||
|
self.rhs.write(mng, w)?;
|
||||||
|
write!(w, ")")
|
||||||
} else {
|
} 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, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,14 +259,14 @@ fn write_variable_list(ir: &Intermediate, w: &mut dyn Write) -> Result<()> {
|
|||||||
|
|
||||||
for data in &ir.local_data {
|
for data in &ir.local_data {
|
||||||
let range = total..total + usize::try_from(data.count()).unwrap();
|
let range = total..total + usize::try_from(data.count()).unwrap();
|
||||||
let typed = data.value_type();
|
|
||||||
|
|
||||||
total = range.end;
|
total = range.end;
|
||||||
|
|
||||||
write!(w, "local ")?;
|
write!(w, "local ")?;
|
||||||
write_ascending("loc", range.clone(), w)?;
|
write_ascending("loc", range.clone(), w)?;
|
||||||
write!(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 {
|
if ir.num_stack != 0 {
|
||||||
|
@ -308,11 +308,6 @@ pub fn translate(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Resu
|
|||||||
|
|
||||||
write_localize_used(&func_list, w)?;
|
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("FUNC_LIST", wasm.functions_space(), w)?;
|
||||||
write_named_array("TABLE_LIST", wasm.table_space(), w)?;
|
write_named_array("TABLE_LIST", wasm.table_space(), w)?;
|
||||||
write_named_array("MEMORY_LIST", wasm.memory_space(), w)?;
|
write_named_array("MEMORY_LIST", wasm.memory_space(), w)?;
|
||||||
|
@ -326,20 +326,6 @@ pub enum BinOpType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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]
|
#[must_use]
|
||||||
pub fn as_name(self) -> (&'static str, &'static str) {
|
pub fn as_name(self) -> (&'static str, &'static str) {
|
||||||
match self {
|
match self {
|
||||||
@ -469,21 +455,6 @@ pub enum CmpOpType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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]
|
#[must_use]
|
||||||
pub fn as_name(self) -> (&'static str, &'static str) {
|
pub fn as_name(self) -> (&'static str, &'static str) {
|
||||||
match self {
|
match self {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user