use crate::{
abstr::{eq_domain::EqualityDomain, BitvectorDomain, Boolean, PanicResult},
concr::ConcreteBitvector,
forward::{BExt, Bitwise, HwArith, HwShift, TypedCmp, TypedEq},
misc::{BitvectorBound, CBound},
ThreeValued,
};
use super::EqualityTracker;
impl<B: BitvectorBound> TypedEq for EqualityDomain<B> {
type Output = Boolean;
fn eq(self, rhs: Self) -> Self::Output {
let (EqualityTracker::Tracked(lhs), EqualityTracker::Tracked(rhs)) =
(self.tracker, rhs.tracker)
else {
return Boolean::from_three_valued(ThreeValued::Unknown);
};
if lhs == rhs {
Boolean::new(true)
} else {
Boolean::from_three_valued(ThreeValued::Unknown)
}
}
fn ne(self, rhs: Self) -> Self::Output {
self.eq(rhs).bit_not()
}
}
impl<B: BitvectorBound> Bitwise for EqualityDomain<B> {
fn bit_not(self) -> Self {
self.into_top()
}
fn bit_and(self, rhs: Self) -> Self {
assert_eq!(self.bound, rhs.bound);
let tracker = match (self.tracker, rhs.tracker) {
(EqualityTracker::Top, _)
| (_, EqualityTracker::Top)
| (EqualityTracker::Constant(_), EqualityTracker::Constant(_)) => EqualityTracker::Top,
(EqualityTracker::Tracked(left), EqualityTracker::Tracked(right)) => {
if left == right {
EqualityTracker::Tracked(left)
} else {
EqualityTracker::Top
}
}
(EqualityTracker::Tracked(tracked), EqualityTracker::Constant(concrete))
| (EqualityTracker::Constant(concrete), EqualityTracker::Tracked(tracked)) => {
if concrete.is_full_mask() {
EqualityTracker::Tracked(tracked)
} else {
EqualityTracker::Top
}
}
};
Self {
tracker,
bound: self.bound,
}
}
fn bit_or(self, rhs: Self) -> Self {
assert_eq!(self.bound, rhs.bound);
let tracker = match (self.tracker, rhs.tracker) {
(EqualityTracker::Top, _)
| (_, EqualityTracker::Top)
| (EqualityTracker::Constant(_), EqualityTracker::Constant(_)) => EqualityTracker::Top,
(EqualityTracker::Tracked(left), EqualityTracker::Tracked(right)) => {
if left == right {
EqualityTracker::Tracked(left)
} else {
EqualityTracker::Top
}
}
(EqualityTracker::Tracked(tracked), EqualityTracker::Constant(concrete))
| (EqualityTracker::Constant(concrete), EqualityTracker::Tracked(tracked)) => {
if concrete.is_zero() {
EqualityTracker::Tracked(tracked)
} else {
EqualityTracker::Top
}
}
};
Self {
tracker,
bound: self.bound,
}
}
fn bit_xor(self, rhs: Self) -> Self {
assert_eq!(self.bound, rhs.bound);
let tracker = match (self.tracker, rhs.tracker) {
(EqualityTracker::Top, _)
| (_, EqualityTracker::Top)
| (EqualityTracker::Constant(_), EqualityTracker::Constant(_)) => EqualityTracker::Top,
(EqualityTracker::Tracked(left), EqualityTracker::Tracked(right)) => {
if left == right {
EqualityTracker::Constant(ConcreteBitvector::zero(self.bound))
} else {
EqualityTracker::Top
}
}
(EqualityTracker::Tracked(tracked), EqualityTracker::Constant(concrete))
| (EqualityTracker::Constant(concrete), EqualityTracker::Tracked(tracked)) => {
if concrete.is_zero() {
EqualityTracker::Tracked(tracked)
} else {
EqualityTracker::Top
}
}
};
Self {
tracker,
bound: self.bound,
}
}
}
impl<B: BitvectorBound> HwArith for EqualityDomain<B> {
type DivRemResult = PanicResult<Self>;
fn arith_neg(self) -> Self {
self.into_top()
}
fn add(self, _rhs: Self) -> Self {
self.into_top()
}
fn sub(self, _rhs: Self) -> Self {
self.into_top()
}
fn mul(self, _rhs: Self) -> Self {
self.into_top()
}
fn udiv(self, _rhs: Self) -> PanicResult<Self> {
PanicResult {
panic: BitvectorDomain::top(CBound),
result: self.into_top(),
}
}
fn sdiv(self, _rhs: Self) -> PanicResult<Self> {
PanicResult {
panic: BitvectorDomain::top(CBound),
result: self.into_top(),
}
}
fn urem(self, _rhs: Self) -> PanicResult<Self> {
PanicResult {
panic: BitvectorDomain::top(CBound),
result: self.into_top(),
}
}
fn srem(self, _rhs: Self) -> PanicResult<Self> {
PanicResult {
panic: BitvectorDomain::top(CBound),
result: self.into_top(),
}
}
}
impl<B: BitvectorBound> HwShift for EqualityDomain<B> {
type Output = Self;
fn logic_shl(self, _amount: Self) -> Self::Output {
self.into_top()
}
fn logic_shr(self, _amount: Self) -> Self::Output {
self.into_top()
}
fn arith_shr(self, _amount: Self) -> Self::Output {
self.into_top()
}
}
impl<B: BitvectorBound> TypedCmp for EqualityDomain<B> {
type Output = Boolean;
fn ult(self, _rhs: Self) -> Self::Output {
Boolean::from_three_valued(ThreeValued::Unknown)
}
fn slt(self, _rhs: Self) -> Self::Output {
Boolean::from_three_valued(ThreeValued::Unknown)
}
fn ule(self, _rhs: Self) -> Self::Output {
Boolean::from_three_valued(ThreeValued::Unknown)
}
fn sle(self, _rhs: Self) -> Self::Output {
Boolean::from_three_valued(ThreeValued::Unknown)
}
}
impl<B: BitvectorBound, X: BitvectorBound> BExt<X> for EqualityDomain<B> {
type Output = EqualityDomain<X>;
fn uext(self, new_bound: X) -> Self::Output {
EqualityDomain {
bound: new_bound,
tracker: EqualityTracker::Top,
}
}
fn sext(self, new_bound: X) -> Self::Output {
EqualityDomain {
bound: new_bound,
tracker: EqualityTracker::Top,
}
}
}