Skip to main content

rapx/check/safedrop/
drop.rs

1use super::checks;
2use super::graph::*;
3
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5pub struct LocalSpot {
6    pub bb: Option<usize>,
7    pub local: Option<usize>,
8}
9
10impl LocalSpot {
11    pub fn new(bb: usize, local: usize) -> Self {
12        LocalSpot {
13            bb: Some(bb),
14            local: Some(local),
15        }
16    }
17    pub fn from_local(local: usize) -> Self {
18        LocalSpot {
19            bb: None,
20            local: Some(local),
21        }
22    }
23    pub fn default() -> Self {
24        LocalSpot {
25            bb: None,
26            local: None,
27        }
28    }
29}
30
31#[derive(Debug, Clone)]
32pub struct DropRecord {
33    pub value_index: usize,
34    pub is_dropped: bool,
35    pub drop_spot: LocalSpot,
36    pub prop_chain: Vec<usize>,
37    pub has_dropped_field: bool,
38}
39
40impl DropRecord {
41    pub fn new(value_index: usize, is_dropped: bool, drop_spot: LocalSpot) -> Self {
42        DropRecord {
43            value_index,
44            is_dropped,
45            drop_spot,
46            prop_chain: Vec::new(),
47            has_dropped_field: false,
48        }
49    }
50    pub fn false_record(value_index: usize) -> Self {
51        DropRecord {
52            value_index,
53            is_dropped: false,
54            drop_spot: LocalSpot::default(),
55            prop_chain: Vec::new(),
56            has_dropped_field: false,
57        }
58    }
59    pub fn from(value_index: usize, record: &DropRecord) -> Self {
60        DropRecord {
61            value_index,
62            is_dropped: record.is_dropped,
63            drop_spot: record.drop_spot.clone(),
64            prop_chain: record.prop_chain.clone(),
65            has_dropped_field: record.has_dropped_field,
66        }
67    }
68    pub fn clear(&mut self) {
69        self.is_dropped = false;
70        self.drop_spot = LocalSpot::default();
71        self.prop_chain.clear();
72        self.has_dropped_field = false;
73    }
74}
75
76impl<'tcx> SafeDropGraph<'tcx> {
77    /*
78     * Mark the node as dropped.
79     * flag_cleanup: used to distinguish if a bug occurs in the unwinding path.
80     */
81    pub fn add_to_drop_record(
82        &mut self,
83        value_idx: usize, // the value to be dropped
84        bb_idx: usize,    // the block via_idx is dropped
85        flag_cleanup: bool,
86    ) {
87        rap_debug!(
88            "add_to_drop_record: value_idx = {}, bb_idx = {}",
89            value_idx,
90            bb_idx
91        );
92        if self
93            .alias_graph
94            .value_to_slot_idx(value_idx)
95            .is_some_and(|si| self.alias_graph.pts_graph.slot_is_ref_count(si))
96        {
97            return;
98        }
99        if self.df_check(value_idx, bb_idx, self.alias_graph.span(), flag_cleanup) {
100            return;
101        }
102        if !self.drop_record[value_idx].is_dropped {
103            let local = self
104                .alias_graph
105                .value_to_slot_idx(value_idx)
106                .and_then(|si| self.alias_graph.pts_graph.get_slot(si))
107                .map(|s| s.local)
108                .unwrap_or(value_idx);
109            let drop_spot = LocalSpot::new(bb_idx, local);
110            self.drop_record[value_idx] = DropRecord::new(value_idx, true, drop_spot);
111            rap_debug!("{:?}", self.drop_record[value_idx]);
112            checks::push_drop_info(
113                &self.alias_graph,
114                &mut self.drop_record,
115                value_idx,
116                drop_spot,
117            );
118        }
119    }
120}