open_vaf/analysis/data_flow/framework/
engine.rs

1//  * ******************************************************************************************
2//  * Copyright (c) 2019 Pascal Kuthe. This file is part of the OpenVAF project.
3//  * It is subject to the license terms in the LICENSE file found in the top-level directory
4//  *  of this distribution and at  https://gitlab.com/DSPOM/OpenVAF/blob/master/LICENSE.
5//  *  No part of OpenVAF, including this file, may be copied, modified, propagated, or
6//  *  distributed except according to the terms contained in the LICENSE file.
7//  * *******************************************************************************************
8
9use std::mem::swap;
10
11use crate::analysis::data_flow::framework::{Analysis, DataFlowGraph, Direction};
12use crate::data_structures::BitSet;
13use crate::ir::cfg::ControlFlowGraph;
14use log::*;
15
16pub struct Engine<'lt, A: Analysis<'lt>> {
17    pub analysis: &'lt mut A,
18    pub dfg: DataFlowGraph<A::SetType>,
19    pub cfg: &'lt ControlFlowGraph,
20}
21
22impl<'lt, A: Analysis<'lt>> Engine<'lt, A> {
23    pub fn new(cfg: &'lt ControlFlowGraph, analysis: &'lt mut A) -> Self {
24        Self {
25            dfg: DataFlowGraph::new(analysis.max_idx(), cfg),
26            analysis,
27            cfg,
28        }
29    }
30
31    pub fn iterate_to_fixpoint(mut self) -> DataFlowGraph<A::SetType> {
32        let mut worklist =
33            <<A as Analysis<'lt>>::Direction as Direction<'lt>>::inital_work_queue(self.cfg);
34        let mut temporary_set = BitSet::new_empty(self.analysis.max_idx());
35        trace!("Data Flow Engine: Starting with worklist: {:?}", worklist);
36        while let Some(bb) = worklist.pop() {
37            trace!("Data Flow Engine: Processing {:?}", bb);
38            self.analysis.transfer_function(
39                &self.dfg.in_sets[bb],
40                &mut temporary_set,
41                bb,
42                self.cfg,
43            );
44            if temporary_set != self.dfg.out_sets[bb] {
45                swap(&mut temporary_set, &mut self.dfg.out_sets[bb]);
46
47                A::Direction::propagate_result(bb, self.cfg, |dst| {
48                    worklist.insert(dst);
49                    self.analysis
50                        .join(&mut self.dfg.in_sets[dst], &self.dfg.out_sets[bb])
51                });
52            }
53        }
54        self.dfg
55    }
56}