Skip to main content

weir/
must_init.rs

1//! Must-init analysis: is variable `v` guaranteed initialized before
2//! `use`?
3//!
4//! Composes the dominator tree with the def site set: `v` is must-
5//! initialized at `use` iff every CFG path from entry to `use`
6//! crosses a definition of `v`. Encoded as: the def set must
7//! dominate the use.
8//!
9//! Output is a per-node bitset where bit `n` is set iff node `n`'s
10//! use of the queried variable is must-initialized.
11//!
12//! Soundness: [`Exact`](super::soundness::Soundness::Exact) when
13//! the supplied dominator tree is correct.
14
15use vyre::ir::Program;
16use vyre_primitives::bitset::and::bitset_and;
17use vyre_primitives::graph::csr_forward_traverse::bitset_words;
18
19pub(crate) const OP_ID: &str = "weir::must_init";
20
21/// Build a must-init Program. `def_dominates` is a host-supplied
22/// per-node bitset where bit `n` is set iff some def of the
23/// queried variable dominates node `n`. `use_set` is the per-node
24/// bitset of use sites. Output: bit `n` set iff `n` is in `use_set`
25/// AND in `def_dominates`.
26#[must_use]
27pub fn must_init(node_count: u32, def_dominates: &str, use_set: &str, out: &str) -> Program {
28    let words = bitset_words(node_count);
29    vyre_harness::region::tag_program(OP_ID, bitset_and(def_dominates, use_set, out, words))
30}
31
32/// reference oracle.
33#[must_use]
34#[cfg(any(test, feature = "cpu-parity"))]
35#[deprecated(
36    note = "reference oracle only; production code must dispatch the Weir Program on a concrete GPU backend or use weir::oracle for parity evidence"
37)]
38pub(crate) fn cpu_ref(def_dominates: &[u32], use_set: &[u32]) -> Vec<u32> {
39    vyre_primitives::bitset::and::cpu_ref(def_dominates, use_set)
40}
41
42/// Soundness marker for [`must_init`].
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub struct MustInit;
45impl super::soundness::SoundnessTagged for MustInit {
46    fn soundness(&self) -> super::soundness::Soundness {
47        super::soundness::Soundness::Exact
48    }
49}
50
51inventory::submit! {
52    vyre_harness::OpEntry::new(
53        OP_ID,
54        || must_init(4, "defs", "uses", "out"),
55        Some(|| {
56            let u32s = crate::dispatch_decode::pack_u32;
57            vec![vec![u32s(&[0b0111]), u32s(&[0b0010]), u32s(&[0])]]
58        }),
59        Some(|| {
60            let u32s = crate::dispatch_decode::pack_u32;
61            vec![vec![u32s(&[0b0010])]]
62        }),
63    )
64}
65
66#[cfg(test)]
67#[allow(deprecated)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn use_with_dominating_def_is_init() {
73        // use at bit 1, def dominates bits 0,1,2
74        assert_eq!(cpu_ref(&[0b0111], &[0b0010]), vec![0b0010]);
75    }
76
77    #[test]
78    fn use_without_dominating_def_is_uninit() {
79        assert_eq!(cpu_ref(&[0b0001], &[0b0010]), vec![0]);
80    }
81
82    #[test]
83    fn no_uses_yields_empty() {
84        assert_eq!(cpu_ref(&[0xFFFF_FFFF], &[0]), vec![0]);
85    }
86
87    #[test]
88    fn idempotent() {
89        let r1 = cpu_ref(&[0xF0F0], &[0x0FF0]);
90        let r2 = cpu_ref(&[0xF0F0], &[0x0FF0]);
91        assert_eq!(r1, r2);
92    }
93}