rapx/analysis/
opt.rs

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