use crate::analysis::cpa::lattice::JoinSemiLattice;
use crate::analysis::pcode_store::{PcodeOpRef, PcodeStore};
use crate::modeling::machine::cpu::concrete::ConcretePcodeAddress;
use jingle_sleigh::PcodeOperation;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::ops::{Add, AddAssign};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum MergeOutcome {
NoOp,
Merged,
}
impl MergeOutcome {
pub fn merged(&self) -> bool {
matches!(self, MergeOutcome::Merged)
}
}
impl Add for MergeOutcome {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::NoOp, Self::NoOp) => Self::NoOp,
_ => Self::Merged,
}
}
}
impl AddAssign for MergeOutcome {
fn add_assign(&mut self, rhs: Self) {
(*self) = *self + rhs
}
}
pub trait CloneableIter<'a, T>: Iterator<Item = T> {
fn clone_box(&self) -> Box<dyn CloneableIter<'a, T> + 'a>;
}
impl<'a, T, I> CloneableIter<'a, T> for I
where
I: Iterator<Item = T> + Clone + 'a,
{
fn clone_box(&self) -> Box<dyn CloneableIter<'a, T> + 'a> {
Box::new(self.clone())
}
}
pub struct DynIterBox<'a, T>(Box<dyn CloneableIter<'a, T> + 'a>);
impl<'a, T> DynIterBox<'a, T> {
pub fn new<I>(iter: I) -> Self
where
I: Iterator<Item = T> + Clone + 'a,
{
DynIterBox(Box::new(iter))
}
}
impl<'a, T> Clone for DynIterBox<'a, T> {
fn clone(&self) -> Self {
DynIterBox(self.0.clone_box())
}
}
impl<'a, T> Iterator for DynIterBox<'a, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, T> Debug for DynIterBox<'a, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.write_str("DynIterBox { .. }")
}
}
pub struct Successor<'a, T>(DynIterBox<'a, T>);
impl<'a, T> Successor<'a, T> {
pub fn empty() -> Self
where
T: 'a,
{
Self(DynIterBox::new(std::iter::empty::<T>()))
}
}
impl<'a, T> Clone for Successor<'a, T> {
fn clone(&self) -> Self {
Successor(self.0.clone())
}
}
impl<'a, T: 'a> IntoIterator for Successor<'a, T> {
type Item = T;
type IntoIter = DynIterBox<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.0
}
}
impl<'a, T: 'a, I> From<I> for Successor<'a, T>
where
I: Iterator<Item = T> + Clone + 'a,
{
fn from(value: I) -> Self {
Self(DynIterBox::new(value))
}
}
pub trait AbstractState: JoinSemiLattice + Clone + Debug + Display {
fn merge(&mut self, other: &Self) -> MergeOutcome;
fn merge_join(&mut self, new_state: &Self) -> MergeOutcome {
if self == new_state {
MergeOutcome::NoOp
} else {
self.join(new_state);
MergeOutcome::Merged
}
}
fn merge_sep(&mut self, _: &Self) -> MergeOutcome {
MergeOutcome::NoOp
}
fn stop<'a, T: Iterator<Item = &'a Self>>(&'a self, states: T) -> bool;
fn stop_sep<'a, T: Iterator<Item = &'a Self>>(&'a self, mut states: T) -> bool {
states.any(|s| {
matches!(
PartialOrd::partial_cmp(self, s),
Some(Ordering::Less) | Some(Ordering::Equal)
)
})
}
fn transfer<'a, B: Borrow<PcodeOperation>>(&'a self, opcode: B) -> Successor<'a, Self>;
}
pub trait LocationState: AbstractState {
fn get_operation<'op, T: PcodeStore<'op> + ?Sized>(&self, t: &'op T)
-> Option<PcodeOpRef<'op>>;
fn get_location(&self) -> Option<ConcretePcodeAddress>;
}