Skip to main content

rapx/check/opt/
mod.rs

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