rapx/analysis/upg/
upg_unit.rs

1use crate::analysis::utils::fn_info::*;
2use rustc_hir::{Safety, def_id::DefId};
3use rustc_middle::mir::Local;
4use std::collections::HashSet;
5
6#[derive(Debug, Clone)]
7pub struct UPGUnit {
8    pub caller: FnInfo,
9    pub callees: HashSet<FnInfo>,
10    pub raw_ptrs: HashSet<Local>,
11    pub static_muts: HashSet<DefId>,
12    pub caller_cons: HashSet<FnInfo>,
13    pub mut_methods: Vec<DefId>,
14}
15
16impl UPGUnit {
17    pub fn new(
18        caller: FnInfo,
19        callees: HashSet<FnInfo>,
20        raw_ptrs: HashSet<Local>,
21        static_muts: HashSet<DefId>,
22        caller_cons: HashSet<FnInfo>,
23        mut_methods: Vec<DefId>,
24    ) -> Self {
25        Self {
26            caller,
27            callees,
28            raw_ptrs,
29            static_muts,
30            caller_cons,
31            mut_methods,
32        }
33    }
34
35    pub fn count_basic_units(&self, data: &mut [u32]) {
36        if self.caller.fn_safety == Safety::Unsafe && self.callees.is_empty() {
37            data[0] += 1;
38        }
39        if self.caller.fn_safety == Safety::Safe && self.caller.fn_kind != FnKind::Method {
40            for callee in &self.callees {
41                if callee.fn_kind == FnKind::Method {
42                    data[2] += 1;
43                } else {
44                    data[1] += 1;
45                }
46            }
47        }
48        if self.caller.fn_safety == Safety::Unsafe && self.caller.fn_kind != FnKind::Method {
49            for callee in &self.callees {
50                if callee.fn_kind == FnKind::Method {
51                    data[4] += 1;
52                } else {
53                    data[3] += 1;
54                }
55            }
56        }
57        if self.caller.fn_safety == Safety::Unsafe && self.caller.fn_kind == FnKind::Method {
58            let mut unsafe_cons = 0;
59            let mut safe_cons = 0;
60            for cons in &self.caller_cons {
61                if cons.fn_safety == Safety::Unsafe {
62                    unsafe_cons += 1;
63                } else {
64                    safe_cons += 1;
65                }
66            }
67            if unsafe_cons == 0 && safe_cons == 0 {
68                safe_cons = 1;
69            }
70            for callee in &self.callees {
71                if callee.fn_kind == FnKind::Method {
72                    data[7] += safe_cons;
73                    data[8] += unsafe_cons;
74                } else {
75                    data[5] += safe_cons;
76                    data[6] += unsafe_cons;
77                }
78            }
79        }
80        if self.caller.fn_safety == Safety::Safe && self.caller.fn_kind == FnKind::Method {
81            let mut unsafe_cons = 0;
82            let mut safe_cons = 0;
83            for cons in &self.caller_cons {
84                if cons.fn_safety == Safety::Unsafe {
85                    unsafe_cons += 1;
86                } else {
87                    safe_cons += 1;
88                }
89            }
90            if unsafe_cons == 0 && safe_cons == 0 {
91                safe_cons = 1;
92            }
93            for callee in &self.callees {
94                if callee.fn_kind == FnKind::Method {
95                    data[11] += safe_cons;
96                    data[12] += unsafe_cons;
97                } else {
98                    data[9] += safe_cons;
99                    data[10] += unsafe_cons;
100                }
101            }
102        }
103    }
104}