rapx/analysis/upg/
upg_unit.rs1use 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}