1 use serde::{Deserialize, Serialize};
2 use std::{fmt, iter::FusedIterator, ops::Range};
4 macro_rules! define_index {
7 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
15 pub const fn new(value: usize) -> Self {
18 pub const fn get(self) -> usize {
21 pub const fn next(self) -> Self {
23 value: self.value + 1,
26 pub const fn prev(self) -> Self {
28 value: self.value - 1,
35 define_index!(SSAValIdx);
36 define_index!(InstIdx);
37 define_index!(BlockIdx);
39 impl fmt::Display for SSAValIdx {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "v{}", self.get())
45 impl fmt::Display for InstIdx {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "inst{}", self.get())
51 impl fmt::Display for BlockIdx {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "blk{}", self.get())
58 pub const ENTRY_BLOCK: BlockIdx = BlockIdx::new(0);
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 {
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())
74 impl IntoIterator for InstRange {
76 type IntoIter = InstRangeIter;
77 fn into_iter(self) -> Self::IntoIter {
83 pub const fn iter(self) -> InstRangeIter {
84 InstRangeIter(self.start.get()..self.end.get())
86 pub const fn is_empty(self) -> bool {
87 self.start.get() >= self.end.get()
89 pub const fn first(self) -> Option<InstIdx> {
90 Some(const_try_opt!(self.split_first()).0)
92 pub const fn last(self) -> Option<InstIdx> {
93 Some(const_try_opt!(self.split_last()).0)
95 pub const fn split_first(self) -> Option<(InstIdx, InstRange)> {
102 start: self.start.next(),
108 pub const fn split_last(self) -> Option<(InstIdx, InstRange)> {
116 end: self.end.prev(),
121 pub const fn len(self) -> usize {
125 self.end.get() - self.start.get()
130 #[derive(Clone, Debug)]
131 pub struct InstRangeIter(Range<usize>);
134 pub const fn range(self) -> InstRange {
136 start: InstIdx::new(self.0.start),
137 end: InstIdx::new(self.0.end),
142 impl Iterator for InstRangeIter {
145 fn next(&mut self) -> Option<Self::Item> {
146 self.0.next().map(InstIdx::new)
149 fn size_hint(&self) -> (usize, Option<usize>) {
150 let v = self.0.len();
154 fn count(self) -> usize
161 fn last(self) -> Option<Self::Item>
165 self.0.last().map(InstIdx::new)
168 fn nth(&mut self, n: usize) -> Option<Self::Item> {
169 self.0.nth(n).map(InstIdx::new)
173 impl FusedIterator for InstRangeIter {}
175 impl DoubleEndedIterator for InstRangeIter {
176 fn next_back(&mut self) -> Option<Self::Item> {
177 self.0.next_back().map(InstIdx::new)
180 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
181 self.0.nth_back(n).map(InstIdx::new)
185 impl ExactSizeIterator for InstRangeIter {
186 fn len(&self) -> usize {