1use super::graph::*;
2use rustc_middle::mir::SourceInfo;
3use std::usize;
4
5#[derive(Debug, Copy, Clone)]
6pub struct LocalSpot {
7 pub bb: Option<usize>,
8 pub local: Option<usize>,
9}
10
11impl LocalSpot {
12 pub fn new(bb: usize, local: usize) -> Self {
13 LocalSpot {
14 bb: Some(bb),
15 local: Some(local),
16 }
17 }
18 pub fn from_local(local: usize) -> Self {
19 LocalSpot {
20 bb: None,
21 local: Some(local),
22 }
23 }
24 pub fn default() -> Self {
25 LocalSpot {
26 bb: None,
27 local: None,
28 }
29 }
30}
31
32#[derive(Debug, Clone)]
33pub struct DropRecord {
34 pub value_index: usize,
35 pub is_dropped: bool,
36 pub drop_spot: LocalSpot,
37 pub prop_chain: Vec<usize>,
38 pub has_dropped_field: bool,
39}
40
41impl DropRecord {
42 pub fn new(value_index: usize, is_dropped: bool, drop_spot: LocalSpot) -> Self {
43 DropRecord {
44 value_index,
45 is_dropped,
46 drop_spot,
47 prop_chain: Vec::new(),
48 has_dropped_field: false,
49 }
50 }
51 pub fn false_record(value_index: usize) -> Self {
52 DropRecord {
53 value_index,
54 is_dropped: false,
55 drop_spot: LocalSpot::default(),
56 prop_chain: Vec::new(),
57 has_dropped_field: false,
58 }
59 }
60 pub fn from(value_index: usize, record: &DropRecord) -> Self {
61 DropRecord {
62 value_index,
63 is_dropped: record.is_dropped,
64 drop_spot: record.drop_spot.clone(),
65 prop_chain: record.prop_chain.clone(),
66 has_dropped_field: record.has_dropped_field,
67 }
68 }
69 pub fn clear(&mut self) {
70 self.is_dropped = false;
71 self.drop_spot = LocalSpot::default();
72 self.prop_chain.clear();
73 self.has_dropped_field = false;
74 }
75}
76
77impl<'tcx> SafeDropGraph<'tcx> {
78 pub fn add_to_drop_record(
83 &mut self,
84 value_idx: usize, bb_idx: usize, _info: &SourceInfo,
87 flag_cleanup: bool,
88 ) {
89 rap_debug!(
90 "add_to_drop_record: value_idx = {}, bb_idx = {}",
91 value_idx,
92 bb_idx
93 );
94 if self.mop_graph.values[value_idx].is_ref_count() {
96 return;
97 }
98 if self.df_check(value_idx, bb_idx, self.mop_graph.span, flag_cleanup) {
99 return;
100 }
101 if !self.drop_record[value_idx].is_dropped {
102 let drop_spot = LocalSpot::new(bb_idx, self.mop_graph.values[value_idx].local);
103 self.drop_record[value_idx] = DropRecord::new(value_idx, true, drop_spot);
104 rap_debug!("{:?}", self.drop_record[value_idx]);
105 self.push_drop_info(value_idx, drop_spot);
106 }
107 }
108
109 pub fn push_drop_info(&mut self, value_idx: usize, drop_spot: LocalSpot) {
110 self.push_drop_bottom_up(value_idx, drop_spot);
111 self.push_drop_top_down(value_idx, drop_spot);
112 }
114
115 pub fn push_drop_alias(&mut self, value_idx: usize, drop_spot: LocalSpot) {
116 rap_debug!("push_drop_alias: value_idx = {}", value_idx,);
117 if let Some(aliases) = self.mop_graph.get_alias_set(value_idx) {
118 for i in aliases {
119 if i != value_idx {
120 self.drop_record[i] = DropRecord::new(i, true, drop_spot);
121 self.drop_record[i].prop_chain = self.drop_record[value_idx].prop_chain.clone();
122 self.drop_record[i].prop_chain.push(i);
123 rap_debug!("{:?}", self.drop_record[i]);
124 }
125 }
126 }
127 }
128
129 pub fn push_drop_top_down(&mut self, value_idx: usize, drop_spot: LocalSpot) {
131 rap_debug!("push_drop_top_down: value_idx = {}", value_idx);
132 let mut prop_chain = vec![value_idx];
133 for (_field_id, field_value_id) in self.mop_graph.values[value_idx].fields.clone() {
134 self.drop_record[field_value_id] = DropRecord::new(field_value_id, true, drop_spot);
135 prop_chain.push(field_value_id);
136 self.drop_record[field_value_id].prop_chain = prop_chain.clone();
137 rap_debug!("{:?}", self.drop_record[field_value_id]);
138 self.push_drop_top_down(field_value_id, drop_spot);
139 }
140 }
141
142 pub fn push_drop_bottom_up(&mut self, value_idx: usize, drop_spot: LocalSpot) {
143 rap_debug!("push_drop_bottom_up: value_idx = {}", value_idx);
144 let mut father = self.mop_graph.values[value_idx].father.clone();
145 let mut prop_chain = vec![value_idx];
146 while let Some(father_info) = father {
147 let father_idx = father_info.father_value_id;
148 self.drop_record[father_idx].has_dropped_field = true;
149 if !self.drop_record[father_idx].is_dropped {
150 prop_chain.push(father_idx);
151 self.drop_record[father_idx].prop_chain = prop_chain.clone();
152 self.drop_record[father_idx].drop_spot = drop_spot;
153 }
154 rap_debug!("{:?}", self.drop_record[father_idx]);
155 father = self.mop_graph.values[father_idx].father.clone();
156 }
157 }
158
159 pub fn fetch_drop_info(&mut self, value_idx: usize) {
160 self.fetch_drop_from_bottom(value_idx);
161 self.fetch_drop_from_top(value_idx);
162 self.fetch_drop_from_alias(value_idx);
163 }
164
165 pub fn clear_drop_info(&mut self, value_idx: usize) {
166 rap_debug!("clear_drop: value_idx = {}", value_idx);
167 self.drop_record[value_idx].clear();
168 self.clear_field_drop(value_idx);
169 self.clear_father_drop(value_idx);
170 }
171
172 pub fn clear_father_drop(&mut self, value_idx: usize) {
173 rap_debug!("clear_drop_father: value_idx = {}", value_idx);
174 let mut father = self.mop_graph.values[value_idx].father.clone();
176 while let Some(father_info) = father {
177 let father_idx = father_info.father_value_id;
178 if !self.drop_record[father_idx].is_dropped {
179 self.drop_record[father_idx].clear();
180 }
181 father = self.mop_graph.values[father_idx].father.clone();
182 }
183 }
184
185 pub fn clear_field_drop(&mut self, value_idx: usize) {
186 rap_debug!("clear_field_drop: value_idx = {}", value_idx);
187 for (_field_id, field_value_id) in self.mop_graph.values[value_idx].fields.clone() {
188 self.drop_record[field_value_id].clear();
189 self.clear_field_drop(field_value_id);
190 }
191 }
192
193 pub fn fetch_drop_from_bottom(&mut self, value_idx: usize) {
194 rap_debug!("fetch_drop_from_bottom: value_idx = {}", value_idx);
195 for (_field_id, field_value_id) in self.mop_graph.values[value_idx].fields.clone() {
196 rap_debug!("{:?}", self.drop_record[field_value_id]);
197 self.fetch_drop_from_alias(field_value_id);
198 if self.drop_record[field_value_id].is_dropped {
199 self.push_drop_bottom_up(
200 field_value_id,
201 self.drop_record[field_value_id].drop_spot,
202 );
203 rap_debug!("{:?}", self.drop_record[value_idx]);
204 break;
205 }
206 self.fetch_drop_from_bottom(field_value_id);
207 }
208 }
209
210 pub fn fetch_drop_from_top(&mut self, value_idx: usize) {
211 rap_debug!("fetch_drop_from_top: value_idx = {}", value_idx);
212 let mut father = self.mop_graph.values[value_idx].father.clone();
213 while let Some(father_info) = father {
214 let father_idx = father_info.father_value_id;
215 self.fetch_drop_from_alias(father_idx);
216 if self.drop_record[father_idx].is_dropped {
217 self.push_drop_top_down(father_idx, self.drop_record[father_idx].drop_spot);
218 rap_debug!("{:?}", self.drop_record[value_idx]);
219 break;
220 }
221 father = self.mop_graph.values[father_idx].father.clone();
222 }
223 }
224
225 pub fn fetch_drop_from_alias(&mut self, value_idx: usize) {
226 rap_debug!("fetch_drop_from_alias: value_idx = {}", value_idx);
227 if let Some(aliases) = self.mop_graph.get_alias_set(value_idx) {
228 for idx in aliases {
229 if self.drop_record[idx].is_dropped {
231 self.drop_record[value_idx] = self.drop_record[idx].clone();
232 self.drop_record[value_idx].value_index = value_idx;
233 self.drop_record[value_idx].prop_chain.push(value_idx);
234 }
235 }
236 }
237 }
238}