Refactored and decoupled BinOp
and CmpOp
This commit is contained in:
parent
e568baee1d
commit
d7df9fb5b4
@ -105,15 +105,11 @@ do
|
||||
end
|
||||
|
||||
do
|
||||
local eqz = {}
|
||||
local le = {}
|
||||
local lt = {}
|
||||
local ge = {}
|
||||
local gt = {}
|
||||
|
||||
function eqz.i32(lhs) return lhs == 0 end
|
||||
function eqz.i64(lhs) return lhs == 0 end
|
||||
|
||||
function ge.u32(lhs, rhs) return u32(lhs) >= u32(rhs) end
|
||||
function ge.u64(lhs, rhs) return u64(lhs) >= u64(rhs) end
|
||||
|
||||
@ -126,7 +122,6 @@ do
|
||||
function lt.u32(lhs, rhs) return u32(lhs) < u32(rhs) end
|
||||
function lt.u64(lhs, rhs) return u64(lhs) < u64(rhs) end
|
||||
|
||||
module.eqz = eqz
|
||||
module.le = le
|
||||
module.lt = lt
|
||||
module.ge = ge
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::ast::node::{AnyBinOp, AnyLoad, AnyStore, AnyUnOp, Function};
|
||||
use crate::ast::node::{AnyBinOp, AnyCmpOp, AnyLoad, AnyStore, AnyUnOp, Function};
|
||||
|
||||
use super::visit::{Driver, Visitor};
|
||||
|
||||
@ -22,6 +22,12 @@ impl Visitor for Visit {
|
||||
}
|
||||
|
||||
fn visit_any_unop(&mut self, v: &AnyUnOp) {
|
||||
let name = v.op.as_name();
|
||||
|
||||
self.result.insert(name);
|
||||
}
|
||||
|
||||
fn visit_any_binop(&mut self, v: &AnyBinOp) {
|
||||
if v.op.as_operator().is_some() {
|
||||
return;
|
||||
}
|
||||
@ -31,7 +37,7 @@ impl Visitor for Visit {
|
||||
self.result.insert(name);
|
||||
}
|
||||
|
||||
fn visit_any_binop(&mut self, v: &AnyBinOp) {
|
||||
fn visit_any_cmpop(&mut self, v: &AnyCmpOp) {
|
||||
if v.op.as_operator().is_some() {
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::ast::node::{
|
||||
AnyBinOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call, CallIndirect, Else,
|
||||
Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize, MemoryGrow, MemorySize,
|
||||
Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
AnyBinOp, AnyCmpOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call,
|
||||
CallIndirect, Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize,
|
||||
MemoryGrow, MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
};
|
||||
|
||||
pub trait Visitor {
|
||||
@ -25,6 +25,8 @@ pub trait Visitor {
|
||||
|
||||
fn visit_any_binop(&mut self, _: &AnyBinOp) {}
|
||||
|
||||
fn visit_any_cmpop(&mut self, _: &AnyCmpOp) {}
|
||||
|
||||
fn visit_expression(&mut self, _: &Expression) {}
|
||||
|
||||
fn visit_unreachable(&mut self) {}
|
||||
@ -137,19 +139,29 @@ impl<T: Visitor> Driver<T> for AnyBinOp {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Visitor> Driver<T> for AnyCmpOp {
|
||||
fn accept(&self, visitor: &mut T) {
|
||||
self.lhs.accept(visitor);
|
||||
self.rhs.accept(visitor);
|
||||
|
||||
visitor.visit_any_cmpop(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Visitor> Driver<T> for Expression {
|
||||
fn accept(&self, visitor: &mut T) {
|
||||
match self {
|
||||
Expression::Recall(v) => v.accept(visitor),
|
||||
Expression::Select(v) => v.accept(visitor),
|
||||
Expression::GetLocal(v) => v.accept(visitor),
|
||||
Expression::GetGlobal(v) => v.accept(visitor),
|
||||
Expression::AnyLoad(v) => v.accept(visitor),
|
||||
Expression::MemorySize(v) => v.accept(visitor),
|
||||
Expression::MemoryGrow(v) => v.accept(visitor),
|
||||
Expression::Value(v) => v.accept(visitor),
|
||||
Expression::AnyUnOp(v) => v.accept(visitor),
|
||||
Expression::AnyBinOp(v) => v.accept(visitor),
|
||||
Self::Recall(v) => v.accept(visitor),
|
||||
Self::Select(v) => v.accept(visitor),
|
||||
Self::GetLocal(v) => v.accept(visitor),
|
||||
Self::GetGlobal(v) => v.accept(visitor),
|
||||
Self::AnyLoad(v) => v.accept(visitor),
|
||||
Self::MemorySize(v) => v.accept(visitor),
|
||||
Self::MemoryGrow(v) => v.accept(visitor),
|
||||
Self::Value(v) => v.accept(visitor),
|
||||
Self::AnyUnOp(v) => v.accept(visitor),
|
||||
Self::AnyBinOp(v) => v.accept(visitor),
|
||||
Self::AnyCmpOp(v) => v.accept(visitor),
|
||||
}
|
||||
|
||||
visitor.visit_expression(self);
|
||||
@ -292,20 +304,20 @@ impl<T: Visitor> Driver<T> for AnyStore {
|
||||
impl<T: Visitor> Driver<T> for Statement {
|
||||
fn accept(&self, visitor: &mut T) {
|
||||
match self {
|
||||
Statement::Unreachable => visitor.visit_unreachable(),
|
||||
Statement::Memorize(v) => v.accept(visitor),
|
||||
Statement::Forward(v) => v.accept(visitor),
|
||||
Statement::Backward(v) => v.accept(visitor),
|
||||
Statement::If(v) => v.accept(visitor),
|
||||
Statement::Br(v) => v.accept(visitor),
|
||||
Statement::BrIf(v) => v.accept(visitor),
|
||||
Statement::BrTable(v) => v.accept(visitor),
|
||||
Statement::Return(v) => v.accept(visitor),
|
||||
Statement::Call(v) => v.accept(visitor),
|
||||
Statement::CallIndirect(v) => v.accept(visitor),
|
||||
Statement::SetLocal(v) => v.accept(visitor),
|
||||
Statement::SetGlobal(v) => v.accept(visitor),
|
||||
Statement::AnyStore(v) => v.accept(visitor),
|
||||
Self::Unreachable => visitor.visit_unreachable(),
|
||||
Self::Memorize(v) => v.accept(visitor),
|
||||
Self::Forward(v) => v.accept(visitor),
|
||||
Self::Backward(v) => v.accept(visitor),
|
||||
Self::If(v) => v.accept(visitor),
|
||||
Self::Br(v) => v.accept(visitor),
|
||||
Self::BrIf(v) => v.accept(visitor),
|
||||
Self::BrTable(v) => v.accept(visitor),
|
||||
Self::Return(v) => v.accept(visitor),
|
||||
Self::Call(v) => v.accept(visitor),
|
||||
Self::CallIndirect(v) => v.accept(visitor),
|
||||
Self::SetLocal(v) => v.accept(visitor),
|
||||
Self::SetGlobal(v) => v.accept(visitor),
|
||||
Self::AnyStore(v) => v.accept(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,11 @@ use parity_wasm::elements::{
|
||||
|
||||
use super::{
|
||||
node::{
|
||||
AnyBinOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call, CallIndirect,
|
||||
Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize, MemoryGrow,
|
||||
MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
AnyBinOp, AnyCmpOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call,
|
||||
CallIndirect, Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize,
|
||||
MemoryGrow, MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
},
|
||||
tag::{BinOp, Load, Store, UnOp},
|
||||
tag::{BinOp, CmpOp, Load, Store, UnOp},
|
||||
};
|
||||
|
||||
struct Arity {
|
||||
@ -310,6 +310,52 @@ impl<'a> Builder<'a> {
|
||||
.push(Expression::AnyBinOp(AnyBinOp { op, lhs, rhs }));
|
||||
}
|
||||
|
||||
fn push_cmp_op(&mut self, op: CmpOp) {
|
||||
let rhs = Box::new(self.stack.pop().unwrap());
|
||||
let lhs = Box::new(self.stack.pop().unwrap());
|
||||
|
||||
self.stack
|
||||
.push(Expression::AnyCmpOp(AnyCmpOp { op, lhs, rhs }));
|
||||
}
|
||||
|
||||
// Since Eqz is the only unary comparison it's cleaner to
|
||||
// generate a simple CmpOp
|
||||
fn from_equal_zero(&mut self, inst: &Instruction) -> bool {
|
||||
match inst {
|
||||
Instruction::I32Eqz => {
|
||||
self.push_constant(Value::I32(0));
|
||||
self.push_cmp_op(CmpOp::Eq_I32);
|
||||
|
||||
true
|
||||
}
|
||||
Instruction::I64Eqz => {
|
||||
self.push_constant(Value::I64(0));
|
||||
self.push_cmp_op(CmpOp::Eq_I64);
|
||||
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_operation(&mut self, inst: &Instruction) -> bool {
|
||||
if let Ok(op) = UnOp::try_from(inst) {
|
||||
self.push_un_op(op);
|
||||
|
||||
true
|
||||
} else if let Ok(op) = BinOp::try_from(inst) {
|
||||
self.push_bin_op(op);
|
||||
|
||||
true
|
||||
} else if let Ok(op) = CmpOp::try_from(inst) {
|
||||
self.push_cmp_op(op);
|
||||
|
||||
true
|
||||
} else {
|
||||
self.from_equal_zero(inst)
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_unreachable(list: &mut &[Instruction]) {
|
||||
use Instruction as Inst;
|
||||
|
||||
@ -353,13 +399,7 @@ impl<'a> Builder<'a> {
|
||||
|
||||
*list = &list[1..];
|
||||
|
||||
if let Ok(op) = UnOp::try_from(inst) {
|
||||
self.push_un_op(op);
|
||||
|
||||
continue;
|
||||
} else if let Ok(op) = BinOp::try_from(inst) {
|
||||
self.push_bin_op(op);
|
||||
|
||||
if self.from_operation(inst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use std::ops::Range;
|
||||
|
||||
use parity_wasm::elements::BrTableData;
|
||||
|
||||
use super::tag::{BinOp, Load, Store, UnOp};
|
||||
use super::tag::{BinOp, CmpOp, Load, Store, UnOp};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Recall {
|
||||
@ -57,6 +57,12 @@ pub struct AnyBinOp {
|
||||
pub rhs: Box<Expression>,
|
||||
}
|
||||
|
||||
pub struct AnyCmpOp {
|
||||
pub op: CmpOp,
|
||||
pub lhs: Box<Expression>,
|
||||
pub rhs: Box<Expression>,
|
||||
}
|
||||
|
||||
pub enum Expression {
|
||||
Recall(Recall),
|
||||
Select(Select),
|
||||
@ -68,6 +74,7 @@ pub enum Expression {
|
||||
Value(Value),
|
||||
AnyUnOp(AnyUnOp),
|
||||
AnyBinOp(AnyBinOp),
|
||||
AnyCmpOp(AnyCmpOp),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
|
@ -128,8 +128,6 @@ impl TryFrom<&Instruction> for Store {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum UnOp {
|
||||
Eqz_I32,
|
||||
Eqz_I64,
|
||||
Clz_I32,
|
||||
Ctz_I32,
|
||||
Popcnt_I32,
|
||||
@ -175,23 +173,8 @@ pub enum UnOp {
|
||||
}
|
||||
|
||||
impl UnOp {
|
||||
pub fn is_compare(self) -> bool {
|
||||
matches!(self, Self::Eqz_I32 | Self::Eqz_I64)
|
||||
}
|
||||
|
||||
pub fn as_operator(self) -> Option<&'static str> {
|
||||
let op = match self {
|
||||
Self::Neg_FN => "-",
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(op)
|
||||
}
|
||||
|
||||
pub fn as_name(self) -> (&'static str, &'static str) {
|
||||
match self {
|
||||
Self::Eqz_I32 => ("eqz", "i32"),
|
||||
Self::Eqz_I64 => ("eqz", "i64"),
|
||||
Self::Clz_I32 => ("clz", "i32"),
|
||||
Self::Ctz_I32 => ("ctz", "i32"),
|
||||
Self::Popcnt_I32 => ("popcnt", "i32"),
|
||||
@ -252,8 +235,6 @@ impl TryFrom<&Instruction> for UnOp {
|
||||
SignExtInstruction::I64Extend16S => Self::Extend_I64_I16,
|
||||
SignExtInstruction::I64Extend32S => Self::Extend_I64_I32,
|
||||
},
|
||||
Inst::I32Eqz => Self::Eqz_I32,
|
||||
Inst::I64Eqz => Self::Eqz_I64,
|
||||
Inst::I32Clz => Self::Clz_I32,
|
||||
Inst::I32Ctz => Self::Ctz_I32,
|
||||
Inst::I32Popcnt => Self::Popcnt_I32,
|
||||
@ -302,26 +283,6 @@ impl TryFrom<&Instruction> for UnOp {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum BinOp {
|
||||
Eq_I32,
|
||||
Ne_I32,
|
||||
LtS_I32,
|
||||
LtU_I32,
|
||||
GtS_I32,
|
||||
GtU_I32,
|
||||
LeS_I32,
|
||||
LeU_I32,
|
||||
GeS_I32,
|
||||
GeU_I32,
|
||||
Eq_I64,
|
||||
Ne_I64,
|
||||
LtS_I64,
|
||||
LtU_I64,
|
||||
GtS_I64,
|
||||
GtU_I64,
|
||||
LeS_I64,
|
||||
LeU_I64,
|
||||
GeS_I64,
|
||||
GeU_I64,
|
||||
Add_I32,
|
||||
Sub_I32,
|
||||
Mul_I32,
|
||||
@ -352,12 +313,6 @@ pub enum BinOp {
|
||||
ShrU_I64,
|
||||
Rotl_I64,
|
||||
Rotr_I64,
|
||||
Eq_FN,
|
||||
Ne_FN,
|
||||
Lt_FN,
|
||||
Gt_FN,
|
||||
Le_FN,
|
||||
Ge_FN,
|
||||
Add_FN,
|
||||
Sub_FN,
|
||||
Mul_FN,
|
||||
@ -368,26 +323,6 @@ pub enum BinOp {
|
||||
}
|
||||
|
||||
impl BinOp {
|
||||
pub fn is_compare(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Eq_I32
|
||||
| Self::Ne_I32 | Self::LtS_I32
|
||||
| Self::LtU_I32 | Self::GtS_I32
|
||||
| Self::GtU_I32 | Self::LeS_I32
|
||||
| Self::LeU_I32 | Self::GeS_I32
|
||||
| Self::GeU_I32 | Self::Eq_I64
|
||||
| Self::Ne_I64 | Self::LtS_I64
|
||||
| Self::LtU_I64 | Self::GtS_I64
|
||||
| Self::GtU_I64 | Self::LeS_I64
|
||||
| Self::LeU_I64 | Self::GeS_I64
|
||||
| Self::GeU_I64 | Self::Eq_FN
|
||||
| Self::Ne_FN | Self::Lt_FN
|
||||
| Self::Gt_FN | Self::Le_FN
|
||||
| Self::Ge_FN
|
||||
)
|
||||
}
|
||||
|
||||
pub fn as_operator(self) -> Option<&'static str> {
|
||||
let op = match self {
|
||||
Self::Add_FN => "+",
|
||||
@ -395,6 +330,142 @@ impl BinOp {
|
||||
Self::Mul_FN => "*",
|
||||
Self::Div_FN => "/",
|
||||
Self::RemS_I32 | Self::RemU_I32 | Self::RemS_I64 | Self::RemU_I64 => "%",
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(op)
|
||||
}
|
||||
|
||||
pub fn as_name(self) -> (&'static str, &'static str) {
|
||||
match self {
|
||||
Self::Add_I32 => ("add", "i32"),
|
||||
Self::Sub_I32 => ("sub", "i32"),
|
||||
Self::Mul_I32 => ("mul", "i32"),
|
||||
Self::DivS_I32 => ("div", "i32"),
|
||||
Self::DivU_I32 => ("div", "u32"),
|
||||
Self::RemS_I32 => ("rem", "i32"),
|
||||
Self::RemU_I32 => ("rem", "u32"),
|
||||
Self::And_I32 => ("band", "i32"),
|
||||
Self::Or_I32 => ("bor", "i32"),
|
||||
Self::Xor_I32 => ("bxor", "i32"),
|
||||
Self::Shl_I32 => ("shl", "i32"),
|
||||
Self::ShrS_I32 => ("shr", "i32"),
|
||||
Self::ShrU_I32 => ("shr", "u32"),
|
||||
Self::Rotl_I32 => ("rotl", "i32"),
|
||||
Self::Rotr_I32 => ("rotr", "i32"),
|
||||
Self::Add_I64 => ("add", "i64"),
|
||||
Self::Sub_I64 => ("sub", "i64"),
|
||||
Self::Mul_I64 => ("mul", "i64"),
|
||||
Self::DivS_I64 => ("div", "i64"),
|
||||
Self::DivU_I64 => ("div", "u64"),
|
||||
Self::RemS_I64 => ("rem", "i64"),
|
||||
Self::RemU_I64 => ("rem", "u64"),
|
||||
Self::And_I64 => ("band", "i64"),
|
||||
Self::Or_I64 => ("bor", "i64"),
|
||||
Self::Xor_I64 => ("bxor", "i64"),
|
||||
Self::Shl_I64 => ("shl", "i64"),
|
||||
Self::ShrS_I64 => ("shr", "i64"),
|
||||
Self::ShrU_I64 => ("shr", "u64"),
|
||||
Self::Rotl_I64 => ("rotl", "i64"),
|
||||
Self::Rotr_I64 => ("rotr", "i64"),
|
||||
Self::Add_FN => ("add", "num"),
|
||||
Self::Sub_FN => ("sub", "num"),
|
||||
Self::Mul_FN => ("mul", "num"),
|
||||
Self::Div_FN => ("div", "num"),
|
||||
Self::Min_FN => ("math", "min"),
|
||||
Self::Max_FN => ("math", "max"),
|
||||
Self::Copysign_FN => ("copysign", "num"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Instruction> for BinOp {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(inst: &Instruction) -> Result<Self, Self::Error> {
|
||||
use Instruction as Inst;
|
||||
|
||||
let result = match inst {
|
||||
Inst::I32Add => Self::Add_I32,
|
||||
Inst::I32Sub => Self::Sub_I32,
|
||||
Inst::I32Mul => Self::Mul_I32,
|
||||
Inst::I32DivS => Self::DivS_I32,
|
||||
Inst::I32DivU => Self::DivU_I32,
|
||||
Inst::I32RemS => Self::RemS_I32,
|
||||
Inst::I32RemU => Self::RemU_I32,
|
||||
Inst::I32And => Self::And_I32,
|
||||
Inst::I32Or => Self::Or_I32,
|
||||
Inst::I32Xor => Self::Xor_I32,
|
||||
Inst::I32Shl => Self::Shl_I32,
|
||||
Inst::I32ShrS => Self::ShrS_I32,
|
||||
Inst::I32ShrU => Self::ShrU_I32,
|
||||
Inst::I32Rotl => Self::Rotl_I32,
|
||||
Inst::I32Rotr => Self::Rotr_I32,
|
||||
Inst::I64Add => Self::Add_I64,
|
||||
Inst::I64Sub => Self::Sub_I64,
|
||||
Inst::I64Mul => Self::Mul_I64,
|
||||
Inst::I64DivS => Self::DivS_I64,
|
||||
Inst::I64DivU => Self::DivU_I64,
|
||||
Inst::I64RemS => Self::RemS_I64,
|
||||
Inst::I64RemU => Self::RemU_I64,
|
||||
Inst::I64And => Self::And_I64,
|
||||
Inst::I64Or => Self::Or_I64,
|
||||
Inst::I64Xor => Self::Xor_I64,
|
||||
Inst::I64Shl => Self::Shl_I64,
|
||||
Inst::I64ShrS => Self::ShrS_I64,
|
||||
Inst::I64ShrU => Self::ShrU_I64,
|
||||
Inst::I64Rotl => Self::Rotl_I64,
|
||||
Inst::I64Rotr => Self::Rotr_I64,
|
||||
Inst::F32Add | Inst::F64Add => Self::Add_FN,
|
||||
Inst::F32Sub | Inst::F64Sub => Self::Sub_FN,
|
||||
Inst::F32Mul | Inst::F64Mul => Self::Mul_FN,
|
||||
Inst::F32Div | Inst::F64Div => Self::Div_FN,
|
||||
Inst::F32Min | Inst::F64Min => Self::Min_FN,
|
||||
Inst::F32Max | Inst::F64Max => Self::Max_FN,
|
||||
Inst::F32Copysign | Inst::F64Copysign => Self::Copysign_FN,
|
||||
_ => {
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum CmpOp {
|
||||
Eq_I32,
|
||||
Ne_I32,
|
||||
LtS_I32,
|
||||
LtU_I32,
|
||||
GtS_I32,
|
||||
GtU_I32,
|
||||
LeS_I32,
|
||||
LeU_I32,
|
||||
GeS_I32,
|
||||
GeU_I32,
|
||||
Eq_I64,
|
||||
Ne_I64,
|
||||
LtS_I64,
|
||||
LtU_I64,
|
||||
GtS_I64,
|
||||
GtU_I64,
|
||||
LeS_I64,
|
||||
LeU_I64,
|
||||
GeS_I64,
|
||||
GeU_I64,
|
||||
Eq_FN,
|
||||
Ne_FN,
|
||||
Lt_FN,
|
||||
Gt_FN,
|
||||
Le_FN,
|
||||
Ge_FN,
|
||||
}
|
||||
|
||||
impl CmpOp {
|
||||
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 => "<",
|
||||
@ -429,54 +500,17 @@ impl BinOp {
|
||||
Self::LeU_I64 => ("le", "u64"),
|
||||
Self::GeS_I64 => ("ge", "i64"),
|
||||
Self::GeU_I64 => ("ge", "u64"),
|
||||
Self::Add_I32 => ("add", "i32"),
|
||||
Self::Sub_I32 => ("sub", "i32"),
|
||||
Self::Mul_I32 => ("mul", "i32"),
|
||||
Self::DivS_I32 => ("div", "i32"),
|
||||
Self::DivU_I32 => ("div", "u32"),
|
||||
Self::RemS_I32 => ("rem", "i32"),
|
||||
Self::RemU_I32 => ("rem", "u32"),
|
||||
Self::And_I32 => ("band", "i32"),
|
||||
Self::Or_I32 => ("bor", "i32"),
|
||||
Self::Xor_I32 => ("bxor", "i32"),
|
||||
Self::Shl_I32 => ("shl", "i32"),
|
||||
Self::ShrS_I32 => ("shr", "i32"),
|
||||
Self::ShrU_I32 => ("shr", "u32"),
|
||||
Self::Rotl_I32 => ("rotl", "i32"),
|
||||
Self::Rotr_I32 => ("rotr", "i32"),
|
||||
Self::Add_I64 => ("add", "i64"),
|
||||
Self::Sub_I64 => ("sub", "i64"),
|
||||
Self::Mul_I64 => ("mul", "i64"),
|
||||
Self::DivS_I64 => ("div", "i64"),
|
||||
Self::DivU_I64 => ("div", "u64"),
|
||||
Self::RemS_I64 => ("rem", "i64"),
|
||||
Self::RemU_I64 => ("rem", "u64"),
|
||||
Self::And_I64 => ("band", "i64"),
|
||||
Self::Or_I64 => ("bor", "i64"),
|
||||
Self::Xor_I64 => ("bxor", "i64"),
|
||||
Self::Shl_I64 => ("shl", "i64"),
|
||||
Self::ShrS_I64 => ("shr", "i64"),
|
||||
Self::ShrU_I64 => ("shr", "u64"),
|
||||
Self::Rotl_I64 => ("rotl", "i64"),
|
||||
Self::Rotr_I64 => ("rotr", "i64"),
|
||||
Self::Eq_FN => ("eq", "num"),
|
||||
Self::Ne_FN => ("ne", "num"),
|
||||
Self::Lt_FN => ("lt", "num"),
|
||||
Self::Gt_FN => ("gt", "num"),
|
||||
Self::Le_FN => ("le", "num"),
|
||||
Self::Ge_FN => ("ge", "num"),
|
||||
Self::Add_FN => ("add", "num"),
|
||||
Self::Sub_FN => ("sub", "num"),
|
||||
Self::Mul_FN => ("mul", "num"),
|
||||
Self::Div_FN => ("div", "num"),
|
||||
Self::Min_FN => ("math", "min"),
|
||||
Self::Max_FN => ("math", "max"),
|
||||
Self::Copysign_FN => ("copysign", "num"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Instruction> for BinOp {
|
||||
impl TryFrom<&Instruction> for CmpOp {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(inst: &Instruction) -> Result<Self, Self::Error> {
|
||||
@ -503,49 +537,12 @@ impl TryFrom<&Instruction> for BinOp {
|
||||
Inst::I64LeU => Self::LeU_I64,
|
||||
Inst::I64GeS => Self::GeS_I64,
|
||||
Inst::I64GeU => Self::GeU_I64,
|
||||
Inst::I32Add => Self::Add_I32,
|
||||
Inst::I32Sub => Self::Sub_I32,
|
||||
Inst::I32Mul => Self::Mul_I32,
|
||||
Inst::I32DivS => Self::DivS_I32,
|
||||
Inst::I32DivU => Self::DivU_I32,
|
||||
Inst::I32RemS => Self::RemS_I32,
|
||||
Inst::I32RemU => Self::RemU_I32,
|
||||
Inst::I32And => Self::And_I32,
|
||||
Inst::I32Or => Self::Or_I32,
|
||||
Inst::I32Xor => Self::Xor_I32,
|
||||
Inst::I32Shl => Self::Shl_I32,
|
||||
Inst::I32ShrS => Self::ShrS_I32,
|
||||
Inst::I32ShrU => Self::ShrU_I32,
|
||||
Inst::I32Rotl => Self::Rotl_I32,
|
||||
Inst::I32Rotr => Self::Rotr_I32,
|
||||
Inst::I64Add => Self::Add_I64,
|
||||
Inst::I64Sub => Self::Sub_I64,
|
||||
Inst::I64Mul => Self::Mul_I64,
|
||||
Inst::I64DivS => Self::DivS_I64,
|
||||
Inst::I64DivU => Self::DivU_I64,
|
||||
Inst::I64RemS => Self::RemS_I64,
|
||||
Inst::I64RemU => Self::RemU_I64,
|
||||
Inst::I64And => Self::And_I64,
|
||||
Inst::I64Or => Self::Or_I64,
|
||||
Inst::I64Xor => Self::Xor_I64,
|
||||
Inst::I64Shl => Self::Shl_I64,
|
||||
Inst::I64ShrS => Self::ShrS_I64,
|
||||
Inst::I64ShrU => Self::ShrU_I64,
|
||||
Inst::I64Rotl => Self::Rotl_I64,
|
||||
Inst::I64Rotr => Self::Rotr_I64,
|
||||
Inst::F32Eq | Inst::F64Eq => Self::Eq_FN,
|
||||
Inst::F32Ne | Inst::F64Ne => Self::Ne_FN,
|
||||
Inst::F32Lt | Inst::F64Lt => Self::Lt_FN,
|
||||
Inst::F32Gt | Inst::F64Gt => Self::Gt_FN,
|
||||
Inst::F32Le | Inst::F64Le => Self::Le_FN,
|
||||
Inst::F32Ge | Inst::F64Ge => Self::Ge_FN,
|
||||
Inst::F32Add | Inst::F64Add => Self::Add_FN,
|
||||
Inst::F32Sub | Inst::F64Sub => Self::Sub_FN,
|
||||
Inst::F32Mul | Inst::F64Mul => Self::Mul_FN,
|
||||
Inst::F32Div | Inst::F64Div => Self::Div_FN,
|
||||
Inst::F32Min | Inst::F64Min => Self::Min_FN,
|
||||
Inst::F32Max | Inst::F64Max => Self::Max_FN,
|
||||
Inst::F32Copysign | Inst::F64Copysign => Self::Copysign_FN,
|
||||
_ => {
|
||||
return Err(());
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ use crate::{
|
||||
ast::{
|
||||
builder::{Arities, Builder},
|
||||
node::{
|
||||
AnyBinOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call, CallIndirect,
|
||||
Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize, MemoryGrow,
|
||||
MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
AnyBinOp, AnyCmpOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call,
|
||||
CallIndirect, Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize,
|
||||
MemoryGrow, MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -165,78 +165,71 @@ impl Driver for Value {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_un_op(un_op: &AnyUnOp, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
if let Some(op) = un_op.op.as_operator() {
|
||||
write!(w, "{} ", op)?;
|
||||
un_op.rhs.visit(v, w)
|
||||
} else {
|
||||
let (a, b) = un_op.op.as_name();
|
||||
|
||||
write!(w, "{}_{}(", a, b)?;
|
||||
un_op.rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for AnyUnOp {
|
||||
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
if self.op.is_compare() {
|
||||
write!(w, "(")?;
|
||||
}
|
||||
|
||||
write_un_op(self, v, w)?;
|
||||
|
||||
if self.op.is_compare() {
|
||||
write!(w, "and 1 or 0)")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_bin_op(bin_op: &AnyBinOp, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
if let Some(op) = bin_op.op.as_operator() {
|
||||
bin_op.lhs.visit(v, w)?;
|
||||
write!(w, "{} ", op)?;
|
||||
bin_op.rhs.visit(v, w)
|
||||
} else {
|
||||
let (a, b) = bin_op.op.as_name();
|
||||
let (a, b) = self.op.as_name();
|
||||
|
||||
write!(w, "{}_{}(", a, b)?;
|
||||
bin_op.lhs.visit(v, w)?;
|
||||
write!(w, ", ")?;
|
||||
bin_op.rhs.visit(v, w)?;
|
||||
self.rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
}
|
||||
}
|
||||
|
||||
fn write_bin_call(
|
||||
op: (&str, &str),
|
||||
lhs: &Expression,
|
||||
rhs: &Expression,
|
||||
v: &mut Visitor,
|
||||
w: Writer,
|
||||
) -> Result<()> {
|
||||
write!(w, "{}_{}(", op.0, op.1)?;
|
||||
lhs.visit(v, w)?;
|
||||
write!(w, ", ")?;
|
||||
rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
}
|
||||
|
||||
impl Driver for AnyBinOp {
|
||||
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
if self.op.is_compare() {
|
||||
if let Some(op) = self.op.as_operator() {
|
||||
write!(w, "(")?;
|
||||
self.lhs.visit(v, w)?;
|
||||
write!(w, "{} ", op)?;
|
||||
self.rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
} else {
|
||||
write_bin_call(self.op.as_name(), &self.lhs, &self.rhs, v, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_bin_op(self, v, w)?;
|
||||
|
||||
if self.op.is_compare() {
|
||||
write!(w, "and 1 or 0)")?;
|
||||
fn write_any_cmp(cmp: &AnyCmpOp, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
if let Some(op) = cmp.op.as_operator() {
|
||||
cmp.lhs.visit(v, w)?;
|
||||
write!(w, "{} ", op)?;
|
||||
cmp.rhs.visit(v, w)
|
||||
} else {
|
||||
write_bin_call(cmp.op.as_name(), &cmp.lhs, &cmp.rhs, v, w)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
impl Driver for AnyCmpOp {
|
||||
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
write!(w, "(")?;
|
||||
write_any_cmp(self, v, w)?;
|
||||
write!(w, "and 1 or 0)")
|
||||
}
|
||||
}
|
||||
|
||||
// Removes the boolean to integer conversion
|
||||
fn write_as_condition(data: &Expression, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
match data {
|
||||
Expression::AnyUnOp(o) if o.op.is_compare() => write_un_op(o, v, w),
|
||||
Expression::AnyBinOp(o) if o.op.is_compare() => write_bin_op(o, v, w),
|
||||
_ => {
|
||||
if let Expression::AnyCmpOp(o) = data {
|
||||
write_any_cmp(o, v, w)
|
||||
} else {
|
||||
data.visit(v, w)?;
|
||||
write!(w, "~= 0 ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_expr_list(list: &[Expression], v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
list.iter().enumerate().try_for_each(|(i, e)| {
|
||||
@ -261,6 +254,7 @@ impl Driver for Expression {
|
||||
Self::Value(e) => e.visit(v, w),
|
||||
Self::AnyUnOp(e) => e.visit(v, w),
|
||||
Self::AnyBinOp(e) => e.visit(v, w),
|
||||
Self::AnyCmpOp(e) => e.visit(v, w),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ use crate::{
|
||||
ast::{
|
||||
builder::{Arities, Builder},
|
||||
node::{
|
||||
AnyBinOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call, CallIndirect,
|
||||
Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize, MemoryGrow,
|
||||
MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
AnyBinOp, AnyCmpOp, AnyLoad, AnyStore, AnyUnOp, Backward, Br, BrIf, BrTable, Call,
|
||||
CallIndirect, Else, Expression, Forward, Function, GetGlobal, GetLocal, If, Memorize,
|
||||
MemoryGrow, MemorySize, Recall, Return, Select, SetGlobal, SetLocal, Statement, Value,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -154,22 +154,13 @@ impl Driver for Value {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_un_op_call(un_op: &AnyUnOp, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
let (a, b) = un_op.op.as_name();
|
||||
|
||||
write!(w, "{}_{}(", a, b)?;
|
||||
un_op.rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
}
|
||||
|
||||
impl Driver for AnyUnOp {
|
||||
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
if let Some(op) = self.op.as_operator() {
|
||||
write!(w, "{}", op)?;
|
||||
self.rhs.visit(v, w)
|
||||
} else {
|
||||
write_un_op_call(self, v, w)
|
||||
}
|
||||
let (a, b) = self.op.as_name();
|
||||
|
||||
write!(w, "{}_{}(", a, b)?;
|
||||
self.rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,6 +194,18 @@ impl Driver for AnyBinOp {
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for AnyCmpOp {
|
||||
fn visit(&self, v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
let (a, b) = self.op.as_name();
|
||||
|
||||
write!(w, "{}_{}(", a, b)?;
|
||||
self.lhs.visit(v, w)?;
|
||||
write!(w, ", ")?;
|
||||
self.rhs.visit(v, w)?;
|
||||
write!(w, ")")
|
||||
}
|
||||
}
|
||||
|
||||
fn write_expr_list(list: &[Expression], v: &mut Visitor, w: Writer) -> Result<()> {
|
||||
list.iter().enumerate().try_for_each(|(i, e)| {
|
||||
if i != 0 {
|
||||
@ -226,6 +229,7 @@ impl Driver for Expression {
|
||||
Self::Value(e) => e.visit(v, w),
|
||||
Self::AnyUnOp(e) => e.visit(v, w),
|
||||
Self::AnyBinOp(e) => e.visit(v, w),
|
||||
Self::AnyCmpOp(e) => e.visit(v, w),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user