Skip to content

Commit c248af1

Browse files
committed
analyze: dataflow: internal implementation of updates_forbidden
1 parent 90ca19a commit c248af1

File tree

1 file changed

+46
-2
lines changed
  • c2rust-analyze/src/dataflow

1 file changed

+46
-2
lines changed

c2rust-analyze/src/dataflow/mod.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,27 +118,52 @@ impl DataflowConstraints {
118118
) -> PermissionSet {
119119
*val & !perms
120120
}
121+
122+
fn restrict_updates(
123+
&mut self,
124+
old: &PermissionSet,
125+
new: &PermissionSet,
126+
updates_forbidden: &PermissionSet,
127+
) -> PermissionSet {
128+
let (old, new, updates_forbidden) = (*old, *new, *updates_forbidden);
129+
(new & !updates_forbidden) | (old & updates_forbidden)
130+
}
121131
}
122132

123-
match self.propagate_inner(hypothesis, &mut PropagatePerms) {
133+
match self.propagate_inner(hypothesis, &mut PropagatePerms, None) {
124134
Ok(changed) => changed,
125135
Err(msg) => {
126136
panic!("{}", msg);
127137
}
128138
}
129139
}
130140

141+
/// Update `xs` by propagating dataflow information of type `T` according to the constraints
142+
/// recorded in `self`.
143+
///
144+
/// If `updates_forbidden` is provided, then the parts of `xs` indicated by `updates_forbidden`
145+
/// will not be modified. (Specifically, all updates will be filtered through the method
146+
/// `PropagateRules::restrict_updates`.)
131147
fn propagate_inner<T, R>(
132148
&self,
133149
xs: &mut PointerTableMut<T>,
134150
rules: &mut R,
151+
updates_forbidden: Option<&PointerTable<T>>,
135152
) -> Result<bool, String>
136153
where
137154
T: PartialEq,
138155
R: PropagateRules<T>,
139156
{
140157
let mut xs = TrackedPointerTable::new(xs.borrow_mut());
141158

159+
let restrict_updates = |rules: &mut R, ptr, old: &T, new: T| {
160+
if let Some(updates_forbidden) = updates_forbidden {
161+
rules.restrict_updates(old, &new, &updates_forbidden[ptr])
162+
} else {
163+
new
164+
}
165+
};
166+
142167
let mut changed = false;
143168
let mut i = 0;
144169
loop {
@@ -157,6 +182,8 @@ impl DataflowConstraints {
157182
let old_a = xs.get(a);
158183
let old_b = xs.get(b);
159184
let (new_a, new_b) = rules.subset(a, old_a, b, old_b);
185+
let new_a = restrict_updates(rules, a, old_a, new_a);
186+
let new_b = restrict_updates(rules, b, old_b, new_b);
160187
xs.set(a, new_a);
161188
xs.set(b, new_b);
162189
}
@@ -169,6 +196,8 @@ impl DataflowConstraints {
169196
let old_a = xs.get(a);
170197
let old_b = xs.get(b);
171198
let (new_a, new_b) = rules.subset_except(a, old_a, b, old_b, except);
199+
let new_a = restrict_updates(rules, a, old_a, new_a);
200+
let new_b = restrict_updates(rules, b, old_b, new_b);
172201
xs.set(a, new_a);
173202
xs.set(b, new_b);
174203
}
@@ -180,6 +209,7 @@ impl DataflowConstraints {
180209

181210
let old = xs.get(ptr);
182211
let new = rules.all_perms(ptr, perms, old);
212+
let new = restrict_updates(rules, ptr, old, new);
183213
xs.set(ptr, new);
184214
}
185215

@@ -190,6 +220,7 @@ impl DataflowConstraints {
190220

191221
let old = xs.get(ptr);
192222
let new = rules.no_perms(ptr, perms, old);
223+
let new = restrict_updates(rules, ptr, old, new);
193224
xs.set(ptr, new);
194225
}
195226
}
@@ -277,9 +308,19 @@ impl DataflowConstraints {
277308
) -> FlagSet {
278309
*val
279310
}
311+
312+
fn restrict_updates(
313+
&mut self,
314+
old: &FlagSet,
315+
new: &FlagSet,
316+
updates_forbidden: &FlagSet,
317+
) -> FlagSet {
318+
let (old, new, updates_forbidden) = (*old, *new, *updates_forbidden);
319+
(new & !updates_forbidden) | (old & updates_forbidden)
320+
}
280321
}
281322

282-
match self.propagate_inner(&mut flags, &mut Rules { perms }) {
323+
match self.propagate_inner(&mut flags, &mut Rules { perms }, None) {
283324
Ok(_changed) => {}
284325
Err(msg) => {
285326
panic!("{}", msg);
@@ -373,6 +414,9 @@ trait PropagateRules<T> {
373414
) -> (T, T);
374415
fn all_perms(&mut self, ptr: PointerId, perms: PermissionSet, val: &T) -> T;
375416
fn no_perms(&mut self, ptr: PointerId, perms: PermissionSet, val: &T) -> T;
417+
/// Apply a filter to restrict updates. The result is similar to `new`, but all flags marked
418+
/// in `updates_forbidden` are adjusted to match their `old` values.
419+
fn restrict_updates(&mut self, old: &T, new: &T, updates_forbidden: &T) -> T;
376420
}
377421

378422
pub fn generate_constraints<'tcx>(

0 commit comments

Comments
 (0)