rapx/analysis/opt/
mod.rs

1pub mod checking;
2pub mod data_collection;
3pub mod iterator;
4pub mod memory_cloning;
5
6use rustc_middle::ty::TyCtxt;
7
8use crate::utils::log::span_to_source_code;
9
10use super::core::dataflow::{default::DataFlowAnalyzer, graph::Graph};
11use checking::bounds_checking::BoundsCheck;
12use checking::encoding_checking::EncodingCheck;
13use data_collection::initialization::InitializationCheck;
14use data_collection::reallocation::ReservationCheck;
15use data_collection::suboptimal::SuboptimalCheck;
16use memory_cloning::used_as_immutable::UsedAsImmutableCheck;
17
18use lazy_static::lazy_static;
19use rustc_span::symbol::Symbol;
20use std::sync::Mutex;
21
22lazy_static! {
23    pub static ref NO_STD: Mutex<bool> = Mutex::new(false);
24    pub static ref LEVEL: Mutex<usize> = Mutex::new(0);
25}
26
27pub struct Opt<'tcx> {
28    pub tcx: TyCtxt<'tcx>,
29    pub level: usize,
30}
31
32pub trait OptCheck {
33    fn new() -> Self;
34    fn check(&mut self, graph: &Graph, tcx: &TyCtxt);
35    fn report(&self, graph: &Graph);
36    fn cnt(&self) -> usize;
37}
38
39impl<'tcx> Opt<'tcx> {
40    pub fn new(tcx: TyCtxt<'tcx>, level: usize) -> Self {
41        Self { tcx, level }
42    }
43
44    fn has_crate(&self, name: &str) -> bool {
45        for num in self.tcx.crates(()) {
46            if self.tcx.crate_name(*num) == Symbol::intern(name) {
47                return true;
48            }
49        }
50        false
51    }
52
53    pub fn start(&mut self) {
54        let mut dataflow = DataFlowAnalyzer::new(self.tcx, false);
55        dataflow.build_graphs();
56        {
57            let mut no_std = NO_STD.lock().unwrap();
58            *no_std = !self.has_crate("std");
59            let mut level = LEVEL.lock().unwrap();
60            *level = self.level;
61        }
62        if !self.has_crate("core") {
63            //core it self
64            return;
65        }
66
67        let mut statistics = vec![0 as usize; 6];
68
69        dataflow.graphs.iter().for_each(|(_, graph)| {
70            let mut bounds_check = BoundsCheck::new();
71            bounds_check.check(graph, &self.tcx);
72            statistics[0] += bounds_check.cnt();
73
74            if self.level > 0 {
75                bounds_check.report(graph);
76            }
77
78            let no_std = NO_STD.lock().unwrap();
79            if !*no_std {
80                let mut encoding_check = EncodingCheck::new();
81                encoding_check.check(graph, &self.tcx);
82                statistics[1] += encoding_check.cnt();
83
84                let mut suboptimal_check = SuboptimalCheck::new();
85                suboptimal_check.check(graph, &self.tcx);
86                statistics[2] += suboptimal_check.cnt();
87
88                let mut initialization_check = InitializationCheck::new();
89                initialization_check.check(graph, &self.tcx);
90                statistics[3] += initialization_check.cnt();
91
92                let mut reservation_check = ReservationCheck::new();
93                reservation_check.check(graph, &self.tcx);
94                statistics[4] += reservation_check.cnt();
95
96                let mut used_as_immutable_check = UsedAsImmutableCheck::new();
97                used_as_immutable_check.check(graph, &self.tcx);
98                statistics[5] += used_as_immutable_check.cnt();
99
100                if self.level > 0 {
101                    encoding_check.report(graph);
102                    suboptimal_check.report(graph);
103                    initialization_check.report(graph);
104                    reservation_check.report(graph);
105                    used_as_immutable_check.report(graph);
106                }
107            }
108        });
109
110        let bug_cnt: usize = statistics.iter().sum();
111        let func_cnt: usize = dataflow.graphs.iter().count();
112        let line_cnt: usize = dataflow
113            .graphs
114            .iter()
115            .map(|(_, graph)| span_to_source_code(graph.span).lines().count())
116            .sum();
117        if bug_cnt > 0 {
118            rap_warn!("Potential optimizations detected.");
119            println!(
120                "RAPx detects {} code inefficiencies from {} functions ({} lines)",
121                bug_cnt, func_cnt, line_cnt,
122            );
123            println!("  Bounds Checking: {}", statistics[0]);
124            println!("  Encoding Checking: {}", statistics[1]);
125            println!("  Suboptimal: {}", statistics[2]);
126            println!("  Initialization: {}", statistics[3]);
127            println!("  Reallocation: {}", statistics[4]);
128            println!("  Cloning: {}", statistics[5]);
129        }
130    }
131}