rapx/analysis/alias_analysis/mfp/
transfer.rs1use rustc_middle::mir::{Operand, Place, ProjectionElem};
3
4use super::intraproc::{AliasDomain, PlaceId, PlaceInfo};
5
6pub fn mir_place_to_place_id<'tcx>(place: Place<'tcx>) -> PlaceId {
8 let mut place_id = PlaceId::Local(place.local.as_usize());
9
10 for proj in place.projection {
12 match proj {
13 ProjectionElem::Field(field, _) => {
14 place_id = place_id.project_field(field.as_usize());
15 }
16 ProjectionElem::Deref => {
17 }
20 _ => {
21 }
23 }
24 }
25
26 place_id
27}
28
29pub fn operand_to_place_id<'tcx>(operand: &Operand<'tcx>) -> Option<PlaceId> {
31 match operand {
32 Operand::Copy(place) | Operand::Move(place) => Some(mir_place_to_place_id(*place)),
33 Operand::Constant(_) => None,
34 #[cfg(rapx_rustc_ge_196)]
35 Operand::RuntimeChecks(_) => None,
36 }
37}
38
39pub fn transfer_assign<'tcx>(
41 state: &mut AliasDomain,
42 lv: Place<'tcx>,
43 rv: &Operand<'tcx>,
44 place_info: &PlaceInfo<'tcx>,
45) {
46 let lv_id = mir_place_to_place_id(lv);
47
48 let lv_idx = match place_info.get_index(&lv_id) {
50 Some(idx) => idx,
51 None => return, };
53
54 if !place_info.may_drop(lv_idx) {
56 return;
57 }
58
59 state.remove_aliases_with_prefix(&lv_id, place_info);
61
62 if let Some(rv_id) = operand_to_place_id(rv) {
64 if let Some(rv_idx) = place_info.get_index(&rv_id) {
65 if place_info.may_drop(rv_idx) {
66 state.union(lv_idx, rv_idx);
67
68 sync_fields(state, &lv_id, &rv_id, place_info);
70 }
71 }
72 }
73}
74
75pub fn transfer_ref<'tcx>(
77 state: &mut AliasDomain,
78 lv: Place<'tcx>,
79 rv: Place<'tcx>,
80 place_info: &PlaceInfo<'tcx>,
81) {
82 let lv_id = mir_place_to_place_id(lv);
84 let rv_id = mir_place_to_place_id(rv);
85
86 let lv_idx = match place_info.get_index(&lv_id) {
87 Some(idx) => idx,
88 None => return,
89 };
90
91 let rv_idx = match place_info.get_index(&rv_id) {
92 Some(idx) => idx,
93 None => return,
94 };
95
96 if !place_info.may_drop(lv_idx) || !place_info.may_drop(rv_idx) {
97 return;
98 }
99
100 state.remove_aliases_with_prefix(&lv_id, place_info);
102
103 state.union(lv_idx, rv_idx);
105
106 sync_fields(state, &lv_id, &rv_id, place_info);
108}
109
110pub fn transfer_aggregate<'tcx>(
112 state: &mut AliasDomain,
113 lv: Place<'tcx>,
114 operands: &[Operand<'tcx>],
115 place_info: &PlaceInfo<'tcx>,
116) {
117 let lv_id = mir_place_to_place_id(lv);
118
119 state.remove_aliases_with_prefix(&lv_id, place_info);
121
122 for (field_idx, operand) in operands.iter().enumerate() {
124 if let Some(rv_id) = operand_to_place_id(operand) {
125 let lv_field_id = lv_id.project_field(field_idx);
126
127 if let Some(lv_field_idx) = place_info.get_index(&lv_field_id) {
128 if let Some(rv_idx) = place_info.get_index(&rv_id) {
129 if place_info.may_drop(lv_field_idx) && place_info.may_drop(rv_idx) {
130 state.union(lv_field_idx, rv_idx);
131
132 sync_fields(state, &lv_field_id, &rv_id, place_info);
134 }
135 }
136 }
137 }
138 }
139}
140
141pub fn transfer_call<'tcx>(
143 state: &mut AliasDomain,
144 ret: Place<'tcx>,
145 _args: &[Operand<'tcx>],
146 place_info: &PlaceInfo<'tcx>,
147) {
148 let ret_id = mir_place_to_place_id(ret);
149
150 state.remove_aliases_with_prefix(&ret_id, place_info);
152
153 }
157
158pub fn sync_fields<'tcx>(
161 state: &mut AliasDomain,
162 lv: &PlaceId,
163 rv: &PlaceId,
164 place_info: &PlaceInfo<'tcx>,
165) {
166 const MAX_SYNC_DEPTH: usize = 3;
168 sync_fields_recursive(state, lv, rv, place_info, 0, MAX_SYNC_DEPTH);
169}
170
171fn sync_fields_recursive<'tcx>(
173 state: &mut AliasDomain,
174 lv: &PlaceId,
175 rv: &PlaceId,
176 place_info: &PlaceInfo<'tcx>,
177 depth: usize,
178 max_depth: usize,
179) {
180 if depth >= max_depth {
181 return;
182 }
183
184 for field_idx in 0..16 {
187 let lv_field = lv.project_field(field_idx);
188 let rv_field = rv.project_field(field_idx);
189
190 if let (Some(lv_field_idx), Some(rv_field_idx)) = (
192 place_info.get_index(&lv_field),
193 place_info.get_index(&rv_field),
194 ) {
195 if place_info.may_drop(lv_field_idx) && place_info.may_drop(rv_field_idx) {
197 if state.union(lv_field_idx, rv_field_idx) {
198 sync_fields_recursive(
200 state,
201 &lv_field,
202 &rv_field,
203 place_info,
204 depth + 1,
205 max_depth,
206 );
207 }
208 }
209 } else {
210 break;
212 }
213 }
214}