use crate::{
- error::{
- BlockIdxOutOfRange, BlockParamIdxOutOfRange, Error, InstIdxOutOfRange,
- OperandIdxOutOfRange, Result, SSAValIdxOutOfRange,
- },
+ error::{BlockParamIdxOutOfRange, Error, OperandIdxOutOfRange, Result},
index::{
- BlockIdx, BlockParamIdx, IndexTy, InstIdx, InstRange, OperandIdx, RangeIter, SSAValIdx,
+ BlockIdx, BlockParamIdx, Entries, InstIdx, InstRange, OperandIdx, SSAValIdx, TryIndex,
+ TryIndexMut,
},
interned::{GlobalState, Intern, Interned},
loc::{BaseTy, Loc, Ty},
use smallvec::SmallVec;
use std::{
collections::{btree_map, BTreeMap, BTreeSet},
- iter::FusedIterator,
mem,
- ops::{Index, IndexMut},
};
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
pub const fn prev(self) -> Self {
Self(self.0 - 1)
}
+ pub const fn as_usize(self) -> usize {
+ self.0
+ }
+ pub const fn from_usize(value: usize) -> Self {
+ Self(value)
+ }
}
impl fmt::Debug for ProgPoint {
}
}
-pub trait Entries<'a, I>: Index<I>
-where
- I: IndexTy,
- Self::Output: 'a,
-{
- type Iter: Iterator<Item = (I, &'a Self::Output)>
- + DoubleEndedIterator
- + ExactSizeIterator
- + FusedIterator;
- fn entries(&'a self) -> Self::Iter;
- fn keys(&'a self) -> RangeIter<I>;
-}
-
-pub trait EntriesMut<'a, I>: Entries<'a, I> + IndexMut<I>
-where
- I: IndexTy,
- Self::Output: 'a,
-{
- type IterMut: Iterator<Item = (I, &'a mut Self::Output)>
- + DoubleEndedIterator
- + ExactSizeIterator
- + FusedIterator;
- fn entries_mut(&'a mut self) -> Self::IterMut;
-}
-
-pub trait TryIndex<I>: for<'a> Entries<'a, I>
-where
- I: IndexTy,
-{
- type Error;
- fn try_index(&self, idx: I) -> Result<&Self::Output, Self::Error>;
-}
-
-pub trait TryIndexMut<I>: TryIndex<I> + for<'a> EntriesMut<'a, I>
-where
- I: IndexTy,
-{
- fn try_index_mut(&mut self, idx: I) -> Result<&mut Self::Output, Self::Error>;
-}
-
-macro_rules! impl_index {
- (
- #[error = $Error:ident, iter = $Iter:ident, iter_mut = $IterMut:ident]
- impl Index<$I:ty> for Vec<$T:ty> {}
- ) => {
- #[derive(Clone, Debug)]
- pub struct $Iter<'a> {
- iter: std::iter::Enumerate<std::slice::Iter<'a, $T>>,
- }
-
- impl<'a> Iterator for $Iter<'a> {
- type Item = ($I, &'a $T);
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next().map(|(i, v)| (<$I>::new(i), v))
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-
- fn fold<B, F>(self, init: B, mut f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter
- .fold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
- }
- }
-
- impl DoubleEndedIterator for $Iter<'_> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back().map(|(i, v)| (<$I>::new(i), v))
- }
-
- fn rfold<B, F>(self, init: B, mut f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter
- .rfold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
- }
- }
-
- impl ExactSizeIterator for $Iter<'_> {
- fn len(&self) -> usize {
- self.iter.len()
- }
- }
-
- impl FusedIterator for $Iter<'_> {}
-
- #[derive(Debug)]
- pub struct $IterMut<'a> {
- iter: std::iter::Enumerate<std::slice::IterMut<'a, $T>>,
- }
-
- impl<'a> Iterator for $IterMut<'a> {
- type Item = ($I, &'a mut $T);
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next().map(|(i, v)| (<$I>::new(i), v))
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-
- fn fold<B, F>(self, init: B, mut f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter
- .fold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
- }
- }
-
- impl DoubleEndedIterator for $IterMut<'_> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back().map(|(i, v)| (<$I>::new(i), v))
- }
-
- fn rfold<B, F>(self, init: B, mut f: F) -> B
- where
- F: FnMut(B, Self::Item) -> B,
- {
- self.iter
- .rfold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
- }
- }
-
- impl ExactSizeIterator for $IterMut<'_> {
- fn len(&self) -> usize {
- self.iter.len()
- }
- }
-
- impl FusedIterator for $IterMut<'_> {}
-
- impl Index<$I> for Vec<$T> {
- type Output = $T;
-
- fn index(&self, index: $I) -> &Self::Output {
- &self[index.get()]
- }
- }
-
- impl IndexMut<$I> for Vec<$T> {
- fn index_mut(&mut self, index: $I) -> &mut Self::Output {
- &mut self[index.get()]
- }
- }
-
- impl<'a> Entries<'a, $I> for Vec<$T> {
- type Iter = $Iter<'a>;
- fn entries(&'a self) -> Self::Iter {
- $Iter {
- iter: (**self).iter().enumerate(),
- }
- }
- fn keys(&'a self) -> RangeIter<$I> {
- RangeIter::from_usize_range(0..self.len())
- }
- }
-
- impl<'a> EntriesMut<'a, $I> for Vec<$T> {
- type IterMut = $IterMut<'a>;
- fn entries_mut(&'a mut self) -> Self::IterMut {
- $IterMut {
- iter: (**self).iter_mut().enumerate(),
- }
- }
- }
-
- impl TryIndex<$I> for Vec<$T> {
- type Error = $Error;
-
- fn try_index(&self, idx: $I) -> Result<&Self::Output, Self::Error> {
- self.get(idx.get()).ok_or($Error { idx })
- }
- }
-
- impl TryIndexMut<$I> for Vec<$T> {
- fn try_index_mut(&mut self, idx: $I) -> Result<&mut Self::Output, Self::Error> {
- self.get_mut(idx.get()).ok_or($Error { idx })
- }
- }
-
- impl Index<$I> for [$T] {
- type Output = $T;
-
- fn index(&self, index: $I) -> &Self::Output {
- &self[index.get()]
- }
- }
-
- impl IndexMut<$I> for [$T] {
- fn index_mut(&mut self, index: $I) -> &mut Self::Output {
- &mut self[index.get()]
- }
- }
-
- impl<'a> Entries<'a, $I> for [$T] {
- type Iter = $Iter<'a>;
- fn entries(&'a self) -> Self::Iter {
- $Iter {
- iter: self.iter().enumerate(),
- }
- }
- fn keys(&'a self) -> RangeIter<$I> {
- RangeIter::from_usize_range(0..self.len())
- }
- }
-
- impl<'a> EntriesMut<'a, $I> for [$T] {
- type IterMut = $IterMut<'a>;
- fn entries_mut(&'a mut self) -> Self::IterMut {
- $IterMut {
- iter: self.iter_mut().enumerate(),
- }
- }
- }
-
- impl TryIndex<$I> for [$T] {
- type Error = $Error;
-
- fn try_index(&self, idx: $I) -> Result<&Self::Output, Self::Error> {
- self.get(idx.get()).ok_or($Error { idx })
- }
- }
-
- impl TryIndexMut<$I> for [$T] {
- fn try_index_mut(&mut self, idx: $I) -> Result<&mut Self::Output, Self::Error> {
- self.get_mut(idx.get()).ok_or($Error { idx })
- }
- }
- };
-}
-
-impl_index! {
- #[error = SSAValIdxOutOfRange, iter = SSAValEntriesIter, iter_mut = SSAValEntriesIterMut]
- impl Index<SSAValIdx> for Vec<SSAVal> {}
-}
-
-impl_index! {
- #[error = BlockParamIdxOutOfRange, iter = BlockParamEntriesIter, iter_mut = BlockParamEntriesIterMut]
- impl Index<BlockParamIdx> for Vec<SSAValIdx> {}
-}
-
-impl_index! {
- #[error = OperandIdxOutOfRange, iter = OperandEntriesIter, iter_mut = OperandEntriesIterMut]
- impl Index<OperandIdx> for Vec<Operand> {}
-}
-
-impl_index! {
- #[error = InstIdxOutOfRange, iter = InstEntriesIter, iter_mut = InstEntriesIterMut]
- impl Index<InstIdx> for Vec<Inst> {}
-}
-
-impl_index! {
- #[error = BlockIdxOutOfRange, iter = BlockEntriesIter, iter_mut = BlockEntriesIterMut]
- impl Index<BlockIdx> for Vec<Block> {}
-}
-
impl GraphBase for FnFields {
type EdgeId = (BlockIdx, BlockIdx);
type NodeId = BlockIdx;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
-use std::{fmt, hash::Hash, iter::FusedIterator, ops::Range};
+use std::{
+ fmt,
+ hash::Hash,
+ iter::FusedIterator,
+ ops::{Index, IndexMut, Range},
+};
+
+use crate::{
+ error::{
+ BlockIdxOutOfRange, BlockParamIdxOutOfRange, InstIdxOutOfRange, OperandIdxOutOfRange,
+ SSAValIdxOutOfRange,
+ },
+ function::{Block, Inst, Operand, SSAVal},
+ live_range::LiveRange,
+};
pub trait DisplayOptionIdx {
type Type: fmt::Display;
impl fmt::Display for DisplayOptionIdxImpl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self.0 {
- Some(v) => v.fmt(f),
+ match &self.0 {
+ Some(v) => fmt::Display::fmt(v, f),
None => write!(f, "none"),
}
}
}
+
impl DisplayOptionIdx for Option<$name> {
type Type = DisplayOptionIdxImpl;
define_index!(BlockIdx);
define_index!(BlockParamIdx);
define_index!(OperandIdx);
+define_index!(LiveRangeIdx);
+
+pub trait Entries<'a, I>: Index<I>
+where
+ I: IndexTy,
+ Self::Output: 'a,
+{
+ type Iter: Iterator<Item = (I, &'a Self::Output)>
+ + DoubleEndedIterator
+ + ExactSizeIterator
+ + FusedIterator;
+ fn entries(&'a self) -> Self::Iter;
+ fn keys(&'a self) -> RangeIter<I>;
+}
+
+pub trait EntriesMut<'a, I>: Entries<'a, I> + IndexMut<I>
+where
+ I: IndexTy,
+ Self::Output: 'a,
+{
+ type IterMut: Iterator<Item = (I, &'a mut Self::Output)>
+ + DoubleEndedIterator
+ + ExactSizeIterator
+ + FusedIterator;
+ fn entries_mut(&'a mut self) -> Self::IterMut;
+}
+
+pub trait TryIndex<I>: for<'a> Entries<'a, I>
+where
+ I: IndexTy,
+{
+ type Error;
+ fn try_index(&self, idx: I) -> Result<&Self::Output, Self::Error>;
+}
+
+pub trait TryIndexMut<I>: TryIndex<I> + for<'a> EntriesMut<'a, I>
+where
+ I: IndexTy,
+{
+ fn try_index_mut(&mut self, idx: I) -> Result<&mut Self::Output, Self::Error>;
+}
+
+macro_rules! impl_index {
+ (
+ #[$(error = $Error:ident, )?iter = $Iter:ident, iter_mut = $IterMut:ident]
+ impl Index<$I:ty> for Vec<$T:ty> {}
+ ) => {
+ #[derive(Clone, Debug)]
+ pub struct $Iter<'a> {
+ iter: std::iter::Enumerate<std::slice::Iter<'a, $T>>,
+ }
+
+ impl<'a> Iterator for $Iter<'a> {
+ type Item = ($I, &'a $T);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .fold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl DoubleEndedIterator for $Iter<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn rfold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .rfold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl ExactSizeIterator for $Iter<'_> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+ }
+
+ impl FusedIterator for $Iter<'_> {}
+
+ #[derive(Debug)]
+ pub struct $IterMut<'a> {
+ iter: std::iter::Enumerate<std::slice::IterMut<'a, $T>>,
+ }
+
+ impl<'a> Iterator for $IterMut<'a> {
+ type Item = ($I, &'a mut $T);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .fold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl DoubleEndedIterator for $IterMut<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back().map(|(i, v)| (<$I>::new(i), v))
+ }
+
+ fn rfold<B, F>(self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iter
+ .rfold(init, move |a, (i, v)| f(a, (<$I>::new(i), v)))
+ }
+ }
+
+ impl ExactSizeIterator for $IterMut<'_> {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+ }
+
+ impl FusedIterator for $IterMut<'_> {}
+
+ impl Index<$I> for Vec<$T> {
+ type Output = $T;
+
+ fn index(&self, index: $I) -> &Self::Output {
+ &self[index.get()]
+ }
+ }
+
+ impl IndexMut<$I> for Vec<$T> {
+ fn index_mut(&mut self, index: $I) -> &mut Self::Output {
+ &mut self[index.get()]
+ }
+ }
+
+ impl<'a> Entries<'a, $I> for Vec<$T> {
+ type Iter = $Iter<'a>;
+ fn entries(&'a self) -> Self::Iter {
+ $Iter {
+ iter: (**self).iter().enumerate(),
+ }
+ }
+ fn keys(&'a self) -> RangeIter<$I> {
+ RangeIter::from_usize_range(0..self.len())
+ }
+ }
+
+ impl<'a> EntriesMut<'a, $I> for Vec<$T> {
+ type IterMut = $IterMut<'a>;
+ fn entries_mut(&'a mut self) -> Self::IterMut {
+ $IterMut {
+ iter: (**self).iter_mut().enumerate(),
+ }
+ }
+ }
+
+ $(
+ impl TryIndex<$I> for Vec<$T> {
+ type Error = $Error;
+
+ fn try_index(&self, idx: $I) -> Result<&Self::Output, Self::Error> {
+ self.get(idx.get()).ok_or($Error { idx })
+ }
+ }
+
+ impl TryIndexMut<$I> for Vec<$T> {
+ fn try_index_mut(&mut self, idx: $I) -> Result<&mut Self::Output, Self::Error> {
+ self.get_mut(idx.get()).ok_or($Error { idx })
+ }
+ }
+ )?
+
+ impl Index<$I> for [$T] {
+ type Output = $T;
+
+ fn index(&self, index: $I) -> &Self::Output {
+ &self[index.get()]
+ }
+ }
+
+ impl IndexMut<$I> for [$T] {
+ fn index_mut(&mut self, index: $I) -> &mut Self::Output {
+ &mut self[index.get()]
+ }
+ }
+
+ impl<'a> Entries<'a, $I> for [$T] {
+ type Iter = $Iter<'a>;
+ fn entries(&'a self) -> Self::Iter {
+ $Iter {
+ iter: self.iter().enumerate(),
+ }
+ }
+ fn keys(&'a self) -> RangeIter<$I> {
+ RangeIter::from_usize_range(0..self.len())
+ }
+ }
+
+ impl<'a> EntriesMut<'a, $I> for [$T] {
+ type IterMut = $IterMut<'a>;
+ fn entries_mut(&'a mut self) -> Self::IterMut {
+ $IterMut {
+ iter: self.iter_mut().enumerate(),
+ }
+ }
+ }
+
+ $(
+ impl TryIndex<$I> for [$T] {
+ type Error = $Error;
+
+ fn try_index(&self, idx: $I) -> Result<&Self::Output, Self::Error> {
+ self.get(idx.get()).ok_or($Error { idx })
+ }
+ }
+
+ impl TryIndexMut<$I> for [$T] {
+ fn try_index_mut(&mut self, idx: $I) -> Result<&mut Self::Output, Self::Error> {
+ self.get_mut(idx.get()).ok_or($Error { idx })
+ }
+ }
+ )?
+ };
+}
+
+impl_index! {
+ #[error = SSAValIdxOutOfRange, iter = SSAValEntriesIter, iter_mut = SSAValEntriesIterMut]
+ impl Index<SSAValIdx> for Vec<SSAVal> {}
+}
+
+impl_index! {
+ #[error = BlockParamIdxOutOfRange, iter = BlockParamEntriesIter, iter_mut = BlockParamEntriesIterMut]
+ impl Index<BlockParamIdx> for Vec<SSAValIdx> {}
+}
+
+impl_index! {
+ #[error = OperandIdxOutOfRange, iter = OperandEntriesIter, iter_mut = OperandEntriesIterMut]
+ impl Index<OperandIdx> for Vec<Operand> {}
+}
+
+impl_index! {
+ #[error = InstIdxOutOfRange, iter = InstEntriesIter, iter_mut = InstEntriesIterMut]
+ impl Index<InstIdx> for Vec<Inst> {}
+}
+
+impl_index! {
+ #[error = BlockIdxOutOfRange, iter = BlockEntriesIter, iter_mut = BlockEntriesIterMut]
+ impl Index<BlockIdx> for Vec<Block> {}
+}
+
+impl_index! {
+ #[iter = LiveRangeEntriesIter, iter_mut = LiveRangeEntriesIterMut]
+ impl Index<LiveRangeIdx> for Vec<LiveRange> {}
+}
impl fmt::Display for SSAValIdx {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
+impl fmt::Display for LiveRangeIdx {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "live_range{}", self.get())
+ }
+}
+
impl BlockIdx {
pub const ENTRY_BLOCK: BlockIdx = BlockIdx::new(0);
}
interners: Interners,
}
+impl fmt::Debug for GlobalState {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("GlobalState").finish_non_exhaustive()
+ }
+}
+
scoped_tls::scoped_thread_local!(static GLOBAL_STATE: Rc<GlobalState>);
impl GlobalState {
pub mod fuzzing;
pub mod index;
pub mod interned;
+pub mod live_range;
pub mod loc;
pub mod loc_set;
+pub mod state;
--- /dev/null
+use crate::{
+ function::ProgPoint,
+ index::{LiveRangeIdx, SSAValIdx},
+ loc::Loc,
+};
+use std::{cmp::Ordering, collections::BTreeSet, iter::FusedIterator, ops::Range};
+
+#[derive(Copy, Clone, Debug)]
+/// a Range<ProgPoint> except that any overlapping ranges compare equal
+pub struct ProgRange {
+ pub start: ProgPoint,
+ pub end: ProgPoint,
+}
+
+impl ProgRange {
+ pub const fn is_empty(self) -> bool {
+ self.len() == 0
+ }
+ pub const fn len(self) -> usize {
+ self.end.as_usize().saturating_sub(self.start.as_usize())
+ }
+ pub fn overlaps(self, other: Self) -> bool {
+ self.start < other.end && other.start < self.end
+ }
+ pub const fn as_usize_range(self) -> Range<usize> {
+ self.start.as_usize()..self.end.as_usize()
+ }
+ pub const fn from_usize_range(value: Range<usize>) -> Self {
+ Self {
+ start: ProgPoint::from_usize(value.start),
+ end: ProgPoint::from_usize(value.end),
+ }
+ }
+ pub fn with_self_as_usize_range<R, F: FnOnce(&mut Range<usize>) -> R>(&mut self, f: F) -> R {
+ let mut range = self.as_usize_range();
+ let retval = f(&mut range);
+ *self = Self::from_usize_range(range);
+ retval
+ }
+}
+
+impl Eq for ProgRange {}
+
+impl PartialEq for ProgRange {
+ fn eq(&self, other: &Self) -> bool {
+ self.cmp(other) == Ordering::Equal
+ }
+}
+
+impl PartialOrd for ProgRange {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for ProgRange {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if self.overlaps(*other) {
+ Ordering::Equal
+ } else {
+ (self.start, self.end).cmp(&(other.start, other.end))
+ }
+ }
+}
+
+impl IntoIterator for ProgRange {
+ type Item = ProgPoint;
+ type IntoIter = ProgRangeIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ ProgRangeIter { range: self }
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct ProgRangeIter {
+ pub range: ProgRange,
+}
+
+impl Iterator for ProgRangeIter {
+ type Item = ProgPoint;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.range
+ .with_self_as_usize_range(|range| range.next())
+ .map(ProgPoint::from_usize)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+
+ fn count(self) -> usize {
+ self.range.as_usize_range().count()
+ }
+
+ fn last(self) -> Option<Self::Item> {
+ self.range
+ .as_usize_range()
+ .last()
+ .map(ProgPoint::from_usize)
+ }
+
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ self.range
+ .with_self_as_usize_range(|range| range.nth(n))
+ .map(ProgPoint::from_usize)
+ }
+
+ fn fold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.range.with_self_as_usize_range(|range| {
+ range.fold(init, |a, b| f(a, ProgPoint::from_usize(b)))
+ })
+ }
+}
+
+impl DoubleEndedIterator for ProgRangeIter {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.range
+ .with_self_as_usize_range(|range| range.next_back())
+ .map(ProgPoint::from_usize)
+ }
+
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ self.range
+ .with_self_as_usize_range(|range| range.nth_back(n))
+ .map(ProgPoint::from_usize)
+ }
+
+ fn rfold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.range.with_self_as_usize_range(|range| {
+ range.rfold(init, |a, b| f(a, ProgPoint::from_usize(b)))
+ })
+ }
+}
+
+impl FusedIterator for ProgRangeIter {}
+
+impl ExactSizeIterator for ProgRangeIter {
+ fn len(&self) -> usize {
+ self.range.as_usize_range().len()
+ }
+}
+
+/// ensure Hash isn't implemented for ProgRange,
+/// since afaict there isn't a way to implement it consistently with Ord
+fn _check_prog_range_is_not_hashable() {
+ struct Hashable<const HASHABLE: bool>;
+ trait ProgRangeHashCheck: Sized {
+ fn _f(self) -> Hashable<false> {
+ Hashable
+ }
+ }
+ struct S<T>([T; 0]);
+ impl<T: std::hash::Hash> S<T> {
+ fn _f(self) -> Hashable<true> {
+ Hashable
+ }
+ }
+ impl<T> ProgRangeHashCheck for S<T> {}
+ let _: Hashable<false> = S::<ProgRange>([])._f();
+}
+
+#[derive(Clone, Debug)]
+pub struct LiveRange {
+ pub range: ProgRange,
+ pub ssa_val: SSAValIdx,
+}
+
+pub struct LiveRangeBundle {
+ pub live_ranges: BTreeSet<LiveRangeIdx>,
+ pub allocation: Option<Loc>,
+}
--- /dev/null
+use crate::{function::Function, interned::GlobalState, live_range::LiveRange};
+
+#[derive(Debug)]
+pub struct AllocatorState<'a> {
+ global_state: &'a GlobalState,
+ func: &'a Function,
+ live_ranges: Vec<LiveRange>,
+}