sleigh_rs/semantic/inner/pattern/
constraint.rs

1use crate::pattern::BitConstraint;
2use crate::semantic::pattern::{CmpOp, ConstraintValue};
3use crate::FieldBits;
4
5impl BitConstraint {
6    pub fn define(self, bit: bool) -> Option<Self> {
7        match self {
8            Self::Unrestrained => Some(Self::Defined(bit)),
9            Self::Defined(old_bit) if old_bit == bit => Some(self),
10            Self::Defined(_old_bit) => None,
11            // TODO this may not be possible, we are unable to verify that now
12            Self::Restrained => Some(Self::Defined(bit)),
13        }
14    }
15    /// select the most restrictive from both, None if they conflict
16    pub fn most_restrictive(self, other: Self) -> Option<Self> {
17        match (self, other) {
18            //if one is unrestrained, just return the other
19            (Self::Unrestrained, other) | (other, Self::Unrestrained) => {
20                Some(other)
21            }
22            // both have the same value
23            (Self::Restrained, Self::Restrained) => Some(self),
24            (Self::Defined(self_value), Self::Defined(other_value))
25                if self_value == other_value =>
26            {
27                Some(self)
28            }
29            // conflicting values
30            (Self::Defined(_), Self::Defined(_)) => None,
31            // TODO this may not be possible, we are unable to verify that now
32            (other @ Self::Defined(_), Self::Restrained)
33            | (Self::Restrained, other @ Self::Defined(_)) => Some(other),
34        }
35    }
36    /// select the least restrictive from both
37    pub fn least_restrictive(self, other: Self) -> Self {
38        match (self, other) {
39            (Self::Unrestrained, _other) | (_other, Self::Unrestrained) => {
40                Self::Unrestrained
41            }
42            (Self::Defined(self_value), Self::Defined(other_value))
43                if self_value != other_value =>
44            {
45                Self::Restrained
46            }
47            //both have the same value
48            (Self::Defined(_), Self::Defined(_)) => self,
49            (Self::Restrained, Self::Restrained)
50            | (Self::Defined(_), Self::Restrained)
51            | (Self::Restrained, Self::Defined(_)) => Self::Restrained,
52        }
53    }
54}
55
56pub fn apply_value(
57    constraint: &mut [BitConstraint],
58    field_order: fn(usize, usize) -> usize,
59    value_order: fn(usize, usize) -> usize,
60    field_bits: FieldBits,
61    op: CmpOp,
62    value: &ConstraintValue,
63) -> Option<()> {
64    //only set the value, if its Eq and the value is known at compile time
65    use crate::semantic::disassembly::{ExprElement, ReadScope};
66    let value = match (op, value.expr().elements()) {
67        (
68            CmpOp::Eq,
69            [ExprElement::Value {
70                value: ReadScope::Integer(value),
71                location: _,
72            }],
73        ) => Some(value.signed_super()),
74        _ => None,
75    };
76
77    let field_bits_len = field_bits.len().get().try_into().unwrap();
78    for (value_bit, field_bit) in field_bits.0.into_iter().enumerate() {
79        let field_bit = field_bit.try_into().unwrap();
80        let field_bit = field_order(field_bit, constraint.len());
81        let bit = &mut constraint[field_bit as usize];
82        if let Some(value) = value {
83            let value_bit = value_order(value_bit, field_bits_len);
84            let value_bit = (value >> value_bit) & 1 != 0;
85            *bit = bit.define(value_bit)?;
86        } else {
87            //error never happen with `BitConstraint::Restrained`
88            *bit = bit.most_restrictive(BitConstraint::Restrained).unwrap();
89        }
90    }
91    Some(())
92}