Skip to main content

weir/reaching/
program.rs

1use super::OP_ID;
2use vyre::ir::Program;
3use vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse;
4use vyre_primitives::graph::program_graph::ProgramGraphShape;
5
6/// Build one CFG-forward propagation step for reaching-defs.
7///
8/// `frontier_in` reads the current `out[n]` bit-sets across all CFG
9/// nodes (flat; surge stdlib is responsible for laying it out as
10/// `n * defs_per_word` per node). `frontier_out` receives the
11/// propagated `in'[n]` after one CFG-edge traversal.
12///
13/// The `gen[n] ∪ (in[n] − kill[n])` transfer runs on the surge side
14/// as a pointwise pre-union step in the fixpoint driver  -  this keeps
15/// the vyre primitive a single traversal call (same shape as
16/// `flows_to`), which composes cleanly with
17/// `vyre_primitives::bitset` ops for the transfer.
18#[must_use]
19pub fn reaching_defs_step(
20    shape: ProgramGraphShape,
21    frontier_in: &str,
22    frontier_out: &str,
23) -> Program {
24    csr_forward_traverse(shape, frontier_in, frontier_out, 0xFFFF_FFFF)
25}
26
27inventory::submit! {
28    vyre_harness::OpEntry::new(
29        OP_ID,
30        || reaching_defs_step(ProgramGraphShape::new(4, 4), "fin", "fout"),
31        Some(|| {
32            let to_bytes = crate::dispatch_decode::pack_u32;
33            // Diamond CFG  -  four nodes with a join at node 3:
34            //   0 → 1 → 3
35            //   0 → 2 → 3
36            // Reaching-defs start at node 0 with def-set {0b0001}.
37            // After one forward step, def 0 has propagated to nodes 1
38            // and 2 after one propagation step; the join into 3 is reached by
39            // the next fixpoint iteration.
40            vec![vec![
41                to_bytes(&[0, 0, 0, 0]),          // pg_nodes
42                to_bytes(&[0, 2, 3, 4, 4]),       // pg_edge_offsets: 0→{1,2}, 1→{3}, 2→{3}, 3→{}
43                to_bytes(&[1, 2, 3, 3]),          // pg_edge_targets
44                to_bytes(&[1, 1, 1, 1]),          // pg_edge_kind_mask
45                to_bytes(&[0, 0, 0, 0]),          // pg_node_tags
46                to_bytes(&[0b0001]),              // fin = {def 0 at node 0}
47                to_bytes(&[0b0001]),              // fout seed = same
48            ]]
49        }),
50        Some(|| {
51            let to_bytes = crate::dispatch_decode::pack_u32;
52            // Diamond 0→{1,2}→3: one forward step from {0} reaches
53            // {0, 1, 2}. A no-op impl that returns the input would
54            // only produce {0} and fail.
55            vec![vec![to_bytes(&[0b0111])]]
56        }),
57    )
58}
59
60inventory::submit! {
61    vyre_harness::ConvergenceContract {
62        op_id: OP_ID,
63        max_iterations: 64,
64    }
65}
66
67/// Marker type for the reaching-definitions dataflow primitive.
68#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69pub struct ReachingDefs;
70
71impl crate::soundness::SoundnessTagged for ReachingDefs {
72    fn soundness(&self) -> crate::soundness::Soundness {
73        crate::soundness::Soundness::Exact
74    }
75}