use std::fmt::Display;
use std::marker::PhantomData;
use std::sync::Arc;
use crate::analysis::cfg::CfgState;
use crate::analysis::cpa::lattice::JoinSemiLattice;
use crate::analysis::cpa::residue::VecReducer;
use crate::analysis::cpa::{
ConfigurableProgramAnalysis, IntoState, RunnableConfigurableProgramAnalysis,
};
use crate::analysis::linkage::PcodeReverseLinkage;
use crate::analysis::pcode_store::PcodeStore;
pub mod state;
pub use state::ReverseLocationState;
pub struct ReverseLocationAnalysis<N: CfgState, L: PcodeReverseLinkage<N>> {
linkage: Arc<L>,
_phantom: PhantomData<N>,
}
impl<N: CfgState, L: PcodeReverseLinkage<N>> ReverseLocationAnalysis<N, L> {
#[must_use]
pub fn new(linkage: Arc<L>) -> Self {
Self {
linkage,
_phantom: PhantomData,
}
}
#[must_use]
pub fn linkage(&self) -> &L {
&self.linkage
}
}
impl<N, L> ConfigurableProgramAnalysis for ReverseLocationAnalysis<N, L>
where
N: CfgState + JoinSemiLattice + Display + PartialOrd + 'static,
L: PcodeReverseLinkage<N> + 'static,
{
type State = ReverseLocationState<N, L>;
type Reducer<'op> = VecReducer;
}
impl<N, L> IntoState<ReverseLocationAnalysis<N, L>> for N
where
N: CfgState + JoinSemiLattice + Display + PartialOrd + 'static,
L: PcodeReverseLinkage<N> + 'static,
{
fn into_state(self, c: &ReverseLocationAnalysis<N, L>) -> ReverseLocationState<N, L> {
ReverseLocationState {
inner: self,
linkage: Arc::clone(&c.linkage),
}
}
}
impl<N, L> ReverseLocationAnalysis<N, L>
where
N: CfgState + JoinSemiLattice + Display + PartialOrd + 'static,
L: PcodeReverseLinkage<N> + 'static,
{
#[must_use]
pub fn run_from_leaves<'op, T: PcodeStore<'op> + ?Sized>(
&self,
store: &'op T,
) -> Vec<ReverseLocationState<N, L>>
where
ReverseLocationState<N, L>: 'op,
{
let mut all = Vec::new();
for leaf in self.linkage.leaf_nodes() {
let initial = ReverseLocationState {
inner: leaf,
linkage: Arc::clone(&self.linkage),
};
let results = self.run_cpa(initial, store);
all.extend(results);
}
all
}
}