1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use crate::ir::{self, FunctionDefinition};

use self::register_usage::RegisterUsageAnalyzer;
pub use self::{
    control_flow::{BindedControlFlowGraph, BindedScc, ControlFlowGraph},
    memory_usage::{BindedMemoryUsage, MemoryUsage},
    register_usage::{BindedRegisterUsage, BindedRegisterUsageAnalyzer},
};
use super::action::Action;

pub mod control_flow;
mod memory_usage;
pub mod register_usage;

pub trait IsAnalyzer<'item, 'bind: 'item> {
    type Binded;
    fn on_action(&'item mut self, action: &Action);
    fn bind(&'item self, content: &'bind ir::FunctionDefinition) -> Self::Binded;
}

/// [`Analyzer`] is for gather information about a [`FunctionDefinition`].
#[derive(Default, Debug)]
pub struct Analyzer {
    pub register_usage: RegisterUsageAnalyzer,
    pub memory_usage: MemoryUsage,
    pub control_flow_graph: ControlFlowGraph,
}

impl Analyzer {
    pub fn new() -> Self {
        Self {
            register_usage: RegisterUsageAnalyzer::new(),
            memory_usage: MemoryUsage::new(),
            control_flow_graph: ControlFlowGraph::new(),
        }
    }

    // todo: remove this when starting to care about performance
    pub fn clear_all_cache(&mut self) {
        *self = Self::new();
    }
}
pub struct BindedAnalyzer<'item, 'bind: 'item> {
    pub bind_on: &'bind FunctionDefinition,
    item: &'item Analyzer,
}

impl<'item, 'bind: 'item> BindedAnalyzer<'item, 'bind> {
    pub fn register_usage(&self) -> BindedRegisterUsageAnalyzer {
        self.item.register_usage.bind(self.bind_on)
    }
    pub fn memory_usage(&self) -> BindedMemoryUsage {
        self.item.memory_usage.bind(self.bind_on)
    }
    pub fn control_flow_graph(&self) -> BindedControlFlowGraph {
        self.item.control_flow_graph.bind(self.bind_on)
    }
}

impl<'item, 'bind: 'item> IsAnalyzer<'item, 'bind> for Analyzer {
    fn on_action(&mut self, action: &Action) {
        self.register_usage.on_action(action);
        self.memory_usage.on_action(action);
        self.control_flow_graph.on_action(action);
    }

    type Binded = BindedAnalyzer<'item, 'bind>;

    fn bind(&'item self, content: &'bind ir::FunctionDefinition) -> Self::Binded {
        BindedAnalyzer {
            bind_on: content,
            item: self,
        }
    }
}