working on code
[bigint-presentation-code.git] / register_allocator / src / index.rs
1 use serde::{Deserialize, Serialize};
2 use std::{fmt, iter::FusedIterator, ops::Range};
3
4 macro_rules! define_index {
5 ($name:ident) => {
6 #[derive(
7 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
8 )]
9 #[serde(transparent)]
10 pub struct $name {
11 value: usize,
12 }
13
14 impl $name {
15 pub const fn new(value: usize) -> Self {
16 Self { value }
17 }
18 pub const fn get(self) -> usize {
19 self.value
20 }
21 pub const fn next(self) -> Self {
22 Self {
23 value: self.value + 1,
24 }
25 }
26 pub const fn prev(self) -> Self {
27 Self {
28 value: self.value - 1,
29 }
30 }
31 }
32 };
33 }
34
35 define_index!(SSAValIdx);
36 define_index!(InstIdx);
37 define_index!(BlockIdx);
38
39 impl fmt::Display for SSAValIdx {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "v{}", self.get())
42 }
43 }
44
45 impl fmt::Display for InstIdx {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "inst{}", self.get())
48 }
49 }
50
51 impl fmt::Display for BlockIdx {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "blk{}", self.get())
54 }
55 }
56
57 impl BlockIdx {
58 pub const ENTRY_BLOCK: BlockIdx = BlockIdx::new(0);
59 }
60
61 /// range of instruction indexes from `start` inclusive to `end` exclusive.
62 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
63 pub struct InstRange {
64 pub start: InstIdx,
65 pub end: InstIdx,
66 }
67
68 impl fmt::Display for InstRange {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "inst{}..{}", self.start.get(), self.end.get())
71 }
72 }
73
74 impl IntoIterator for InstRange {
75 type Item = InstIdx;
76 type IntoIter = InstRangeIter;
77 fn into_iter(self) -> Self::IntoIter {
78 self.iter()
79 }
80 }
81
82 impl InstRange {
83 pub const fn iter(self) -> InstRangeIter {
84 InstRangeIter(self.start.get()..self.end.get())
85 }
86 pub const fn is_empty(self) -> bool {
87 self.start.get() >= self.end.get()
88 }
89 pub const fn first(self) -> Option<InstIdx> {
90 Some(const_try_opt!(self.split_first()).0)
91 }
92 pub const fn last(self) -> Option<InstIdx> {
93 Some(const_try_opt!(self.split_last()).0)
94 }
95 pub const fn split_first(self) -> Option<(InstIdx, InstRange)> {
96 if self.is_empty() {
97 None
98 } else {
99 Some((
100 self.start,
101 Self {
102 start: self.start.next(),
103 end: self.end,
104 },
105 ))
106 }
107 }
108 pub const fn split_last(self) -> Option<(InstIdx, InstRange)> {
109 if self.is_empty() {
110 None
111 } else {
112 Some((
113 self.end.prev(),
114 Self {
115 start: self.start,
116 end: self.end.prev(),
117 },
118 ))
119 }
120 }
121 pub const fn len(self) -> usize {
122 if self.is_empty() {
123 0
124 } else {
125 self.end.get() - self.start.get()
126 }
127 }
128 }
129
130 #[derive(Clone, Debug)]
131 pub struct InstRangeIter(Range<usize>);
132
133 impl InstRangeIter {
134 pub const fn range(self) -> InstRange {
135 InstRange {
136 start: InstIdx::new(self.0.start),
137 end: InstIdx::new(self.0.end),
138 }
139 }
140 }
141
142 impl Iterator for InstRangeIter {
143 type Item = InstIdx;
144
145 fn next(&mut self) -> Option<Self::Item> {
146 self.0.next().map(InstIdx::new)
147 }
148
149 fn size_hint(&self) -> (usize, Option<usize>) {
150 let v = self.0.len();
151 (v, Some(v))
152 }
153
154 fn count(self) -> usize
155 where
156 Self: Sized,
157 {
158 self.len()
159 }
160
161 fn last(self) -> Option<Self::Item>
162 where
163 Self: Sized,
164 {
165 self.0.last().map(InstIdx::new)
166 }
167
168 fn nth(&mut self, n: usize) -> Option<Self::Item> {
169 self.0.nth(n).map(InstIdx::new)
170 }
171 }
172
173 impl FusedIterator for InstRangeIter {}
174
175 impl DoubleEndedIterator for InstRangeIter {
176 fn next_back(&mut self) -> Option<Self::Item> {
177 self.0.next_back().map(InstIdx::new)
178 }
179
180 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
181 self.0.nth_back(n).map(InstIdx::new)
182 }
183 }
184
185 impl ExactSizeIterator for InstRangeIter {
186 fn len(&self) -> usize {
187 self.0.len()
188 }
189 }