use std::{any::Any, cell::RefCell, rc::Rc};
use type_map::TypeMap;
use crate::Optimizer;
use super::{
dominance::{Dominators, PostDominators},
liveness::Liveness,
post_order::PostOrder,
uniformity::Uniformity,
};
pub trait Analysis {
fn init(opt: &mut Optimizer) -> Self;
}
#[derive(Default, Clone, Debug)]
pub struct AnalysisCache {
cache: Rc<RefCell<TypeMap>>,
}
impl AnalysisCache {
pub fn get<A: Analysis + Any>(&self, opt: &mut Optimizer) -> Rc<A> {
let analysis = self.cache.borrow().get::<Rc<A>>().cloned();
if let Some(analysis) = analysis {
analysis
} else {
let analysis = Rc::new(A::init(opt));
self.cache.borrow_mut().insert(analysis.clone());
analysis
}
}
pub fn try_get<A: Any>(&self) -> Option<Rc<A>> {
self.cache.borrow().get().cloned()
}
pub fn invalidate<A: Analysis + Any>(&self) {
self.cache.borrow_mut().remove::<Rc<A>>();
}
}
impl Optimizer {
pub fn analysis<A: Analysis + Any>(&mut self) -> Rc<A> {
let analyses = self.analysis_cache.clone();
analyses.get(self)
}
pub fn invalidate_analysis<A: Analysis + Any>(&self) {
self.analysis_cache.invalidate::<A>();
}
pub fn invalidate_structure(&self) {
self.invalidate_analysis::<PostOrder>();
self.invalidate_analysis::<Dominators>();
self.invalidate_analysis::<PostDominators>();
self.invalidate_analysis::<Liveness>();
self.invalidate_analysis::<Uniformity>();
}
}