converted to using get_state_part_kinds!

This commit is contained in:
Jacob Lifshay 2025-09-05 03:35:40 -07:00
parent f0e3aef061
commit b5b1ee866c
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
6 changed files with 2551 additions and 2848 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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;