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