299 lines
7.7 KiB
Rust
299 lines
7.7 KiB
Rust
//! Operator definitions.
|
|
|
|
use peepmatic_macro::PeepmaticOperator;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// An operator.
|
|
///
|
|
/// These are a subset of Cranelift IR's operators.
|
|
///
|
|
/// ## Caveats for Branching and Trapping Operators
|
|
///
|
|
/// Branching operators are not fully modeled: we do not represent their label
|
|
/// and jump arguments. It is up to the interpreter doing the instruction
|
|
/// replacement to recognize when we are replacing one branch with another, and
|
|
/// copy over the extra information.
|
|
///
|
|
/// Affected operations: `brz`, `brnz`, `trapz`, `trapnz`.
|
|
#[derive(PeepmaticOperator, Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
|
|
#[repr(u32)]
|
|
pub enum Operator {
|
|
/// `adjust_sp_down`
|
|
#[peepmatic(params(iNN), result(void))]
|
|
// NB: We convert `Operator`s into `NonZeroU32`s with unchecked casts;
|
|
// memory safety relies on `Operator` starting at `1` and no variant ever
|
|
// being zero.
|
|
AdjustSpDown = 1,
|
|
|
|
/// `adjust_sp_down_imm`
|
|
#[peepmatic(immediates(iNN), result(void))]
|
|
AdjustSpDownImm,
|
|
|
|
/// `band`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Band,
|
|
|
|
/// `band_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
BandImm,
|
|
|
|
/// `bconst`
|
|
#[peepmatic(immediates(b1), result(bNN))]
|
|
Bconst,
|
|
|
|
/// `bint`
|
|
#[peepmatic(params(bNN), result(iNN))]
|
|
Bint,
|
|
|
|
/// `bor`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Bor,
|
|
|
|
/// `bor_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
BorImm,
|
|
|
|
/// `brnz`
|
|
#[peepmatic(params(bool_or_int), result(void))]
|
|
Brnz,
|
|
|
|
/// `brz`
|
|
#[peepmatic(params(bool_or_int), result(void))]
|
|
Brz,
|
|
|
|
/// `bxor`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Bxor,
|
|
|
|
/// `bxor_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
BxorImm,
|
|
|
|
/// `iadd`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Iadd,
|
|
|
|
/// `iadd_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
IaddImm,
|
|
|
|
/// `icmp`
|
|
#[peepmatic(immediates(cc), params(iNN, iNN), result(b1))]
|
|
Icmp,
|
|
|
|
/// `icmp_imm`
|
|
#[peepmatic(immediates(cc, iNN), params(iNN), result(b1))]
|
|
IcmpImm,
|
|
|
|
/// `iconst`
|
|
#[peepmatic(immediates(iNN), result(iNN))]
|
|
Iconst,
|
|
|
|
/// `ifcmp`
|
|
#[peepmatic(params(iNN, iNN), result(cpu_flags))]
|
|
Ifcmp,
|
|
|
|
/// `ifcmp_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(cpu_flags))]
|
|
IfcmpImm,
|
|
|
|
/// `imul`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Imul,
|
|
|
|
/// `imul_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
ImulImm,
|
|
|
|
/// `ireduce`
|
|
#[peepmatic(params(iNN), result(iMM))]
|
|
Ireduce,
|
|
|
|
/// `irsub_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
IrsubImm,
|
|
|
|
/// `ishl`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Ishl,
|
|
|
|
/// `ishl_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
IshlImm,
|
|
|
|
/// `isub`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Isub,
|
|
|
|
/// `rotl`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Rotl,
|
|
|
|
/// `rotl_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
RotlImm,
|
|
|
|
/// `rotr`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Rotr,
|
|
|
|
/// `rotr_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
RotrImm,
|
|
|
|
/// `sdiv`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Sdiv,
|
|
|
|
/// `sdiv_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
SdivImm,
|
|
|
|
/// `select`
|
|
#[peepmatic(params(bool_or_int, any_t, any_t), result(any_t))]
|
|
Select,
|
|
|
|
/// `sextend`
|
|
#[peepmatic(params(iNN), result(iMM))]
|
|
Sextend,
|
|
|
|
/// `srem`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Srem,
|
|
|
|
/// `srem_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
SremImm,
|
|
|
|
/// `sshr`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Sshr,
|
|
|
|
/// `sshr_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
SshrImm,
|
|
|
|
/// `trapnz`
|
|
#[peepmatic(params(bool_or_int), result(void))]
|
|
Trapnz,
|
|
|
|
/// `trapz`
|
|
#[peepmatic(params(bool_or_int), result(void))]
|
|
Trapz,
|
|
|
|
/// `udiv`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Udiv,
|
|
|
|
/// `udiv_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
UdivImm,
|
|
|
|
/// `uextend`
|
|
#[peepmatic(params(iNN), result(iMM))]
|
|
Uextend,
|
|
|
|
/// `urem`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Urem,
|
|
|
|
/// `urem_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
UremImm,
|
|
|
|
/// `ushr`
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Ushr,
|
|
|
|
/// `ushr_imm`
|
|
#[peepmatic(immediates(iNN), params(iNN), result(iNN))]
|
|
UshrImm,
|
|
}
|
|
|
|
/// Compile-time unquote operators.
|
|
///
|
|
/// These are used in the right-hand side to perform compile-time evaluation of
|
|
/// constants matched on the left-hand side.
|
|
#[derive(PeepmaticOperator, Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
|
|
#[repr(u32)]
|
|
pub enum UnquoteOperator {
|
|
/// Compile-time `band` of two constant values.
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Band,
|
|
|
|
/// Compile-time `bor` of two constant values.
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Bor,
|
|
|
|
/// Compile-time `bxor` of two constant values.
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Bxor,
|
|
|
|
/// Compile-time `iadd` of two constant values.
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Iadd,
|
|
|
|
/// Compile-time `imul` of two constant values.
|
|
#[peepmatic(params(iNN, iNN), result(iNN))]
|
|
Imul,
|
|
|
|
/// Take the base-2 log of a power of two integer.
|
|
#[peepmatic(params(iNN), result(iNN))]
|
|
Log2,
|
|
|
|
/// Wrapping negation of an integer.
|
|
#[peepmatic(params(iNN), result(iNN))]
|
|
Neg,
|
|
}
|
|
|
|
/// A trait to represent a typing context.
|
|
///
|
|
/// This is used by the macro-generated operator methods that create the type
|
|
/// variables for their immediates, parameters, and results. This trait is
|
|
/// implemented by the concrete typing context in `peepmatic/src/verify.rs`.
|
|
#[cfg(feature = "construct")]
|
|
pub trait TypingContext<'a> {
|
|
/// A type variable.
|
|
type TypeVariable;
|
|
|
|
/// Create a condition code type.
|
|
fn cc(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create a boolean type with a polymorphic bit width.
|
|
///
|
|
/// Each use of `bNN` by the same operator refers to the same type variable.
|
|
#[allow(non_snake_case)]
|
|
fn bNN(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create an integer type with a polymorphic bit width.
|
|
///
|
|
/// Each use of `iNN` by the same operator refers to the same type variable.
|
|
#[allow(non_snake_case)]
|
|
fn iNN(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create an integer type with a polymorphic bit width.
|
|
///
|
|
/// Each use of `iMM` by the same operator refers to the same type variable.
|
|
#[allow(non_snake_case)]
|
|
fn iMM(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create the CPU flags type variable.
|
|
fn cpu_flags(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create a boolean type of size one bit.
|
|
fn b1(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create the void type, used as the result of operators that branch away,
|
|
/// or do not return anything.
|
|
fn void(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create a type variable that may be either a boolean or an integer.
|
|
fn bool_or_int(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
|
|
/// Create a type variable that can be any type T.
|
|
///
|
|
/// Each use of `any_t` by the same operator refers to the same type
|
|
/// variable.
|
|
fn any_t(&mut self, span: wast::Span) -> Self::TypeVariable;
|
|
}
|