#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum UnOp {
Not,
Neg,
Popcnt,
Clz,
Ctz,
Bswap,
BitRev,
}
impl UnOp {
pub const ALL: [UnOp; 7] = [
UnOp::Not,
UnOp::Neg,
UnOp::Popcnt,
UnOp::Clz,
UnOp::Ctz,
UnOp::Bswap,
UnOp::BitRev,
];
pub const fn name(self) -> &'static str {
match self {
UnOp::Not => "not",
UnOp::Neg => "neg",
UnOp::Popcnt => "popcnt",
UnOp::Clz => "clz",
UnOp::Ctz => "ctz",
UnOp::Bswap => "bswap",
UnOp::BitRev => "bitrev",
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum BinOp {
Add,
Sub,
Mul,
UMulHi,
SMulHi,
UDiv,
URem,
SDiv,
SRem,
And,
Or,
Xor,
Shl,
LShr,
AShr,
RotL,
RotR,
Pdep,
Pext,
}
impl BinOp {
pub const ALL: [BinOp; 19] = [
BinOp::Add,
BinOp::Sub,
BinOp::Mul,
BinOp::UMulHi,
BinOp::SMulHi,
BinOp::UDiv,
BinOp::URem,
BinOp::SDiv,
BinOp::SRem,
BinOp::And,
BinOp::Or,
BinOp::Xor,
BinOp::Shl,
BinOp::LShr,
BinOp::AShr,
BinOp::RotL,
BinOp::RotR,
BinOp::Pdep,
BinOp::Pext,
];
pub const fn name(self) -> &'static str {
match self {
BinOp::Add => "add",
BinOp::Sub => "sub",
BinOp::Mul => "mul",
BinOp::UMulHi => "umulhi",
BinOp::SMulHi => "smulhi",
BinOp::UDiv => "udiv",
BinOp::URem => "urem",
BinOp::SDiv => "sdiv",
BinOp::SRem => "srem",
BinOp::And => "and",
BinOp::Or => "or",
BinOp::Xor => "xor",
BinOp::Shl => "shl",
BinOp::LShr => "lshr",
BinOp::AShr => "ashr",
BinOp::RotL => "rotl",
BinOp::RotR => "rotr",
BinOp::Pdep => "pdep",
BinOp::Pext => "pext",
}
}
pub const fn is_commutative(self) -> bool {
matches!(
self,
BinOp::Add
| BinOp::Mul
| BinOp::UMulHi
| BinOp::SMulHi
| BinOp::And
| BinOp::Or
| BinOp::Xor
)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum CmpOp {
Eq,
Ne,
Ult,
Ule,
Slt,
Sle,
}
impl CmpOp {
pub const ALL: [CmpOp; 6] = [
CmpOp::Eq,
CmpOp::Ne,
CmpOp::Ult,
CmpOp::Ule,
CmpOp::Slt,
CmpOp::Sle,
];
pub const fn is_commutative(self) -> bool {
matches!(self, CmpOp::Eq | CmpOp::Ne)
}
pub const fn negated(self) -> CmpOpExt {
match self {
CmpOp::Eq => CmpOpExt::Ne,
CmpOp::Ne => CmpOpExt::Eq,
CmpOp::Ult => CmpOpExt::Uge,
CmpOp::Ule => CmpOpExt::Ugt,
CmpOp::Slt => CmpOpExt::Sge,
CmpOp::Sle => CmpOpExt::Sgt,
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum CmpOpExt {
Eq,
Ne,
Ult,
Ule,
Ugt,
Uge,
Slt,
Sle,
Sgt,
Sge,
}
impl CmpOpExt {
pub const ALL: [CmpOpExt; 10] = [
CmpOpExt::Eq,
CmpOpExt::Ne,
CmpOpExt::Ult,
CmpOpExt::Ule,
CmpOpExt::Ugt,
CmpOpExt::Uge,
CmpOpExt::Slt,
CmpOpExt::Sle,
CmpOpExt::Sgt,
CmpOpExt::Sge,
];
pub const fn canonical(self) -> (CmpOp, bool) {
match self {
CmpOpExt::Eq => (CmpOp::Eq, false),
CmpOpExt::Ne => (CmpOp::Ne, false),
CmpOpExt::Ult => (CmpOp::Ult, false),
CmpOpExt::Ule => (CmpOp::Ule, false),
CmpOpExt::Ugt => (CmpOp::Ult, true),
CmpOpExt::Uge => (CmpOp::Ule, true),
CmpOpExt::Slt => (CmpOp::Slt, false),
CmpOpExt::Sle => (CmpOp::Sle, false),
CmpOpExt::Sgt => (CmpOp::Slt, true),
CmpOpExt::Sge => (CmpOp::Sle, true),
}
}
pub const fn symbol(self) -> &'static str {
match self {
CmpOpExt::Eq => "==",
CmpOpExt::Ne => "!=",
CmpOpExt::Ult => "<u",
CmpOpExt::Ule => "<=u",
CmpOpExt::Ugt => ">u",
CmpOpExt::Uge => ">=u",
CmpOpExt::Slt => "<s",
CmpOpExt::Sle => "<=s",
CmpOpExt::Sgt => ">s",
CmpOpExt::Sge => ">=s",
}
}
}
impl From<CmpOp> for CmpOpExt {
fn from(op: CmpOp) -> Self {
match op {
CmpOp::Eq => CmpOpExt::Eq,
CmpOp::Ne => CmpOpExt::Ne,
CmpOp::Ult => CmpOpExt::Ult,
CmpOp::Ule => CmpOpExt::Ule,
CmpOp::Slt => CmpOpExt::Slt,
CmpOp::Sle => CmpOpExt::Sle,
}
}
}