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