Collect variables that may be changed during the loop execution. The input to this function should include all the sub loops that constitute a fat-loop. This function will return two sets of variables that represents, respectively, - the set of values to be havoc-ed, and - the set of mutations to he havoc-ed and how they should be havoc-ed.
(
cfg: &StacklessControlFlowGraph,
func_target: &FunctionTarget<'_>,
sub_loops: &[NaturalLoop<BlockId>],
)
| 375 | /// - the set of values to be havoc-ed, and |
| 376 | /// - the set of mutations to he havoc-ed and how they should be havoc-ed. |
| 377 | fn collect_loop_targets( |
| 378 | cfg: &StacklessControlFlowGraph, |
| 379 | func_target: &FunctionTarget<'_>, |
| 380 | sub_loops: &[NaturalLoop<BlockId>], |
| 381 | ) -> (BTreeSet<TempIndex>, BTreeMap<TempIndex, bool>) { |
| 382 | let code = func_target.get_bytecode(); |
| 383 | let mut val_targets = BTreeSet::new(); |
| 384 | let mut mut_targets = BTreeMap::new(); |
| 385 | let fat_loop_body: BTreeSet<_> = sub_loops |
| 386 | .iter() |
| 387 | .map(|l| l.loop_body.iter()) |
| 388 | .flatten() |
| 389 | .copied() |
| 390 | .collect(); |
| 391 | for block_id in fat_loop_body { |
| 392 | for code_offset in cfg |
| 393 | .instr_indexes(block_id) |
| 394 | .expect("A loop body should never contain a dummy block") |
| 395 | { |
| 396 | let bytecode = &code[code_offset as usize]; |
| 397 | let (bc_val_targets, bc_mut_targets) = bytecode.modifies(func_target); |
| 398 | val_targets.extend(bc_val_targets); |
| 399 | for (idx, is_full_havoc) in bc_mut_targets { |
| 400 | mut_targets |
| 401 | .entry(idx) |
| 402 | .and_modify(|v| { |
| 403 | *v = *v || is_full_havoc; |
| 404 | }) |
| 405 | .or_insert(is_full_havoc); |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | (val_targets, mut_targets) |
| 410 | } |
| 411 | |
| 412 | /// Collect code offsets that are branch instructions forming loop back-edges |
| 413 | /// |
nothing calls this directly
no test coverage detected