use crate::{Error, Reg};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct RegSpan(Reg);
impl RegSpan {
pub fn new(head: Reg) -> Self {
Self(head)
}
pub fn iter_sized(self, len: usize) -> RegSpanIter {
RegSpanIter::new(self.0, len)
}
pub fn iter(self, len: u16) -> RegSpanIter {
RegSpanIter::new_u16(self.0, len)
}
pub fn head(self) -> Reg {
self.0
}
pub fn head_mut(&mut self) -> &mut Reg {
&mut self.0
}
pub fn has_overlapping_copies(results: Self, values: Self, len: u16) -> bool {
RegSpanIter::has_overlapping_copies(results.iter(len), values.iter(len))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct FixedRegSpan<const N: u16> {
span: RegSpan,
}
impl<const N: u16> FixedRegSpan<N> {
pub fn new(span: RegSpan) -> Result<Self, Error> {
let head = span.head();
if head >= head.next_n(N) {
return Err(Error::RegisterOutOfBounds);
}
Ok(Self { span })
}
pub fn iter(&self) -> RegSpanIter {
self.span.iter(self.len())
}
pub fn bounded(self) -> BoundedRegSpan {
BoundedRegSpan {
span: self.span,
len: N,
}
}
pub fn span(self) -> RegSpan {
self.span
}
pub fn span_mut(&mut self) -> &mut RegSpan {
&mut self.span
}
pub fn contains(self, reg: Reg) -> bool {
if self.is_empty() {
return false;
}
let min = self.span.head();
let max = min.next_n(N);
min <= reg && reg < max
}
pub fn len(self) -> u16 {
N
}
pub fn is_empty(self) -> bool {
N == 0
}
}
impl<'a, const N: u16> IntoIterator for &'a FixedRegSpan<N> {
type Item = Reg;
type IntoIter = RegSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<const N: u16> IntoIterator for FixedRegSpan<N> {
type Item = Reg;
type IntoIter = RegSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BoundedRegSpan {
span: RegSpan,
len: u16,
}
impl BoundedRegSpan {
pub fn new(span: RegSpan, len: u16) -> Self {
Self { span, len }
}
pub fn iter(&self) -> RegSpanIter {
self.span.iter(self.len())
}
pub fn span(&self) -> RegSpan {
self.span
}
pub fn span_mut(&mut self) -> &mut RegSpan {
&mut self.span
}
pub fn contains(self, reg: Reg) -> bool {
if self.is_empty() {
return false;
}
let min = self.span.head();
let max = min.next_n(self.len);
min <= reg && reg < max
}
pub fn len(&self) -> u16 {
self.len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<'a> IntoIterator for &'a BoundedRegSpan {
type Item = Reg;
type IntoIter = RegSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for BoundedRegSpan {
type Item = Reg;
type IntoIter = RegSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct RegSpanIter {
next: Reg,
last: Reg,
}
impl RegSpanIter {
pub fn from_raw_parts(start: Reg, end: Reg) -> Self {
debug_assert!(i16::from(start) <= i16::from(end));
Self {
next: start,
last: end,
}
}
fn new(start: Reg, len: usize) -> Self {
let len = u16::try_from(len)
.unwrap_or_else(|_| panic!("out of bounds length for register span: {len}"));
Self::new_u16(start, len)
}
fn new_u16(start: Reg, len: u16) -> Self {
let next = start;
let last = start
.0
.checked_add_unsigned(len)
.map(Reg)
.expect("overflowing register index for register span");
Self::from_raw_parts(next, last)
}
pub fn span(self) -> RegSpan {
RegSpan(self.next)
}
pub fn len_as_u16(&self) -> u16 {
self.last.0.abs_diff(self.next.0)
}
pub fn is_empty(&self) -> bool {
self.len_as_u16() == 0
}
pub fn has_overlapping_copies(results: Self, values: Self) -> bool {
assert_eq!(
results.len(),
values.len(),
"cannot copy between different sized register spans"
);
let len = results.len();
if len <= 1 {
return false;
}
let first_value = values.span().head();
let first_result = results.span().head();
if first_value >= first_result {
return false;
}
let mut values = values;
let last_value = values
.next_back()
.expect("span is non empty and thus must return");
last_value >= first_result
}
}
impl Iterator for RegSpanIter {
type Item = Reg;
fn next(&mut self) -> Option<Self::Item> {
if self.next == self.last {
return None;
}
let reg = self.next;
self.next = self.next.next();
Some(reg)
}
}
impl DoubleEndedIterator for RegSpanIter {
fn next_back(&mut self) -> Option<Self::Item> {
if self.next == self.last {
return None;
}
self.last = self.last.prev();
Some(self.last)
}
}
impl ExactSizeIterator for RegSpanIter {
fn len(&self) -> usize {
usize::from(RegSpanIter::len_as_u16(self))
}
}