use crate::analysis::cfg::CfgState;
use crate::analysis::cfg::PcodeCfg;
use crate::analysis::cpa::residue::Residue;
use crate::analysis::cpa::state::LocationState;
use crate::analysis::pcode_store::PcodeOpRef;
#[derive(Debug)]
pub struct CfgReducer<'a> {
edges: Vec<(usize, usize, Option<PcodeOpRef<'a>>)>,
}
impl<'a> Default for CfgReducer<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> CfgReducer<'a> {
pub fn new() -> Self {
Self { edges: Vec::new() }
}
}
impl<'a, N> Residue<'a, N> for CfgReducer<'a>
where
N: LocationState + CfgState,
{
type Output = PcodeCfg<N, PcodeOpRef<'a>>;
fn new_state(&mut self, source_idx: usize, dest_idx: usize, op: &Option<PcodeOpRef<'a>>) {
self.edges.push((source_idx, dest_idx, op.clone()));
}
fn merged_state(&mut self, source_idx: usize, merged_idx: usize, op: &Option<PcodeOpRef<'a>>) {
self.edges.push((source_idx, merged_idx, op.clone()));
}
fn new() -> Self {
Self::new()
}
fn finalize(self, reached: Vec<N>) -> Self::Output {
let mut cfg = PcodeCfg::new();
for (source_idx, dest_idx, op) in self.edges {
if let Some(op_ref) = op {
cfg.add_edge(&reached[source_idx], &reached[dest_idx], op_ref);
} else {
cfg.add_node(&reached[source_idx]);
cfg.add_node(&reached[dest_idx]);
}
}
cfg
}
}
#[derive(Debug, Clone, Copy)]
pub struct CfgReducerFactory;
impl CfgReducerFactory {
pub const fn new() -> Self {
CfgReducerFactory
}
}
impl Default for CfgReducerFactory {
fn default() -> Self {
Self::new()
}
}
pub const CFG: CfgReducerFactory = CfgReducerFactory;
impl<A> crate::analysis::cpa::residue::ReducerFactoryForState<A> for CfgReducerFactory
where
A: crate::analysis::cpa::ConfigurableProgramAnalysis,
A::State: crate::analysis::cpa::state::LocationState + CfgState,
{
type Reducer<'op> = CfgReducer<'op>;
fn make<'op>(&self) -> Self::Reducer<'op> {
CfgReducer::new()
}
}