use super::{Dep};
use super::code::{Register, Variable, Precision, UnaryOp, BinaryOp, Width, Address, Action};
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[repr(u8)]
pub enum Op {
Guard,
Input,
Constant(i64),
Unary(Precision, UnaryOp),
Binary(Precision, BinaryOp),
Load(i32, Width),
Store(i32, Width),
Send,
Debug,
}
impl Op {
pub fn deps(self) -> &'static [Dep] {
match self {
Op::Guard => &[Dep::GUARD, Dep::VALUE],
Op::Input => &[],
Op::Constant(_) => &[],
Op::Unary(_, _) => &[Dep::VALUE],
Op::Binary(_, _) => &[Dep::VALUE, Dep::VALUE],
Op::Load(_, _) => &[Dep::GUARD, Dep::LOAD],
Op::Store(_, _) => &[Dep::GUARD, Dep::VALUE, Dep::STORE],
Op::Send => &[Dep::VALUE, Dep::SEND],
Op::Debug => &[Dep::GUARD, Dep::VALUE],
}
}
pub fn to_action(self, out: Option<Register>, ins: &[Variable]) -> Action {
match self {
Op::Guard => panic!("Cannot convert a guard to an action"),
Op::Input => panic!("Cannot convert an input to an action"),
Op::Constant(c) => {
assert_eq!(ins.len(), 0);
Action::Constant(Precision::P64, out.unwrap(), c)
},
Op::Unary(prec, op) => {
assert_eq!(ins.len(), 1);
Action::Unary(op, prec, out.unwrap(), ins[0])
},
Op::Binary(prec, op) => {
assert_eq!(ins.len(), 2);
Action::Binary(op, prec, out.unwrap(), ins[0], ins[1])
},
Op::Load(offset, width) => {
assert_eq!(ins.len(), 1);
Action::Load(out.unwrap(), Address {base: ins[0], offset, width})
},
Op::Store(offset, width) => {
assert_eq!(ins.len(), 2);
Action::Store(out.unwrap(), ins[0], Address {base: ins[1], offset, width})
},
Op::Send => {
assert_eq!(ins.len(), 2);
Action::Send(out.unwrap(), ins[0], ins[1])
},
Op::Debug => {
assert!(out.is_none());
assert_eq!(ins.len(), 1);
Action::Debug(ins[0])
},
}
}
}