peepmatic_runtime/
part.rs

1//! Parts of instructions.
2
3use crate::cc::ConditionCode;
4use crate::r#type::BitWidth;
5use std::fmt::Debug;
6
7/// A constant value.
8///
9/// Whether an integer is interpreted as signed or unsigned depends on the
10/// operations applied to it.
11#[derive(Copy, Clone, Debug, PartialEq, Eq)]
12pub enum Constant {
13    /// A boolean of the given width.
14    Bool(bool, BitWidth),
15
16    /// An integer constant of the given width,
17    Int(u64, BitWidth),
18}
19
20/// A part of an instruction, or a whole instruction itself.
21///
22/// These are the different values that can be matched in an optimization's
23/// left-hand side and then built up in its right-hand side.
24#[derive(Copy, Clone, Debug, PartialEq, Eq)]
25pub enum Part<I>
26where
27    I: Copy + Debug + Eq,
28{
29    /// An instruction (or result of an instruction).
30    Instruction(I),
31
32    /// A constant value.
33    Constant(Constant),
34
35    /// A condition code.
36    ConditionCode(ConditionCode),
37}
38
39impl<I> From<Constant> for Part<I>
40where
41    I: Copy + Debug + Eq,
42{
43    #[inline]
44    fn from(c: Constant) -> Part<I> {
45        Part::Constant(c)
46    }
47}
48
49impl<I> From<ConditionCode> for Part<I>
50where
51    I: Copy + Debug + Eq,
52{
53    #[inline]
54    fn from(c: ConditionCode) -> Part<I> {
55        Part::ConditionCode(c)
56    }
57}
58
59macro_rules! accessors {
60    ( $( $variant:ident , $result:ty , $getter:ident , $is:ident , $unwrap:ident ; )* ) => {
61        $(
62            #[inline]
63            #[allow(missing_docs)]
64            pub fn $getter(&self) -> Option<$result> {
65                match *self {
66                    Self::$variant(x, ..) => Some(x),
67                    _ => None
68                }
69            }
70
71            #[inline]
72            #[allow(missing_docs)]
73            pub fn $is(&self) -> bool {
74                self.$getter().is_some()
75            }
76
77            #[inline]
78            #[allow(missing_docs)]
79            pub fn $unwrap(&self) -> $result {
80                self.$getter().expect(concat!("failed to unwrap `", stringify!($variant), "`"))
81            }
82        )*
83    }
84}
85
86impl Constant {
87    /// If this is any kind of integer constant, get it as a 64-bit unsigned
88    /// integer.
89    pub fn as_int(&self) -> Option<u64> {
90        match *self {
91            Constant::Bool(..) => None,
92            Constant::Int(x, _) => Some(x),
93        }
94    }
95
96    /// If this is any kind of boolean constant, get its value.
97    pub fn as_bool(&self) -> Option<bool> {
98        match *self {
99            Constant::Bool(b, _) => Some(b),
100            Constant::Int(..) => None,
101        }
102    }
103
104    /// The number of bits required to represent this constant value's type.
105    pub fn bit_width(&self, root_width: u8) -> u8 {
106        match *self {
107            Constant::Bool(_, w) | Constant::Int(_, w) => {
108                if let Some(w) = w.fixed_width() {
109                    w
110                } else {
111                    debug_assert!(w.is_polymorphic());
112                    root_width
113                }
114            }
115        }
116    }
117}
118
119impl<I> Part<I>
120where
121    I: Copy + Debug + Eq,
122{
123    accessors! {
124        Instruction, I, as_instruction, is_instruction, unwrap_instruction;
125        Constant, Constant, as_constant, is_constant, unwrap_constant;
126        ConditionCode, ConditionCode, as_condition_code, is_condition_code, unwrap_condition_code;
127    }
128}