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, N>
where
N: LocationState + CfgState,
{
pub cfg: PcodeCfg<N, PcodeOpRef<'a>>,
}
impl<'a, N> Default for CfgReducer<'a, N>
where
N: LocationState + CfgState,
{
fn default() -> Self {
Self::new()
}
}
impl<'a, N> CfgReducer<'a, N>
where
N: LocationState + CfgState,
{
pub fn new() -> Self {
Self {
cfg: PcodeCfg::new(),
}
}
pub fn take_cfg(&mut self) -> PcodeCfg<N, PcodeOpRef<'a>> {
std::mem::take(&mut self.cfg)
}
}
impl<'a, N> Residue<'a, N> for CfgReducer<'a, N>
where
N: LocationState + CfgState,
{
type Output = PcodeCfg<N, PcodeOpRef<'a>>;
fn new_state(&mut self, state: &N, dest_state: &N, op: &Option<PcodeOpRef<'a>>) {
self.cfg.add_node(state);
if let Some(op_ref) = op {
let owned = op_ref.clone();
self.cfg.add_edge(state, dest_state, owned);
}
}
fn merged_state(
&mut self,
state: &N,
dest_state: &N,
merged_state: &N,
op: &Option<PcodeOpRef<'a>>,
) {
self.cfg.replace_and_combine_nodes(dest_state, merged_state);
if let Some(op_ref) = op {
let owned = op_ref.clone();
self.cfg.add_edge(state, merged_state, owned);
}
}
fn new() -> Self {
Self::new()
}
fn finalize(self) -> Self::Output {
self.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, A::State>;
fn make<'op>(&self) -> Self::Reducer<'op> {
CfgReducer {
cfg: PcodeCfg::new(),
}
}
}