Skip to main content

wave_compiler/mir/
value.rs

1// Copyright 2026 Ojima Abraham
2// SPDX-License-Identifier: Apache-2.0
3
4//! SSA value identifiers for MIR.
5//!
6//! Values in MIR are in Static Single Assignment form. Each value is
7//! assigned exactly once and identified by a unique `ValueId`.
8
9/// Unique identifier for an SSA value (virtual register).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
11pub struct ValueId(pub u32);
12
13impl ValueId {
14    /// Returns the raw numeric ID.
15    #[must_use]
16    pub fn index(self) -> u32 {
17        self.0
18    }
19}
20
21impl std::fmt::Display for ValueId {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        write!(f, "%{}", self.0)
24    }
25}
26
27/// Unique identifier for a basic block.
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
29pub struct BlockId(pub u32);
30
31impl BlockId {
32    /// Returns the raw numeric ID.
33    #[must_use]
34    pub fn index(self) -> u32 {
35        self.0
36    }
37}
38
39impl std::fmt::Display for BlockId {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        write!(f, "bb{}", self.0)
42    }
43}
44
45/// Generator for unique value and block IDs.
46pub struct IdGenerator {
47    next_value: u32,
48    next_block: u32,
49}
50
51impl IdGenerator {
52    /// Create a new ID generator.
53    #[must_use]
54    pub fn new() -> Self {
55        Self {
56            next_value: 0,
57            next_block: 0,
58        }
59    }
60
61    /// Generate a fresh value ID.
62    pub fn next_value(&mut self) -> ValueId {
63        let id = ValueId(self.next_value);
64        self.next_value += 1;
65        id
66    }
67
68    /// Generate a fresh block ID.
69    pub fn next_block(&mut self) -> BlockId {
70        let id = BlockId(self.next_block);
71        self.next_block += 1;
72        id
73    }
74
75    /// Returns the count of values generated so far.
76    #[must_use]
77    pub fn value_count(&self) -> u32 {
78        self.next_value
79    }
80}
81
82impl Default for IdGenerator {
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_id_generator_values() {
94        let mut gen = IdGenerator::new();
95        let v0 = gen.next_value();
96        let v1 = gen.next_value();
97        assert_eq!(v0, ValueId(0));
98        assert_eq!(v1, ValueId(1));
99        assert_eq!(gen.value_count(), 2);
100    }
101
102    #[test]
103    fn test_id_generator_blocks() {
104        let mut gen = IdGenerator::new();
105        let b0 = gen.next_block();
106        let b1 = gen.next_block();
107        assert_eq!(b0, BlockId(0));
108        assert_eq!(b1, BlockId(1));
109    }
110
111    #[test]
112    fn test_display() {
113        assert_eq!(format!("{}", ValueId(5)), "%5");
114        assert_eq!(format!("{}", BlockId(3)), "bb3");
115    }
116}