regalloc2/
index.rs

1#[macro_export]
2macro_rules! define_index {
3    ($ix:ident) => {
4        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
5        #[cfg_attr(
6            feature = "enable-serde",
7            derive(::serde::Serialize, ::serde::Deserialize)
8        )]
9        pub struct $ix(pub u32);
10        impl $ix {
11            #[inline(always)]
12            pub fn new(i: usize) -> Self {
13                Self(i as u32)
14            }
15            #[inline(always)]
16            pub fn index(self) -> usize {
17                debug_assert!(self.is_valid());
18                self.0 as usize
19            }
20            #[inline(always)]
21            pub fn invalid() -> Self {
22                Self(u32::MAX)
23            }
24            #[inline(always)]
25            pub fn is_invalid(self) -> bool {
26                self == Self::invalid()
27            }
28            #[inline(always)]
29            pub fn is_valid(self) -> bool {
30                self != Self::invalid()
31            }
32            #[inline(always)]
33            pub fn next(self) -> $ix {
34                debug_assert!(self.is_valid());
35                Self(self.0 + 1)
36            }
37            #[inline(always)]
38            pub fn prev(self) -> $ix {
39                debug_assert!(self.is_valid());
40                Self(self.0 - 1)
41            }
42
43            #[inline(always)]
44            pub fn raw_u32(self) -> u32 {
45                self.0
46            }
47        }
48
49        impl crate::index::ContainerIndex for $ix {}
50    };
51}
52
53pub trait ContainerIndex: Clone + Copy + std::fmt::Debug + PartialEq + Eq {}
54
55pub trait ContainerComparator {
56    type Ix: ContainerIndex;
57    fn compare(&self, a: Self::Ix, b: Self::Ix) -> std::cmp::Ordering;
58}
59
60define_index!(Inst);
61define_index!(Block);
62
63#[derive(Clone, Copy, Debug)]
64pub struct InstRange(Inst, Inst, bool);
65
66impl InstRange {
67    #[inline(always)]
68    pub fn forward(from: Inst, to: Inst) -> Self {
69        debug_assert!(from.index() <= to.index());
70        InstRange(from, to, true)
71    }
72
73    #[inline(always)]
74    pub fn backward(from: Inst, to: Inst) -> Self {
75        debug_assert!(from.index() >= to.index());
76        InstRange(to, from, false)
77    }
78
79    #[inline(always)]
80    pub fn first(self) -> Inst {
81        debug_assert!(self.len() > 0);
82        if self.is_forward() {
83            self.0
84        } else {
85            self.1.prev()
86        }
87    }
88
89    #[inline(always)]
90    pub fn last(self) -> Inst {
91        debug_assert!(self.len() > 0);
92        if self.is_forward() {
93            self.1.prev()
94        } else {
95            self.0
96        }
97    }
98
99    #[inline(always)]
100    pub fn rest(self) -> InstRange {
101        debug_assert!(self.len() > 0);
102        if self.is_forward() {
103            InstRange::forward(self.0.next(), self.1)
104        } else {
105            InstRange::backward(self.1.prev(), self.0)
106        }
107    }
108
109    #[inline(always)]
110    pub fn len(self) -> usize {
111        self.1.index() - self.0.index()
112    }
113
114    #[inline(always)]
115    pub fn is_forward(self) -> bool {
116        self.2
117    }
118
119    #[inline(always)]
120    pub fn rev(self) -> Self {
121        Self(self.0, self.1, !self.2)
122    }
123
124    #[inline(always)]
125    pub fn iter(self) -> InstRangeIter {
126        InstRangeIter(self)
127    }
128}
129
130#[derive(Clone, Copy, Debug)]
131pub struct InstRangeIter(InstRange);
132
133impl Iterator for InstRangeIter {
134    type Item = Inst;
135    #[inline(always)]
136    fn next(&mut self) -> Option<Inst> {
137        if self.0.len() == 0 {
138            None
139        } else {
140            let ret = self.0.first();
141            self.0 = self.0.rest();
142            Some(ret)
143        }
144    }
145}
146
147#[cfg(test)]
148mod test {
149    use super::*;
150
151    #[test]
152    fn test_inst_range() {
153        let range = InstRange::forward(Inst::new(0), Inst::new(0));
154        debug_assert_eq!(range.len(), 0);
155
156        let range = InstRange::forward(Inst::new(0), Inst::new(5));
157        debug_assert_eq!(range.first().index(), 0);
158        debug_assert_eq!(range.last().index(), 4);
159        debug_assert_eq!(range.len(), 5);
160        debug_assert_eq!(
161            range.iter().collect::<Vec<_>>(),
162            vec![
163                Inst::new(0),
164                Inst::new(1),
165                Inst::new(2),
166                Inst::new(3),
167                Inst::new(4)
168            ]
169        );
170        let range = range.rev();
171        debug_assert_eq!(range.first().index(), 4);
172        debug_assert_eq!(range.last().index(), 0);
173        debug_assert_eq!(range.len(), 5);
174        debug_assert_eq!(
175            range.iter().collect::<Vec<_>>(),
176            vec![
177                Inst::new(4),
178                Inst::new(3),
179                Inst::new(2),
180                Inst::new(1),
181                Inst::new(0)
182            ]
183        );
184    }
185}