#![allow(dead_code)]
pub use self::InstKind::*;
use crate::{ty::*, unit::UnitContext, value::*};
#[derive(Debug)]
pub struct Inst {
id: InstRef,
name: Option<String>,
kind: InstKind,
}
impl Inst {
pub fn new(name: Option<String>, kind: InstKind) -> Inst {
Inst {
id: InstRef::new(ValueId::alloc()),
name: name,
kind: kind,
}
}
pub fn as_ref(&self) -> InstRef {
self.id
}
pub fn mnemonic(&self) -> Mnemonic {
self.kind.mnemonic()
}
pub fn kind(&self) -> &InstKind {
&self.kind
}
}
impl Value for Inst {
fn id(&self) -> ValueId {
self.id.into()
}
fn ty(&self) -> Type {
self.kind.ty()
}
fn name(&self) -> Option<&str> {
self.name.as_ref().map(|x| x as &str)
}
fn is_global(&self) -> bool {
false
}
}
pub struct InstIter<'tf> {
refs: std::slice::Iter<'tf, InstRef>,
ctx: &'tf UnitContext,
}
impl<'tf> InstIter<'tf> {
pub fn new(refs: std::slice::Iter<'tf, InstRef>, ctx: &'tf UnitContext) -> InstIter<'tf> {
InstIter {
refs: refs,
ctx: ctx,
}
}
}
impl<'tf> std::iter::Iterator for InstIter<'tf> {
type Item = &'tf Inst;
fn next(&mut self) -> Option<&'tf Inst> {
let n = self.refs.next();
n.map(|r| self.ctx.inst(*r))
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum InstPosition {
Begin,
End,
Before(InstRef),
After(InstRef),
BlockBegin(BlockRef),
BlockEnd(BlockRef),
}
#[derive(Debug)]
pub enum InstKind {
UnaryInst(UnaryOp, Type, ValueRef),
BinaryInst(BinaryOp, Type, ValueRef, ValueRef),
CompareInst(CompareOp, Type, ValueRef, ValueRef),
CallInst(Type, ValueRef, Vec<ValueRef>),
InstanceInst(Type, ValueRef, Vec<ValueRef>, Vec<ValueRef>),
WaitInst(BlockRef, Option<ValueRef>, Vec<ValueRef>),
ReturnInst(ReturnKind),
BranchInst(BranchKind),
SignalInst(Type, Option<ValueRef>),
ProbeInst(Type, ValueRef),
DriveInst(ValueRef, ValueRef, Option<ValueRef>),
HaltInst,
}
impl InstKind {
pub fn ty(&self) -> Type {
match *self {
UnaryInst(_, ref ty, _) => ty.clone(),
BinaryInst(_, ref ty, _, _) => ty.clone(),
CompareInst(..) => int_ty(1),
CallInst(ref ty, _, _) => ty.as_func().1.clone(),
InstanceInst(..) | WaitInst(..) | ReturnInst(_) | BranchInst(_) => void_ty(),
SignalInst(ref ty, _) => signal_ty(ty.clone()),
ProbeInst(ref ty, _) => ty.clone(),
DriveInst(..) => void_ty(),
HaltInst => void_ty(),
}
}
pub fn mnemonic(&self) -> Mnemonic {
match *self {
UnaryInst(op, _, _) => Mnemonic::Unary(op.mnemonic()),
BinaryInst(op, _, _, _) => Mnemonic::Binary(op.mnemonic()),
CompareInst(..) => Mnemonic::Cmp,
CallInst(..) => Mnemonic::Call,
InstanceInst(..) => Mnemonic::Inst,
WaitInst(..) => Mnemonic::Wait,
ReturnInst(..) => Mnemonic::Ret,
BranchInst(..) => Mnemonic::Br,
SignalInst(..) => Mnemonic::Sig,
ProbeInst(..) => Mnemonic::Prb,
DriveInst(..) => Mnemonic::Drv,
HaltInst => Mnemonic::Halt,
}
}
pub fn is_instance(&self) -> bool {
match *self {
InstanceInst(..) => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum UnaryOp {
Not,
}
impl UnaryOp {
pub fn mnemonic(&self) -> UnaryMnemonic {
match *self {
UnaryOp::Not => UnaryMnemonic::Not,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Rem,
Shl,
Shr,
And,
Or,
Xor,
}
impl BinaryOp {
pub fn mnemonic(&self) -> BinaryMnemonic {
match *self {
BinaryOp::Add => BinaryMnemonic::Add,
BinaryOp::Sub => BinaryMnemonic::Sub,
BinaryOp::Mul => BinaryMnemonic::Mul,
BinaryOp::Div => BinaryMnemonic::Div,
BinaryOp::Mod => BinaryMnemonic::Mod,
BinaryOp::Rem => BinaryMnemonic::Rem,
BinaryOp::Shl => BinaryMnemonic::Shl,
BinaryOp::Shr => BinaryMnemonic::Shr,
BinaryOp::And => BinaryMnemonic::And,
BinaryOp::Or => BinaryMnemonic::Or,
BinaryOp::Xor => BinaryMnemonic::Xor,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CompareOp {
Eq,
Neq,
Slt,
Sgt,
Sle,
Sge,
Ult,
Ugt,
Ule,
Uge,
}
impl CompareOp {
pub fn to_str(self) -> &'static str {
match self {
CompareOp::Eq => "eq",
CompareOp::Neq => "neq",
CompareOp::Slt => "slt",
CompareOp::Sgt => "sgt",
CompareOp::Sle => "sle",
CompareOp::Sge => "sge",
CompareOp::Ult => "ult",
CompareOp::Ugt => "ugt",
CompareOp::Ule => "ule",
CompareOp::Uge => "uge",
}
}
pub fn from_str(s: &str) -> Option<CompareOp> {
Some(match s {
"eq" => CompareOp::Eq,
"neq" => CompareOp::Neq,
"slt" => CompareOp::Slt,
"sgt" => CompareOp::Sgt,
"sle" => CompareOp::Sle,
"sge" => CompareOp::Sge,
"ult" => CompareOp::Ult,
"ugt" => CompareOp::Ugt,
"ule" => CompareOp::Ule,
"uge" => CompareOp::Uge,
_ => return None,
})
}
}
#[derive(Debug, Clone)]
pub enum ReturnKind {
Void,
Value(Type, ValueRef),
}
#[derive(Debug, Clone)]
pub enum BranchKind {
Uncond(BlockRef),
Cond(ValueRef, BlockRef, BlockRef),
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Mnemonic {
Unary(UnaryMnemonic),
Binary(BinaryMnemonic),
Call,
Inst,
Cmp,
Wait,
Ret,
Br,
Phi,
Sig,
Prb,
Drv,
Halt,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum UnaryMnemonic {
Not,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum BinaryMnemonic {
Add,
Sub,
Mul,
Div,
Mod,
Rem,
Shl,
Shr,
And,
Or,
Xor,
}
impl Mnemonic {
pub fn as_str(self) -> &'static str {
match self {
Mnemonic::Unary(m) => m.as_str(),
Mnemonic::Binary(m) => m.as_str(),
Mnemonic::Call => "call",
Mnemonic::Inst => "inst",
Mnemonic::Cmp => "cmp",
Mnemonic::Wait => "wait",
Mnemonic::Ret => "ret",
Mnemonic::Br => "br",
Mnemonic::Phi => "phi",
Mnemonic::Sig => "sig",
Mnemonic::Prb => "prb",
Mnemonic::Drv => "drv",
Mnemonic::Halt => "halt",
}
}
}
impl UnaryMnemonic {
pub fn as_str(self) -> &'static str {
match self {
UnaryMnemonic::Not => "not",
}
}
}
impl BinaryMnemonic {
pub fn as_str(self) -> &'static str {
match self {
BinaryMnemonic::Add => "add",
BinaryMnemonic::Sub => "sub",
BinaryMnemonic::Mul => "mul",
BinaryMnemonic::Div => "div",
BinaryMnemonic::Mod => "mod",
BinaryMnemonic::Rem => "rem",
BinaryMnemonic::Shl => "shl",
BinaryMnemonic::Shr => "shr",
BinaryMnemonic::And => "and",
BinaryMnemonic::Or => "or",
BinaryMnemonic::Xor => "xor",
}
}
}