wip
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 9 Feb 2023 01:09:51 +0000 (17:09 -0800)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 9 Feb 2023 01:09:51 +0000 (17:09 -0800)
register_allocator/src/function.rs
register_allocator/src/index.rs
register_allocator/src/interned.rs
register_allocator/src/lib.rs
register_allocator/src/live_range.rs [new file with mode: 0644]
register_allocator/src/state.rs [new file with mode: 0644]

index 02419e538731560f8aea5a82465f7a0a2471d6e2..24b73c0ff6370db0a47be5f51ae6c4d871cb1c5e 100644 (file)
@@ -1,10 +1,8 @@
 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},
@@ -23,9 +21,7 @@ use serde::{Deserialize, Serialize};
 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)]
@@ -182,6 +178,12 @@ impl ProgPoint {
     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 {
@@ -1031,270 +1033,6 @@ impl FnFields {
     }
 }
 
-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;
index a235f4fcf16d74526459742f545aaba1a9024c78..bcfd26ede5e15e052943292bdeb574fc29064236 100644 (file)
@@ -1,5 +1,19 @@
 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;
@@ -135,12 +149,13 @@ macro_rules! define_index {
 
             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;
 
@@ -157,6 +172,280 @@ define_index!(InstIdx);
 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 {
@@ -188,6 +477,12 @@ impl fmt::Display for OperandIdx {
     }
 }
 
+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);
 }
index 2eb61d75aa1998131d921d7b43ff811136d048d7..ce58c0b1404a69ce77d53d456923b75cb002cf62 100644 (file)
@@ -215,6 +215,12 @@ pub struct GlobalState {
     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 {
index c3595628ac29c65f05943c7ebc6ca702b45ef0cc..6131f8bf60a6975149a45667751efab9698c5e18 100644 (file)
@@ -5,5 +5,7 @@ pub mod function;
 pub mod fuzzing;
 pub mod index;
 pub mod interned;
+pub mod live_range;
 pub mod loc;
 pub mod loc_set;
+pub mod state;
diff --git a/register_allocator/src/live_range.rs b/register_allocator/src/live_range.rs
new file mode 100644 (file)
index 0000000..239120f
--- /dev/null
@@ -0,0 +1,179 @@
+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>,
+}
diff --git a/register_allocator/src/state.rs b/register_allocator/src/state.rs
new file mode 100644 (file)
index 0000000..103233a
--- /dev/null
@@ -0,0 +1,8 @@
+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>,
+}