weir/test_harness/
dominator_fixture.rs1use std::collections::{HashMap, HashSet};
4
5use rand::{Rng, SeedableRng};
6
7use crate::ssa::{try_compute_dominators, Block, Cfg};
8
9#[derive(Clone, Debug)]
10pub struct CfgFixture {
11 pub node_count: u32,
12 pub entry: u32,
13 pub preds: Vec<Vec<u32>>,
14 pub succs: Vec<Vec<u32>>,
15 pub idoms: HashMap<u32, u32>,
16}
17
18pub struct DominatorFixture;
19
20impl DominatorFixture {
21 pub fn random_dag(node_count: u32, edge_probability: f64, seed: u64) -> CfgFixture {
22 if node_count == 0 {
23 return empty_fixture();
24 }
25 let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
26 let probability = edge_probability.clamp(0.0, 1.0);
27 let mut succs = vec![Vec::new(); node_count as usize];
28
29 for dst in 1..node_count {
30 let parent = rng.random_range(0..dst);
31 succs[parent as usize].push(dst);
32 }
33 for src in 0..node_count {
34 for dst in (src + 1)..node_count {
35 if rng.random::<f64>() < probability {
36 succs[src as usize].push(dst);
37 }
38 }
39 }
40 normalize_fixture(node_count, 0, succs)
41 }
42
43 pub fn random_irreducible(node_count: u32, edge_probability: f64, seed: u64) -> CfgFixture {
44 let mut fixture = Self::random_dag(node_count, edge_probability, seed);
45 if node_count > 1 {
46 fixture.succs[(node_count - 1) as usize].push(0);
47 if node_count > 2 {
48 fixture.succs[(node_count - 1) as usize].push(1);
49 fixture.succs[1].push(node_count - 1);
50 }
51 fixture = normalize_fixture(node_count, 0, fixture.succs);
52 }
53 fixture
54 }
55}
56
57fn empty_fixture() -> CfgFixture {
58 CfgFixture {
59 node_count: 0,
60 entry: 0,
61 preds: Vec::new(),
62 succs: Vec::new(),
63 idoms: HashMap::new(),
64 }
65}
66
67fn normalize_fixture(node_count: u32, entry: u32, mut succs: Vec<Vec<u32>>) -> CfgFixture {
68 for targets in &mut succs {
69 targets.retain(|target| *target < node_count);
70 targets.sort_unstable();
71 targets.dedup();
72 }
73
74 let mut preds = vec![Vec::new(); node_count as usize];
75 for (src, targets) in succs.iter().enumerate() {
76 for &dst in targets {
77 preds[dst as usize].push(src as u32);
78 }
79 }
80 for sources in &mut preds {
81 sources.sort_unstable();
82 sources.dedup();
83 }
84
85 let cfg = cfg_from_parts(entry, &preds, &succs);
86 let idoms = try_compute_dominators(&cfg).unwrap_or_default();
87 CfgFixture {
88 node_count,
89 entry,
90 preds,
91 succs,
92 idoms,
93 }
94}
95
96fn cfg_from_parts(entry: u32, preds: &[Vec<u32>], succs: &[Vec<u32>]) -> Cfg {
97 let mut blocks = HashMap::with_capacity(succs.len());
98 for id in 0..succs.len() as u32 {
99 blocks.insert(
100 id,
101 Block {
102 id,
103 preds: preds[id as usize].clone(),
104 succs: succs[id as usize].clone(),
105 defs: HashSet::new(),
106 uses: HashSet::new(),
107 },
108 );
109 }
110 Cfg { entry, blocks }
111}