1use super::graph::*;
2use crate::analysis::alias_analysis::default::types::ValueKind;
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 pub fn add_to_drop_record(
82 &mut self,
83 value_idx: usize, bb_idx: usize, 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.alias_graph.values[value_idx].is_ref_count() {
94 return;
95 }
96 if self.df_check(value_idx, bb_idx, self.alias_graph.span(), flag_cleanup) {
97 return;
98 }
99 if !self.drop_record[value_idx].is_dropped {
100 let drop_spot = LocalSpot::new(bb_idx, self.alias_graph.values[value_idx].local);
101 self.drop_record[value_idx] = DropRecord::new(value_idx, true, drop_spot);
102 rap_debug!("{:?}", self.drop_record[value_idx]);
103 self.push_drop_info(value_idx, drop_spot);
104 }
105 }
106
107 pub fn push_drop_info(&mut self, value_idx: usize, drop_spot: LocalSpot) {
108 self.push_drop_bottom_up(value_idx, drop_spot);
109 self.push_drop_top_down(value_idx, drop_spot);
110 }
111
112 pub fn push_drop_top_down(&mut self, value_idx: usize, drop_spot: LocalSpot) {
114 rap_debug!("push_drop_top_down: value_idx = {}", value_idx);
115 let mut prop_chain = vec![value_idx];
116 for (_field_id, field_value_id) in self.alias_graph.values[value_idx].fields.clone() {
117 if self.alias_graph.values[field_value_id].kind == ValueKind::Ref {
118 continue;
119 }
120 self.drop_record[field_value_id] = DropRecord::new(field_value_id, true, drop_spot);
121 prop_chain.push(field_value_id);
122 self.drop_record[field_value_id].prop_chain = prop_chain.clone();
123 rap_debug!("{:?}", self.drop_record[field_value_id]);
124 self.push_drop_top_down(field_value_id, drop_spot);
125 }
126 }
127
128 pub fn push_drop_bottom_up(&mut self, value_idx: usize, drop_spot: LocalSpot) {
129 rap_debug!("push_drop_bottom_up: value_idx = {}", value_idx);
130 let mut father = self.alias_graph.values[value_idx].father.clone();
131 let mut prop_chain = vec![value_idx];
132 while let Some(father_info) = father {
133 let father_idx = father_info.father_value_id;
134 self.drop_record[father_idx].has_dropped_field = true;
135 if !self.drop_record[father_idx].is_dropped {
136 prop_chain.push(father_idx);
137 self.drop_record[father_idx].prop_chain = prop_chain.clone();
138 self.drop_record[father_idx].drop_spot = drop_spot;
139 }
140 rap_debug!("{:?}", self.drop_record[father_idx]);
141 father = self.alias_graph.values[father_idx].father.clone();
142 }
143 }
144
145 pub fn fetch_drop_info(&mut self, value_idx: usize) {
146 self.fetch_drop_from_bottom(value_idx);
147 self.fetch_drop_from_top(value_idx);
148 self.fetch_drop_from_alias(value_idx);
149 }
150
151 pub fn clear_drop_info(&mut self, value_idx: usize) {
152 rap_debug!("clear_drop: value_idx = {}", value_idx);
153 self.drop_record[value_idx].clear();
154 self.clear_field_drop(value_idx);
155 self.clear_father_drop(value_idx);
156 }
157
158 pub fn clear_father_drop(&mut self, value_idx: usize) {
159 rap_debug!("clear_drop_father: value_idx = {}", value_idx);
160 let mut father = self.alias_graph.values[value_idx].father.clone();
162 while let Some(father_info) = father {
163 let father_idx = father_info.father_value_id;
164 if !self.drop_record[father_idx].is_dropped {
165 self.drop_record[father_idx].clear();
166 }
167 father = self.alias_graph.values[father_idx].father.clone();
168 }
169 }
170
171 pub fn clear_field_drop(&mut self, value_idx: usize) {
172 rap_debug!("clear_field_drop: value_idx = {}", value_idx);
173 for (_field_id, field_value_id) in self.alias_graph.values[value_idx].fields.clone() {
174 self.drop_record[field_value_id].clear();
175 self.clear_field_drop(field_value_id);
176 }
177 }
178
179 pub fn fetch_drop_from_bottom(&mut self, value_idx: usize) {
180 rap_debug!("fetch_drop_from_bottom: value_idx = {}", value_idx);
181 for (_field_id, field_value_id) in self.alias_graph.values[value_idx].fields.clone() {
182 rap_debug!("{:?}", self.drop_record[field_value_id]);
183 self.fetch_drop_from_alias(field_value_id);
184 if self.drop_record[field_value_id].is_dropped {
185 self.push_drop_bottom_up(
186 field_value_id,
187 self.drop_record[field_value_id].drop_spot,
188 );
189 rap_debug!("{:?}", self.drop_record[value_idx]);
190 break;
191 }
192 self.fetch_drop_from_bottom(field_value_id);
193 }
194 }
195
196 pub fn fetch_drop_from_top(&mut self, value_idx: usize) {
197 rap_debug!("fetch_drop_from_top: value_idx = {}", value_idx);
198 let mut father = self.alias_graph.values[value_idx].father.clone();
199 while let Some(father_info) = father {
200 let father_idx = father_info.father_value_id;
201 self.fetch_drop_from_alias(father_idx);
202 if self.drop_record[father_idx].is_dropped {
203 self.push_drop_top_down(father_idx, self.drop_record[father_idx].drop_spot);
204 rap_debug!("{:?}", self.drop_record[value_idx]);
205 break;
206 }
207 father = self.alias_graph.values[father_idx].father.clone();
208 }
209 }
210
211 pub fn fetch_drop_from_alias(&mut self, value_idx: usize) {
212 rap_debug!("fetch_drop_from_alias: value_idx = {}", value_idx);
213 if let Some(aliases) = self.alias_graph.get_alias_set(value_idx) {
214 for idx in aliases {
215 if self.drop_record[idx].is_dropped {
217 self.drop_record[value_idx] = self.drop_record[idx].clone();
218 self.drop_record[value_idx].value_index = value_idx;
219 self.drop_record[value_idx].prop_chain.push(value_idx);
220 }
221 }
222 }
223 }
224}