forked from libre-chip/fayalite
converted to using get_state_part_kinds!
This commit is contained in:
parent
f0e3aef061
commit
b5b1ee866c
6 changed files with 2551 additions and 2848 deletions
|
@ -21,9 +21,11 @@ use crate::{
|
|||
CompiledValue,
|
||||
},
|
||||
interpreter::{
|
||||
BreakAction, BreakpointsSet, RunResult, SmallUInt, State, StatePartIndex,
|
||||
StatePartKindBigSlots, StatePartKindMemories, StatePartKindSmallSlots, TypeIndexRange,
|
||||
TypeLen,
|
||||
BreakAction, BreakpointsSet, RunResult, SmallUInt, State,
|
||||
parts::{
|
||||
StatePartIndex, StatePartKindBigSlots, StatePartKindMemories,
|
||||
StatePartKindSmallSlots, TypeIndexRange, TypeLenSingle,
|
||||
},
|
||||
},
|
||||
time::{SimDuration, SimInstant},
|
||||
value::SimValue,
|
||||
|
@ -1325,14 +1327,15 @@ impl MaybeNeedsSettleFn<&'_ mut interpreter::State> for ReadBitFn {
|
|||
type Output = bool;
|
||||
|
||||
fn call(self, state: &mut interpreter::State) -> Self::Output {
|
||||
match self.compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => {
|
||||
match self.compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => {
|
||||
state.small_slots[self.compiled_value.range.small_slots.start] != 0
|
||||
}
|
||||
TypeLen::A_BIG_SLOT => !state.big_slots[self.compiled_value.range.big_slots.start]
|
||||
Some(TypeLenSingle::BigSlot) => !state.big_slots
|
||||
[self.compiled_value.range.big_slots.start]
|
||||
.clone()
|
||||
.is_zero(),
|
||||
_ => unreachable!(),
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1347,13 +1350,13 @@ impl<I: BoolOrIntType> MaybeNeedsSettleFn<&'_ mut interpreter::State> for ReadBo
|
|||
|
||||
fn call(self, state: &mut interpreter::State) -> Self::Output {
|
||||
let Self { compiled_value, io } = self;
|
||||
match compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => Expr::ty(io)
|
||||
match compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => Expr::ty(io)
|
||||
.value_from_int_wrapping(state.small_slots[compiled_value.range.small_slots.start]),
|
||||
TypeLen::A_BIG_SLOT => Expr::ty(io).value_from_int_wrapping(
|
||||
Some(TypeLenSingle::BigSlot) => Expr::ty(io).value_from_int_wrapping(
|
||||
state.big_slots[compiled_value.range.big_slots.start].clone(),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1980,14 +1983,14 @@ impl SimulationImpl {
|
|||
.get_module_mut(which_module)
|
||||
.write_helper(io, which_module);
|
||||
self.state_ready_to_run = true;
|
||||
match compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => {
|
||||
match compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => {
|
||||
self.state.small_slots[compiled_value.range.small_slots.start] = value as _;
|
||||
}
|
||||
TypeLen::A_BIG_SLOT => {
|
||||
Some(TypeLenSingle::BigSlot) => {
|
||||
self.state.big_slots[compiled_value.range.big_slots.start] = value.into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
|
@ -2013,18 +2016,18 @@ impl SimulationImpl {
|
|||
.write_helper(Expr::canonical(io), which_module);
|
||||
self.state_ready_to_run = true;
|
||||
let value: BigInt = value.into();
|
||||
match compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => {
|
||||
match compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => {
|
||||
let mut small_value = value.iter_u64_digits().next().unwrap_or(0);
|
||||
if value.is_negative() {
|
||||
small_value = small_value.wrapping_neg();
|
||||
}
|
||||
self.state.small_slots[compiled_value.range.small_slots.start] = small_value;
|
||||
}
|
||||
TypeLen::A_BIG_SLOT => {
|
||||
Some(TypeLenSingle::BigSlot) => {
|
||||
self.state.big_slots[compiled_value.range.big_slots.start] = value
|
||||
}
|
||||
_ => unreachable!(),
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
|
@ -2053,20 +2056,20 @@ impl SimulationImpl {
|
|||
};
|
||||
let bit_indexes =
|
||||
start_bit_index..start_bit_index + compiled_value.layout.ty.bit_width();
|
||||
match compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => read_write_small_scalar(
|
||||
match compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => read_write_small_scalar(
|
||||
signed,
|
||||
bit_indexes,
|
||||
bits,
|
||||
&mut state.small_slots[compiled_value.range.small_slots.start],
|
||||
),
|
||||
TypeLen::A_BIG_SLOT => read_write_big_scalar(
|
||||
Some(TypeLenSingle::BigSlot) => read_write_big_scalar(
|
||||
signed,
|
||||
bit_indexes,
|
||||
bits,
|
||||
&mut state.big_slots[compiled_value.range.big_slots.start],
|
||||
),
|
||||
_ => unreachable!(),
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
CompiledTypeLayoutBody::Array { element } => {
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,25 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::util::const_str_cmp;
|
||||
use crate::{
|
||||
array::Array,
|
||||
intern::{Intern, Interned},
|
||||
sim::interpreter::{
|
||||
Insn, InsnsBuilding, InsnsBuildingDone, InsnsBuildingKind, PrefixLinesWrapper, SmallSInt,
|
||||
SmallUInt, State,
|
||||
},
|
||||
ty::CanonicalType,
|
||||
util::{chain, const_str_cmp},
|
||||
};
|
||||
use bitvec::{boxed::BitBox, slice::BitSlice};
|
||||
use num_bigint::BigInt;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
fmt::{self, Write},
|
||||
hash::Hash,
|
||||
marker::PhantomData,
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
#[rustfmt::skip]
|
||||
macro_rules! make_get_state_part_kinds {
|
||||
|
@ -21,11 +39,15 @@ macro_rules! make_get_state_part_kinds {
|
|||
singular_variant = $type_singular_variants:ident;
|
||||
plural_variant = $type_plural_variants:ident;
|
||||
copy_insn = $copy_insn:ident;
|
||||
read_indexed_insn = $read_indexed_insn:ident;
|
||||
write_indexed_insn = $write_indexed_insn:ident;
|
||||
array_indexed_variant = $array_indexed_variants:ident;
|
||||
})*
|
||||
) => {
|
||||
make_get_state_part_kinds! {
|
||||
#![dollar = $d]
|
||||
parts! {
|
||||
#![part_names = [$(#[state] $state_singular_fields,)* $(#[type] $type_singular_fields,)*]]
|
||||
[$(state_singular_fields = (#[state] $state_singular_fields),)* $(state_singular_fields = (#[type] $type_singular_fields),)*];
|
||||
[$(type_singular_fields = ($type_singular_fields),)*];
|
||||
[$(state_plural_fields = (#[state] $state_plural_fields),)* $(state_plural_fields = (#[type] $type_plural_fields),)*];
|
||||
|
@ -37,12 +59,16 @@ macro_rules! make_get_state_part_kinds {
|
|||
[$(state_plural_variants = (#[state] $state_plural_variants),)* $(state_plural_variants = (#[type] $type_plural_variants),)*];
|
||||
[$(type_plural_variants = ($type_plural_variants),)*];
|
||||
[$(copy_insns = ($copy_insn),)*];
|
||||
[$(read_indexed_insns = ($read_indexed_insn),)*];
|
||||
[$(write_indexed_insns = ($write_indexed_insn),)*];
|
||||
[$(array_indexed_variants = ($array_indexed_variants),)*];
|
||||
}
|
||||
}
|
||||
};
|
||||
(
|
||||
#![dollar = $d:tt]
|
||||
parts! {
|
||||
#![part_names = [$(#[state] $state_part_name:ident,)* $(#[type] $type_part_name:ident,)*]]
|
||||
$([
|
||||
$first_name:ident = ($($first_value:tt)*),
|
||||
$($name:ident = ($($value:tt)*),)*
|
||||
|
@ -105,14 +131,35 @@ macro_rules! make_get_state_part_kinds {
|
|||
(
|
||||
@expand
|
||||
$d macro_ident:ident! $d group:tt
|
||||
(custom = $d custom:tt $d ($d rest:tt)*)
|
||||
(; $d ($d rest:tt)*)
|
||||
($d ($d prev_args:tt)*)
|
||||
) => {
|
||||
get_state_part_kinds! {
|
||||
@expand
|
||||
$d macro_ident! $d group
|
||||
($d ($d rest)*)
|
||||
($d ($d prev_args)* custom = $d custom)
|
||||
($d ($d prev_args)*;)
|
||||
}
|
||||
};
|
||||
(
|
||||
@expand
|
||||
$d macro_ident:ident! $d group:tt
|
||||
(#[custom] $d name:ident = [
|
||||
$d ($($state_part_name = $d $state_part_name:tt,)*)?
|
||||
$($type_part_name = $d $type_part_name:tt,)*
|
||||
]
|
||||
$d ($d rest:tt)*
|
||||
)
|
||||
($d ($d prev_args:tt)*)
|
||||
) => {
|
||||
get_state_part_kinds! {
|
||||
@expand
|
||||
$d macro_ident! $d group
|
||||
($d ($d rest)*)
|
||||
($d ($d prev_args)* $d name = [
|
||||
$d ($($d $state_part_name,)*)?
|
||||
$($d $type_part_name,)*
|
||||
])
|
||||
}
|
||||
};
|
||||
$((
|
||||
|
@ -128,14 +175,6 @@ macro_rules! make_get_state_part_kinds {
|
|||
($d ($d prev_args)* $first_name = [$($first_value)*, $($($value)*,)*])
|
||||
}
|
||||
};)*
|
||||
(
|
||||
@expand
|
||||
$d macro_ident:ident! $d group:tt
|
||||
($d unexpected:tt $d ($d rest:tt)*)
|
||||
($d ($d prev_args:tt)*)
|
||||
) => {
|
||||
compile_error! {concat!("Unexpected token: ", stringify!($d unexpected))}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use get_state_part_kinds;
|
||||
|
@ -158,6 +197,9 @@ make_get_state_part_kinds! {
|
|||
singular_variant = SmallSlot;
|
||||
plural_variant = SmallSlots;
|
||||
copy_insn = CopySmall;
|
||||
read_indexed_insn = ReadSmallIndexed;
|
||||
write_indexed_insn = WriteSmallIndexed;
|
||||
array_indexed_variant = SmallSlotArrayIndexed;
|
||||
}
|
||||
type_part! {
|
||||
singular_field = big_slot;
|
||||
|
@ -166,5 +208,805 @@ make_get_state_part_kinds! {
|
|||
singular_variant = BigSlot;
|
||||
plural_variant = BigSlots;
|
||||
copy_insn = Copy;
|
||||
read_indexed_insn = ReadIndexed;
|
||||
write_indexed_insn = WriteIndexed;
|
||||
array_indexed_variant = BigSlotArrayIndexed;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait StatePartKind:
|
||||
Send + Sync + Ord + Hash + fmt::Debug + 'static + Copy + Default
|
||||
{
|
||||
const NAME: &'static str;
|
||||
type DebugData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy;
|
||||
type LayoutData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy;
|
||||
type State: fmt::Debug + 'static + Clone;
|
||||
type BorrowedState<'a>: 'a;
|
||||
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State;
|
||||
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a>;
|
||||
fn part_debug_data<BK: InsnsBuildingKind>(
|
||||
state_layout: &StateLayout<BK>,
|
||||
part_index: StatePartIndex<Self>,
|
||||
) -> Option<&Self::DebugData>;
|
||||
fn debug_fmt_state_value(
|
||||
state: &State,
|
||||
index: StatePartIndex<Self>,
|
||||
f: &mut impl fmt::Write,
|
||||
) -> fmt::Result;
|
||||
}
|
||||
|
||||
macro_rules! make_state_part_kinds {
|
||||
(
|
||||
state_kinds = [$(#[$kind_attr:ident] $kind:ident,)*];
|
||||
) => {
|
||||
$(
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy, Default)]
|
||||
pub(crate) struct $kind;
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
get_state_part_kinds! {
|
||||
make_state_part_kinds! {
|
||||
state_kinds;
|
||||
}
|
||||
}
|
||||
|
||||
impl StatePartKind for StatePartKindMemories {
|
||||
const NAME: &'static str = "Memories";
|
||||
type DebugData = ();
|
||||
type LayoutData = MemoryData<Interned<BitSlice>>;
|
||||
type State = Box<[MemoryData<BitBox>]>;
|
||||
type BorrowedState<'a> = &'a mut [MemoryData<BitBox>];
|
||||
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
|
||||
layout_data
|
||||
.iter()
|
||||
.map(|MemoryData { array_type, data }| MemoryData {
|
||||
array_type: *array_type,
|
||||
data: BitBox::from_bitslice(data),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
|
||||
state
|
||||
}
|
||||
fn part_debug_data<BK: InsnsBuildingKind>(
|
||||
state_layout: &StateLayout<BK>,
|
||||
part_index: StatePartIndex<Self>,
|
||||
) -> Option<&Self::DebugData> {
|
||||
state_layout.memories.debug_data.get(part_index.as_usize())
|
||||
}
|
||||
fn debug_fmt_state_value(
|
||||
state: &State,
|
||||
index: StatePartIndex<Self>,
|
||||
f: &mut impl fmt::Write,
|
||||
) -> fmt::Result {
|
||||
write!(f, "{:#?}", &state.memories[index])
|
||||
}
|
||||
}
|
||||
|
||||
impl StatePartKind for StatePartKindSmallSlots {
|
||||
const NAME: &'static str = "SmallSlots";
|
||||
type DebugData = SlotDebugData;
|
||||
type LayoutData = ();
|
||||
type State = Box<[SmallUInt]>;
|
||||
type BorrowedState<'a> = &'a mut [SmallUInt];
|
||||
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
|
||||
vec![0; layout_data.len()].into_boxed_slice()
|
||||
}
|
||||
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
|
||||
state
|
||||
}
|
||||
fn part_debug_data<BK: InsnsBuildingKind>(
|
||||
state_layout: &StateLayout<BK>,
|
||||
part_index: StatePartIndex<Self>,
|
||||
) -> Option<&Self::DebugData> {
|
||||
state_layout
|
||||
.ty
|
||||
.small_slots
|
||||
.debug_data
|
||||
.get(part_index.as_usize())
|
||||
}
|
||||
fn debug_fmt_state_value(
|
||||
state: &State,
|
||||
index: StatePartIndex<Self>,
|
||||
f: &mut impl fmt::Write,
|
||||
) -> fmt::Result {
|
||||
let value = state.small_slots[index];
|
||||
write!(f, "{value:#x} {}", value as SmallSInt)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl StatePartKind for StatePartKindBigSlots {
|
||||
const NAME: &'static str = "BigSlots";
|
||||
type DebugData = SlotDebugData;
|
||||
type LayoutData = ();
|
||||
type State = Box<[BigInt]>;
|
||||
type BorrowedState<'a> = &'a mut [BigInt];
|
||||
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
|
||||
layout_data.iter().map(|_| BigInt::default()).collect()
|
||||
}
|
||||
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
|
||||
state
|
||||
}
|
||||
fn part_debug_data<BK: InsnsBuildingKind>(
|
||||
state_layout: &StateLayout<BK>,
|
||||
part_index: StatePartIndex<Self>,
|
||||
) -> Option<&Self::DebugData> {
|
||||
state_layout
|
||||
.ty
|
||||
.big_slots
|
||||
.debug_data
|
||||
.get(part_index.as_usize())
|
||||
}
|
||||
fn debug_fmt_state_value(
|
||||
state: &State,
|
||||
index: StatePartIndex<Self>,
|
||||
f: &mut impl fmt::Write,
|
||||
) -> fmt::Result {
|
||||
write!(f, "{:#x}", state.big_slots[index])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) struct StatePartIndex<K: StatePartKind> {
|
||||
pub(crate) value: u32,
|
||||
pub(crate) _phantom: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> StatePartIndex<K> {
|
||||
pub(crate) const ZERO: Self = Self::new(0);
|
||||
pub(crate) const fn new(value: u32) -> Self {
|
||||
Self {
|
||||
value,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub(crate) fn as_usize(self) -> usize {
|
||||
self.value.try_into().expect("index too big")
|
||||
}
|
||||
pub(crate) fn offset(self, offset: StatePartIndex<K>) -> Self {
|
||||
Self::new(
|
||||
self.value
|
||||
.checked_add(offset.value)
|
||||
.expect("offset too big"),
|
||||
)
|
||||
}
|
||||
pub(crate) fn debug_fmt<BK: InsnsBuildingKind>(
|
||||
&self,
|
||||
f: &mut impl fmt::Write,
|
||||
before_debug_info_text: &str,
|
||||
comment_start: &str,
|
||||
comment_line_start: &str,
|
||||
comment_end: &str,
|
||||
state_layout: Option<&StateLayout<BK>>,
|
||||
state: Option<&State>,
|
||||
) -> fmt::Result {
|
||||
write!(f, "StatePartIndex<{}>({})", K::NAME, self.value)?;
|
||||
f.write_str(before_debug_info_text)?;
|
||||
let debug_data =
|
||||
state_layout.and_then(|state_layout| K::part_debug_data(state_layout, *self));
|
||||
if state.is_some() || debug_data.is_some() {
|
||||
f.write_str(comment_start)?;
|
||||
}
|
||||
let mut f = PrefixLinesWrapper {
|
||||
writer: f,
|
||||
at_beginning_of_line: false,
|
||||
blank_line_prefix: comment_line_start.trim_end(),
|
||||
line_prefix: comment_line_start,
|
||||
};
|
||||
if let Some(state) = state {
|
||||
f.write_str("(")?;
|
||||
K::debug_fmt_state_value(state, *self, &mut f)?;
|
||||
f.write_str(")")?;
|
||||
}
|
||||
if state.is_some() && debug_data.is_some() {
|
||||
f.write_str(" ")?;
|
||||
}
|
||||
if let Some(debug_data) = debug_data {
|
||||
write!(f, "{debug_data:?}")?;
|
||||
}
|
||||
if state.is_some() || debug_data.is_some() {
|
||||
f.writer.write_str(comment_end)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> fmt::Debug for StatePartIndex<K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.debug_fmt::<InsnsBuildingDone>(f, "", "", "", "", None, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct StatePartIndexRange<K: StatePartKind> {
|
||||
pub(crate) start: StatePartIndex<K>,
|
||||
pub(crate) len: StatePartLen<K>,
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> StatePartIndexRange<K> {
|
||||
pub(crate) fn start(self) -> StatePartIndex<K> {
|
||||
self.start
|
||||
}
|
||||
pub(crate) fn end(self) -> StatePartIndex<K> {
|
||||
StatePartIndex::new(
|
||||
self.start
|
||||
.value
|
||||
.checked_add(self.len.value)
|
||||
.expect("state part allocation layout is too big"),
|
||||
)
|
||||
}
|
||||
pub(crate) fn len(self) -> StatePartLen<K> {
|
||||
self.len
|
||||
}
|
||||
pub(crate) fn is_empty(self) -> bool {
|
||||
self.len.value == 0
|
||||
}
|
||||
pub(crate) fn iter(self) -> impl Iterator<Item = StatePartIndex<K>> {
|
||||
(self.start.value..self.end().value).map(StatePartIndex::new)
|
||||
}
|
||||
pub(crate) fn offset(self, offset: StatePartIndex<K>) -> Self {
|
||||
self.end().offset(offset); // check for overflow
|
||||
Self {
|
||||
start: self.start.offset(offset),
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
pub(crate) fn slice(self, index: StatePartIndexRange<K>) -> Self {
|
||||
assert!(index.end().value <= self.len.value, "index out of range");
|
||||
Self {
|
||||
start: StatePartIndex::new(self.start.value + index.start.value),
|
||||
len: index.len,
|
||||
}
|
||||
}
|
||||
pub(crate) fn index_array(self, element_size: StatePartLen<K>, index: usize) -> Self {
|
||||
if element_size.value == 0 {
|
||||
assert_eq!(
|
||||
self.len.value, 0,
|
||||
"array with zero-sized element must also be zero-sized",
|
||||
);
|
||||
return self;
|
||||
}
|
||||
assert!(
|
||||
self.len.value % element_size.value == 0,
|
||||
"array's size must be a multiple of its element size",
|
||||
);
|
||||
self.slice(StatePartIndexRange {
|
||||
start: StatePartIndex::new(
|
||||
index
|
||||
.try_into()
|
||||
.ok()
|
||||
.and_then(|index| element_size.value.checked_mul(index))
|
||||
.expect("index out of range"),
|
||||
),
|
||||
len: element_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> fmt::Debug for StatePartIndexRange<K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"StatePartIndexRange<{}> {{ start: {}, len: {} }}",
|
||||
K::NAME,
|
||||
self.start.value,
|
||||
self.len.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub(crate) struct MemoryData<T: Deref<Target = BitSlice>> {
|
||||
pub(crate) array_type: Array,
|
||||
pub(crate) data: T,
|
||||
}
|
||||
|
||||
impl<T: Deref<Target = BitSlice>> fmt::Debug for MemoryData<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { array_type, data } = self;
|
||||
f.debug_struct("MemoryData")
|
||||
.field("array_type", array_type)
|
||||
.field(
|
||||
"data",
|
||||
&crate::memory::DebugMemoryData::from_bit_slice(*array_type, data),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_state_layout {
|
||||
(
|
||||
state_plural_fields = [$(#[state] $state_plural_field:ident,)* $(#[type] $type_plural_field:ident,)*];
|
||||
state_kinds = [$(#[state] $state_kind:ident,)* $(#[type] $type_kind:ident,)*];
|
||||
) => {
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct StateLayout<BK: InsnsBuildingKind> {
|
||||
pub(crate) ty: TypeLayout<BK>,
|
||||
$(pub(crate) $state_plural_field: StatePartLayout<$state_kind, BK>,)*
|
||||
}
|
||||
|
||||
impl Copy for StateLayout<InsnsBuildingDone> {}
|
||||
|
||||
impl<BK: InsnsBuildingKind> StateLayout<BK> {
|
||||
pub(crate) fn len(&self) -> StateLen {
|
||||
StateLen {
|
||||
ty: self.ty.len(),
|
||||
$($state_plural_field: self.$state_plural_field.len(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.ty.is_empty() $(&& self.$state_plural_field.is_empty())*
|
||||
}
|
||||
pub(crate) fn empty() -> Self {
|
||||
Self {
|
||||
ty: TypeLayout::empty(),
|
||||
$($state_plural_field: StatePartLayout::empty(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StateLayout<InsnsBuilding> {
|
||||
pub(crate) fn next_index(&self) -> StateIndex {
|
||||
StateIndex {
|
||||
ty: self.ty.next_index(),
|
||||
$($state_plural_field: self.$state_plural_field.next_index(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn allocate<BK: InsnsBuildingKind>(
|
||||
&mut self,
|
||||
layout: &StateLayout<BK>,
|
||||
) -> StateIndexRange {
|
||||
StateIndexRange {
|
||||
ty: self.ty.allocate(&layout.ty),
|
||||
$($state_plural_field: self.$state_plural_field.allocate(&layout.$state_plural_field),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StateLayout<InsnsBuilding>> for StateLayout<InsnsBuildingDone> {
|
||||
fn from(v: StateLayout<InsnsBuilding>) -> Self {
|
||||
Self {
|
||||
ty: v.ty.into(),
|
||||
$($state_plural_field: v.$state_plural_field.into(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct TypeLayout<BK: InsnsBuildingKind> {
|
||||
$(pub(crate) $type_plural_field: StatePartLayout<$type_kind, BK>,)*
|
||||
}
|
||||
|
||||
impl Copy for TypeLayout<InsnsBuildingDone> {}
|
||||
|
||||
impl<BK: InsnsBuildingKind> TypeLayout<BK> {
|
||||
pub(crate) fn len(&self) -> TypeLen {
|
||||
TypeLen {
|
||||
$($type_plural_field: self.$type_plural_field.len(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
$(self.$type_plural_field.is_empty())&&+
|
||||
}
|
||||
pub(crate) fn empty() -> Self {
|
||||
Self {
|
||||
$($type_plural_field: StatePartLayout::empty(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeLayout<InsnsBuilding> {
|
||||
pub(crate) fn next_index(&self) -> TypeIndex {
|
||||
TypeIndex {
|
||||
$($type_plural_field: self.$type_plural_field.next_index(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn allocate<BK: InsnsBuildingKind>(
|
||||
&mut self,
|
||||
layout: &TypeLayout<BK>,
|
||||
) -> TypeIndexRange {
|
||||
TypeIndexRange {
|
||||
$($type_plural_field: self.$type_plural_field.allocate(&layout.$type_plural_field),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TypeLayout<InsnsBuilding>> for TypeLayout<InsnsBuildingDone> {
|
||||
fn from(v: TypeLayout<InsnsBuilding>) -> Self {
|
||||
Self {
|
||||
$($type_plural_field: v.$type_plural_field.into(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get_state_part_kinds! {
|
||||
make_state_layout! {
|
||||
state_plural_fields;
|
||||
state_kinds;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct StatePartLayout<K: StatePartKind, BK: InsnsBuildingKind> {
|
||||
pub(crate) debug_data: BK::Vec<K::DebugData>,
|
||||
pub(crate) layout_data: BK::Vec<K::LayoutData>,
|
||||
pub(crate) _phantom: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> Copy for StatePartLayout<K, InsnsBuildingDone> {}
|
||||
|
||||
impl<K: StatePartKind, BK: InsnsBuildingKind> StatePartLayout<K, BK> {
|
||||
pub(crate) fn len(&self) -> StatePartLen<K> {
|
||||
StatePartLen::new(
|
||||
self.debug_data
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("state part allocation layout is too big"),
|
||||
)
|
||||
}
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.debug_data.is_empty()
|
||||
}
|
||||
pub(crate) fn empty() -> Self {
|
||||
Self {
|
||||
debug_data: Default::default(),
|
||||
layout_data: Default::default(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub(crate) fn debug_data(&self, index: StatePartIndex<K>) -> &K::DebugData {
|
||||
&self.debug_data[index.as_usize()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> From<StatePartLayout<K, InsnsBuilding>>
|
||||
for StatePartLayout<K, InsnsBuildingDone>
|
||||
{
|
||||
fn from(value: StatePartLayout<K, InsnsBuilding>) -> Self {
|
||||
Self {
|
||||
debug_data: Intern::intern_owned(value.debug_data),
|
||||
layout_data: Intern::intern_owned(value.layout_data),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> StatePartLayout<K, InsnsBuilding> {
|
||||
pub(crate) fn scalar(debug_data: K::DebugData, layout_data: K::LayoutData) -> Self {
|
||||
Self {
|
||||
debug_data: vec![debug_data],
|
||||
layout_data: vec![layout_data],
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub(crate) fn next_index(&self) -> StatePartIndex<K> {
|
||||
StatePartIndex::new(self.len().value)
|
||||
}
|
||||
pub(crate) fn allocate<BK: InsnsBuildingKind>(
|
||||
&mut self,
|
||||
layout: &StatePartLayout<K, BK>,
|
||||
) -> StatePartIndexRange<K> {
|
||||
let start = self.next_index();
|
||||
let len = layout.len();
|
||||
let Self {
|
||||
debug_data,
|
||||
layout_data,
|
||||
_phantom: _,
|
||||
} = self;
|
||||
debug_data.extend_from_slice(&layout.debug_data);
|
||||
layout_data.extend_from_slice(&layout.layout_data);
|
||||
StatePartIndexRange { start, len }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind, BK: InsnsBuildingKind> fmt::Debug for StatePartLayout<K, BK> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self {
|
||||
debug_data,
|
||||
layout_data,
|
||||
_phantom: _,
|
||||
} = self;
|
||||
write!(f, "StatePartLayout<{}>", K::NAME)?;
|
||||
let mut debug_struct = f.debug_struct("");
|
||||
debug_struct
|
||||
.field("len", &debug_data.len())
|
||||
.field("debug_data", debug_data);
|
||||
if TypeId::of::<K::LayoutData>() != TypeId::of::<()>() {
|
||||
debug_struct.field("layout_data", layout_data);
|
||||
}
|
||||
debug_struct.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind<DebugData = SlotDebugData>, BK: InsnsBuildingKind> StatePartLayout<K, BK> {
|
||||
pub(crate) fn with_prefixed_debug_names(&self, prefix: &str) -> Self {
|
||||
Self {
|
||||
debug_data: self
|
||||
.debug_data
|
||||
.iter()
|
||||
.map(|v| v.with_prefixed_debug_names(prefix))
|
||||
.collect(),
|
||||
layout_data: self.layout_data.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub(crate) fn with_anonymized_debug_info(&self) -> Self {
|
||||
Self {
|
||||
debug_data: self
|
||||
.debug_data
|
||||
.iter()
|
||||
.map(|v| v.with_anonymized_debug_info())
|
||||
.collect(),
|
||||
layout_data: self.layout_data.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BK: InsnsBuildingKind> TypeLayout<BK> {
|
||||
pub(crate) fn with_prefixed_debug_names(&self, prefix: &str) -> Self {
|
||||
Self {
|
||||
small_slots: self.small_slots.with_prefixed_debug_names(prefix),
|
||||
big_slots: self.big_slots.with_prefixed_debug_names(prefix),
|
||||
}
|
||||
}
|
||||
pub(crate) fn with_anonymized_debug_info(&self) -> Self {
|
||||
Self {
|
||||
small_slots: self.small_slots.with_anonymized_debug_info(),
|
||||
big_slots: self.big_slots.with_anonymized_debug_info(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_state_len {
|
||||
(
|
||||
state_plural_fields = [$(#[state] $state_plural_field:ident,)* $(#[type] $type_plural_field:ident,)*];
|
||||
state_kinds = [$(#[state] $state_kind:ident,)* $(#[type] $type_kind:ident,)*];
|
||||
type_singular_variants = [$($type_singular_variant:ident,)*];
|
||||
type_singular_fields = [$($type_singular_field:ident,)*];
|
||||
) => {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct StateLen {
|
||||
pub(crate) ty: TypeLen,
|
||||
$(pub(crate) $state_plural_field: StatePartLen<$state_kind>,)*
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct TypeLen {
|
||||
$(pub(crate) $type_plural_field: StatePartLen<$type_kind>,)*
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) enum TypeLenSingle {
|
||||
$($type_singular_variant,)*
|
||||
}
|
||||
|
||||
impl TypeLen {
|
||||
pub(crate) const fn as_index(self) -> TypeIndex {
|
||||
TypeIndex {
|
||||
$($type_plural_field: self.$type_plural_field.as_index(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) const fn empty() -> Self {
|
||||
Self {
|
||||
$($type_plural_field: StatePartLen::new(0),)*
|
||||
}
|
||||
}
|
||||
$(pub(crate) const fn $type_singular_field() -> Self {
|
||||
let mut retval = Self::empty();
|
||||
retval.$type_plural_field.value = 1;
|
||||
retval
|
||||
})*
|
||||
pub(crate) const fn as_single(self) -> Option<TypeLenSingle> {
|
||||
$({
|
||||
const SINGLE: TypeLen = TypeLen::$type_singular_field();
|
||||
if let SINGLE = self {
|
||||
return Some(TypeLenSingle::$type_singular_variant);
|
||||
}
|
||||
})*
|
||||
None
|
||||
}
|
||||
pub(crate) const fn only_small(mut self) -> Option<StatePartLen<StatePartKindSmallSlots>> {
|
||||
const EMPTY: TypeLen = TypeLen::empty();
|
||||
let retval = self.small_slots;
|
||||
self.small_slots.value = 0;
|
||||
if let EMPTY = self {
|
||||
Some(retval)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get_state_part_kinds! {
|
||||
make_state_len! {
|
||||
state_plural_fields;
|
||||
state_kinds;
|
||||
type_singular_variants;
|
||||
type_singular_fields;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) struct StatePartLen<K: StatePartKind> {
|
||||
pub(crate) value: u32,
|
||||
pub(crate) _phantom: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> StatePartLen<K> {
|
||||
pub(crate) const fn new(value: u32) -> Self {
|
||||
Self {
|
||||
value,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub(crate) const fn as_index(self) -> StatePartIndex<K> {
|
||||
StatePartIndex::new(self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> fmt::Debug for StatePartLen<K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "StatePartLen<{}>({})", K::NAME, self.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub(crate) struct SlotDebugData {
|
||||
pub(crate) name: Interned<str>,
|
||||
pub(crate) ty: CanonicalType,
|
||||
}
|
||||
|
||||
impl SlotDebugData {
|
||||
pub(crate) fn with_prefixed_debug_names(&self, prefix: &str) -> Self {
|
||||
let mut name = String::with_capacity(self.name.len() + prefix.len());
|
||||
name.push_str(prefix);
|
||||
name.push_str(&self.name);
|
||||
Self {
|
||||
name: Intern::intern_owned(name),
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
pub(crate) fn with_anonymized_debug_info(&self) -> Self {
|
||||
Self {
|
||||
name: Interned::default(),
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_state_index {
|
||||
(
|
||||
state_plural_fields = [$(#[state] $state_plural_field:ident,)* $(#[type] $type_plural_field:ident,)*];
|
||||
state_kinds = [$(#[state] $state_kind:ident,)* $(#[type] $type_kind:ident,)*];
|
||||
) => {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct StateIndex {
|
||||
pub(crate) ty: TypeIndex,
|
||||
$(pub(crate) $state_plural_field: StatePartIndex<$state_kind>,)*
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct TypeIndex {
|
||||
$(pub(crate) $type_plural_field: StatePartIndex<$type_kind>,)*
|
||||
}
|
||||
|
||||
impl TypeIndex {
|
||||
pub(crate) const ZERO: Self = Self {
|
||||
$($type_plural_field: StatePartIndex::ZERO,)*
|
||||
};
|
||||
pub(crate) fn offset(self, offset: TypeIndex) -> Self {
|
||||
Self {
|
||||
$($type_plural_field: self.$type_plural_field.offset(offset.$type_plural_field),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get_state_part_kinds! {
|
||||
make_state_index! {
|
||||
state_plural_fields;
|
||||
state_kinds;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_state_index_range {
|
||||
(
|
||||
state_plural_fields = [$(#[state] $state_plural_field:ident,)* $(#[type] $type_plural_field:ident,)*];
|
||||
state_kinds = [$(#[state] $state_kind:ident,)* $(#[type] $type_kind:ident,)*];
|
||||
copy_insns = [$($copy_insn:ident,)*];
|
||||
) => {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct StateIndexRange {
|
||||
pub(crate) ty: TypeIndexRange,
|
||||
$(pub(crate) $state_plural_field: StatePartIndexRange<$state_kind>,)*
|
||||
}
|
||||
|
||||
impl StateIndexRange {
|
||||
pub(crate) fn start(self) -> StateIndex {
|
||||
StateIndex {
|
||||
ty: self.ty.start(),
|
||||
$($state_plural_field: self.$state_plural_field.start(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn len(self) -> StateLen {
|
||||
StateLen {
|
||||
ty: self.ty.len(),
|
||||
$($state_plural_field: self.$state_plural_field.len(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn is_empty(self) -> bool {
|
||||
self.ty.is_empty() $(&& self.$state_plural_field.is_empty())*
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct TypeIndexRange {
|
||||
$(pub(crate) $type_plural_field: StatePartIndexRange<$type_kind>,)*
|
||||
}
|
||||
|
||||
impl TypeIndexRange {
|
||||
pub(crate) fn new(start: TypeIndex, len: TypeLen) -> Self {
|
||||
Self {
|
||||
$($type_plural_field: StatePartIndexRange {
|
||||
start: start.$type_plural_field,
|
||||
len: len.$type_plural_field,
|
||||
},)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn start(self) -> TypeIndex {
|
||||
TypeIndex {
|
||||
$($type_plural_field: self.$type_plural_field.start(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn len(self) -> TypeLen {
|
||||
TypeLen {
|
||||
$($type_plural_field: self.$type_plural_field.len(),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn is_empty(self) -> bool {
|
||||
$(self.$type_plural_field.is_empty()) &&+
|
||||
}
|
||||
pub(crate) fn slice(self, index: TypeIndexRange) -> Self {
|
||||
Self {
|
||||
$($type_plural_field: self.$type_plural_field.slice(index.$type_plural_field),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn index_array(self, element_size: TypeLen, index: usize) -> Self {
|
||||
Self {
|
||||
$($type_plural_field: self.$type_plural_field.index_array(element_size.$type_plural_field, index),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn offset(self, offset: TypeIndex) -> Self {
|
||||
Self {
|
||||
$($type_plural_field: self.$type_plural_field.offset(offset.$type_plural_field),)*
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub(crate) fn insns_for_copy_to(self, dest: TypeIndexRange) -> impl Iterator<Item = Insn> {
|
||||
assert_eq!(self.len(), dest.len());
|
||||
chain!($(self.$type_plural_field.iter().zip(dest.$type_plural_field.iter()).map(|(src, dest)| Insn::$copy_insn { dest, src })),*)
|
||||
}
|
||||
#[must_use]
|
||||
pub(crate) fn insns_for_copy_from(self, src: TypeIndexRange) -> impl Iterator<Item = Insn> {
|
||||
src.insns_for_copy_to(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get_state_part_kinds! {
|
||||
make_state_index_range! {
|
||||
state_plural_fields;
|
||||
state_kinds;
|
||||
copy_insns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ pub use const_cmp::{
|
|||
#[doc(inline)]
|
||||
pub use scoped_ref::ScopedRef;
|
||||
|
||||
pub(crate) use misc::chain;
|
||||
#[doc(inline)]
|
||||
pub use misc::{
|
||||
BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice, RcWriter, interned_bit,
|
||||
|
|
|
@ -209,3 +209,18 @@ impl std::io::Write for RcWriter {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! chain {
|
||||
() => {
|
||||
std::iter::empty()
|
||||
};
|
||||
($first:expr $(, $rest:expr)* $(,)?) => {
|
||||
{
|
||||
let retval = IntoIterator::into_iter($first);
|
||||
$(let retval = Iterator::chain(retval, $rest);)*
|
||||
retval
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use chain;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue