(
func: &Function,
visited: &mut FxHashSet<Word>,
postorder: &mut Vec<Word>,
current: Word,
)
| 33 | return; |
| 34 | } |
| 35 | fn visit_postorder( |
| 36 | func: &Function, |
| 37 | visited: &mut FxHashSet<Word>, |
| 38 | postorder: &mut Vec<Word>, |
| 39 | current: Word, |
| 40 | ) { |
| 41 | if !visited.insert(current) { |
| 42 | return; |
| 43 | } |
| 44 | let current_block = func |
| 45 | .blocks |
| 46 | .iter() |
| 47 | .find(|b| b.label_id().unwrap() == current) |
| 48 | .unwrap(); |
| 49 | let mut edges = outgoing_edges(current_block).collect::<Vec<_>>(); |
| 50 | // HACK(eddyb) treat `OpSelectionMerge` as an edge, in case it points |
| 51 | // to an otherwise-unreachable block. |
| 52 | if let Some(before_last_idx) = current_block.instructions.len().checked_sub(2) { |
| 53 | if let Some(before_last) = current_block.instructions.get(before_last_idx) { |
| 54 | if before_last.class.opcode == Op::SelectionMerge { |
| 55 | edges.push(before_last.operands[0].unwrap_id_ref()); |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | // Reverse the order, so reverse-postorder keeps things tidy |
| 60 | for &outgoing in edges.iter().rev() { |
| 61 | visit_postorder(func, visited, postorder, outgoing); |
| 62 | } |
| 63 | postorder.push(current); |
| 64 | } |
| 65 | |
| 66 | let mut visited = FxHashSet::default(); |
| 67 | let mut postorder = Vec::new(); |
no test coverage detected