Extract our own dominator tree from
(&self, func: Cow<Function>, context: &Context)
| 40 | |
| 41 | // Extract our own dominator tree from |
| 42 | fn run(&self, func: Cow<Function>, context: &Context) -> anyhow::Result<()> { |
| 43 | let func = func.borrow(); |
| 44 | let cfg = ControlFlowGraph::with_function(func); |
| 45 | let domtree = DominatorTree::with_function(func, &cfg); |
| 46 | |
| 47 | // Build an expected domtree from the source annotations. |
| 48 | let mut expected = HashMap::new(); |
| 49 | for comment in &context.details.comments { |
| 50 | if let Some(tail) = match_directive(comment.text, "dominates:") { |
| 51 | let inst = match comment.entity { |
| 52 | AnyEntity::Inst(inst) => inst, |
| 53 | _ => { |
| 54 | anyhow::bail!( |
| 55 | "annotation on non-inst {}: {}", |
| 56 | comment.entity, |
| 57 | comment.text |
| 58 | ); |
| 59 | } |
| 60 | }; |
| 61 | |
| 62 | let expected_block = match func.layout.inst_block(inst) { |
| 63 | Some(expected_block) => expected_block, |
| 64 | _ => anyhow::bail!("instruction {inst} is not in layout"), |
| 65 | }; |
| 66 | for src_block in tail.split_whitespace() { |
| 67 | let block = match context.details.map.lookup_str(src_block) { |
| 68 | Some(AnyEntity::Block(block)) => block, |
| 69 | _ => anyhow::bail!("expected defined block, got {src_block}"), |
| 70 | }; |
| 71 | |
| 72 | // Annotations say that `expected_block` is the idom of `block`. |
| 73 | if expected.insert(block, expected_block).is_some() { |
| 74 | anyhow::bail!("multiple dominators for {src_block}"); |
| 75 | } |
| 76 | |
| 77 | // Compare to computed domtree. |
| 78 | match domtree.idom(block) { |
| 79 | Some(got_block) if got_block != expected_block => { |
| 80 | anyhow::bail!( |
| 81 | "mismatching idoms for {src_block}:\n\ |
| 82 | want: {inst}, got: {got_block}" |
| 83 | ); |
| 84 | } |
| 85 | None => { |
| 86 | anyhow::bail!( |
| 87 | "mismatching idoms for {src_block}:\n\ |
| 88 | want: {inst}, got: unreachable" |
| 89 | ); |
| 90 | } |
| 91 | _ => {} |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | // Now we know that everything in `expected` is consistent with `domtree`. |
| 98 | // All other block's should be either unreachable or the entry block. |
| 99 | for block in func |
nothing calls this directly
no test coverage detected