working on simulator
This commit is contained in:
		
							parent
							
								
									86c711c36e
								
							
						
					
					
						commit
						435514654c
					
				
					 4 changed files with 1454 additions and 589 deletions
				
			
		
							
								
								
									
										5
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -473,11 +473,10 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" | |||
| 
 | ||||
| [[package]] | ||||
| name = "num-bigint" | ||||
| version = "0.4.4" | ||||
| version = "0.4.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" | ||||
| checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" | ||||
| dependencies = [ | ||||
|  "autocfg", | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
| ] | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ eyre = "0.6.12" | |||
| hashbrown = "0.14.3" | ||||
| indexmap = { version = "2.2.6", features = ["serde"] } | ||||
| jobslot = "0.2.19" | ||||
| num-bigint = "0.4.4" | ||||
| num-bigint = "0.4.6" | ||||
| num-traits = "0.2.16" | ||||
| os_pipe = "1.2.1" | ||||
| prettyplease = "0.2.20" | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -2,11 +2,13 @@ | |||
| // See Notices.txt for copyright information
 | ||||
| 
 | ||||
| use crate::{ | ||||
|     intern::{Intern, Interned}, | ||||
|     intern::{Intern, Interned, Memoize}, | ||||
|     source_location::SourceLocation, | ||||
|     ty::CanonicalType, | ||||
|     util::get_many_mut, | ||||
| }; | ||||
| use num_bigint::BigInt; | ||||
| use num_traits::{One, Signed, ToPrimitive, Zero}; | ||||
| use std::{ | ||||
|     borrow::BorrowMut, | ||||
|     convert::Infallible, | ||||
|  | @ -21,6 +23,147 @@ pub(crate) type SmallUInt = u64; | |||
| pub(crate) type SmallSInt = i64; | ||||
| pub(crate) const MIN_BITS_FOR_NEEDING_BIG: usize = SmallUInt::BITS as usize + 1; | ||||
| 
 | ||||
| #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||||
| pub(crate) enum InsnFieldKind { | ||||
|     Input, | ||||
|     Output, | ||||
|     Immediate, | ||||
|     BranchTarget, | ||||
| } | ||||
| 
 | ||||
| pub(crate) trait InsnFieldTypeTransform: Eq + Hash + fmt::Debug + Send + Sync { | ||||
|     type Type<FieldType: InsnFieldTrait>: Eq + Hash + fmt::Debug + Send + Sync; | ||||
|     fn empty_type() -> Self::Type<[(); 0]>; | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)] | ||||
| pub(crate) struct InsnFieldTypeTransformUnit; | ||||
| 
 | ||||
| impl InsnFieldTypeTransform for InsnFieldTypeTransformUnit { | ||||
|     type Type<FieldType: InsnFieldTrait> = (); | ||||
|     fn empty_type() -> Self::Type<[(); 0]> { | ||||
|         () | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||||
| pub(crate) struct InsnFieldTypeTransformRef<'a>(PhantomData<&'a ()>); | ||||
| 
 | ||||
| impl<'a> InsnFieldTypeTransform for InsnFieldTypeTransformRef<'a> { | ||||
|     type Type<FieldType: InsnFieldTrait> = &'a FieldType; | ||||
|     fn empty_type() -> Self::Type<[(); 0]> { | ||||
|         &[] | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(PartialEq, Eq, Hash, Debug)] | ||||
| pub(crate) struct InsnFieldTypeTransformRefMut<'a>(PhantomData<&'a mut ()>); | ||||
| 
 | ||||
| impl<'a> InsnFieldTypeTransform for InsnFieldTypeTransformRefMut<'a> { | ||||
|     type Type<FieldType: InsnFieldTrait> = &'a mut FieldType; | ||||
|     fn empty_type() -> Self::Type<[(); 0]> { | ||||
|         &mut [] | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||||
| pub(crate) struct InsnFieldTypeTransformValue; | ||||
| 
 | ||||
| impl InsnFieldTypeTransform for InsnFieldTypeTransformValue { | ||||
|     type Type<FieldType: InsnFieldTrait> = FieldType; | ||||
|     fn empty_type() -> Self::Type<[(); 0]> { | ||||
|         [] | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait InsnFieldTrait: Send + Sync + 'static + Copy + Eq + Hash + fmt::Debug { | ||||
|     const UNIT: InsnFieldType<InsnFieldTypeTransformUnit>; | ||||
|     fn variant<Transform: InsnFieldTypeTransform>( | ||||
|         v: Transform::Type<Self>, | ||||
|     ) -> InsnFieldType<Transform>; | ||||
| } | ||||
| 
 | ||||
| macro_rules! insn_field_enum { | ||||
|     ( | ||||
|         $enum_vis:vis enum $InsnFieldType:ident<$Transform:ident: $InsnFieldTypeTransform:ident> { | ||||
|             $($Variant:ident($Transform2:ident::$Type:ident<$variant_ty:ty>),)* | ||||
|         } | ||||
|     ) => { | ||||
|         #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||||
|         $enum_vis enum $InsnFieldType<$Transform: $InsnFieldTypeTransform> { | ||||
|             $($Variant($Transform2::$Type<$variant_ty>),)* | ||||
|         } | ||||
| 
 | ||||
|         $(impl InsnFieldTrait for $variant_ty { | ||||
|             const UNIT: $InsnFieldType<InsnFieldTypeTransformUnit> = $InsnFieldType::$Variant(()); | ||||
|             fn variant<$Transform2: $InsnFieldTypeTransform>( | ||||
|                 v: $Transform2::$Type<Self>, | ||||
|             ) -> $InsnFieldType<$Transform2> { | ||||
|                 $InsnFieldType::$Variant(v) | ||||
|             } | ||||
|         })* | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| insn_field_enum! { | ||||
|     pub(crate) enum InsnFieldType<Transform: InsnFieldTypeTransform> { | ||||
|         SmallSlot(Transform::Type<StatePartIndex<StatePartKindSmallSlots>>), | ||||
|         BigSlot(Transform::Type<StatePartIndex<StatePartKindBigSlots>>), | ||||
|         SmallUInt(Transform::Type<SmallUInt>), | ||||
|         SmallSInt(Transform::Type<SmallSInt>), | ||||
|         InternedBigInt(Transform::Type<Interned<BigInt>>), | ||||
|         U8(Transform::Type<u8>), | ||||
|         USize(Transform::Type<usize>), | ||||
|         Empty(Transform::Type<[(); 0]>), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<Transform: InsnFieldTypeTransform> InsnFieldType<Transform> { | ||||
|     pub(crate) fn empty() -> Self { | ||||
|         Self::Empty(Transform::empty_type()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(PartialEq, Eq, Hash, Debug)] | ||||
| pub(crate) struct InsnField<Transform: InsnFieldTypeTransform> { | ||||
|     pub(crate) ty: InsnFieldType<Transform>, | ||||
|     pub(crate) kind: InsnFieldKind, | ||||
| } | ||||
| 
 | ||||
| impl<Transform: InsnFieldTypeTransform> Clone for InsnField<Transform> | ||||
| where | ||||
|     InsnFieldType<Transform>: Clone, | ||||
| { | ||||
|     fn clone(&self) -> Self { | ||||
|         Self { | ||||
|             ty: self.ty.clone(), | ||||
|             kind: self.kind.clone(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<Transform: InsnFieldTypeTransform> Copy for InsnField<Transform> where | ||||
|     InsnFieldType<Transform>: Copy | ||||
| { | ||||
| } | ||||
| 
 | ||||
| fn make_array_into_iter<T, const I: usize, const N: usize>( | ||||
|     input: [T; I], | ||||
|     mut default: impl FnMut() -> T, | ||||
| ) -> std::array::IntoIter<T, N> { | ||||
|     const { | ||||
|         assert!(I <= N); | ||||
|     }; | ||||
|     let mut input = input.into_iter(); | ||||
|     let array = std::array::from_fn(|_| input.next().unwrap_or_else(&mut default)); | ||||
|     let mut retval = array.into_iter(); | ||||
|     // remove unneeded trailing elements
 | ||||
|     if I < N { | ||||
|         retval.nth_back(N - I - 1); | ||||
|     } | ||||
|     retval | ||||
| } | ||||
| 
 | ||||
| macro_rules! impl_insns { | ||||
|     ( | ||||
|         #[insn = $Insn:ident, next_macro = $next_macro:ident, branch_macro = $branch_macro:ident] | ||||
|  | @ -39,6 +182,7 @@ macro_rules! impl_insns { | |||
|             $(#[$insn_meta:meta])* | ||||
|             $insn_name:ident $({ | ||||
|                 $( | ||||
|                     #[kind = $field_kind:ident] | ||||
|                     $(#[$field_meta:meta])* | ||||
|                     $field_name:ident: $field_ty:ty, | ||||
|                 )* | ||||
|  | @ -58,6 +202,91 @@ macro_rules! impl_insns { | |||
|             )* | ||||
|         } | ||||
| 
 | ||||
|         impl $Insn { | ||||
|             $vis const MAX_FIELDS: usize = { | ||||
|                 let mut retval = 0; | ||||
|                 $($( | ||||
|                     let fields = [$(stringify!($field_name),)*].len(); | ||||
|                     if retval < fields { | ||||
|                         retval = fields; | ||||
|                     } | ||||
|                 )?)* | ||||
|                 retval | ||||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         impl $Insn { | ||||
|             $vis const fn fields_unit(&self) -> &'static [InsnField<InsnFieldTypeTransformUnit>] { | ||||
|                 match self { | ||||
|                     $( | ||||
|                         $Insn::$insn_name {..} => &[ | ||||
|                             $($(InsnField { | ||||
|                                 ty: <$field_ty as InsnFieldTrait>::UNIT, | ||||
|                                 kind: InsnFieldKind::$field_kind, | ||||
|                             },)*)? | ||||
|                         ], | ||||
|                     )* | ||||
|                 } | ||||
|             } | ||||
|             $vis fn fields<'a>(&'a self) -> std::array::IntoIter<InsnField<InsnFieldTypeTransformRef<'a>>, { $Insn::MAX_FIELDS }> { | ||||
|                 match self { | ||||
|                     $( | ||||
|                         $Insn::$insn_name $({ | ||||
|                             $($field_name,)* | ||||
|                         })? => make_array_into_iter([ | ||||
|                                 $($(InsnField { | ||||
|                                     ty: <$field_ty as InsnFieldTrait>::variant($field_name), | ||||
|                                     kind: InsnFieldKind::$field_kind, | ||||
|                                 },)*)? | ||||
|                             ], | ||||
|                             || InsnField { | ||||
|                                 ty: InsnFieldType::empty(), | ||||
|                                 kind: InsnFieldKind::Immediate, | ||||
|                             }, | ||||
|                         ), | ||||
|                     )* | ||||
|                 } | ||||
|             } | ||||
|             $vis fn fields_mut<'a>(&'a mut self) -> std::array::IntoIter<InsnField<InsnFieldTypeTransformRefMut<'a>>, { $Insn::MAX_FIELDS }> { | ||||
|                 match self { | ||||
|                     $( | ||||
|                         $Insn::$insn_name $({ | ||||
|                             $($field_name,)* | ||||
|                         })? => make_array_into_iter([ | ||||
|                                 $($(InsnField { | ||||
|                                     ty: <$field_ty as InsnFieldTrait>::variant($field_name), | ||||
|                                     kind: InsnFieldKind::$field_kind, | ||||
|                                 },)*)? | ||||
|                             ], | ||||
|                             || InsnField { | ||||
|                                 ty: InsnFieldType::empty(), | ||||
|                                 kind: InsnFieldKind::Immediate, | ||||
|                             }, | ||||
|                         ), | ||||
|                     )* | ||||
|                 } | ||||
|             } | ||||
|             $vis fn into_fields(self) -> std::array::IntoIter<InsnField<InsnFieldTypeTransformValue>, { $Insn::MAX_FIELDS }> { | ||||
|                 match self { | ||||
|                     $( | ||||
|                         $Insn::$insn_name $({ | ||||
|                             $($field_name,)* | ||||
|                         })? => make_array_into_iter([ | ||||
|                                 $($(InsnField { | ||||
|                                     ty: <$field_ty as InsnFieldTrait>::variant($field_name), | ||||
|                                     kind: InsnFieldKind::$field_kind, | ||||
|                                 },)*)? | ||||
|                             ], | ||||
|                             || InsnField { | ||||
|                                 ty: InsnFieldType::empty(), | ||||
|                                 kind: InsnFieldKind::Immediate, | ||||
|                             }, | ||||
|                         ), | ||||
|                     )* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl $State { | ||||
|             $vis fn $run(&mut $self) -> $run_ret_ty { | ||||
|                 let mut $state = $state_init; | ||||
|  | @ -497,6 +726,11 @@ macro_rules! make_state_part_kinds { | |||
|                     $($type_field: self.$type_field.index_array(element_size.$type_field, index),)* | ||||
|                 } | ||||
|             } | ||||
|             pub(crate) fn offset(self, offset: TypeIndex) -> Self { | ||||
|                 Self { | ||||
|                     $($type_field: self.$type_field.offset(offset.$type_field),)* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||||
|  | @ -509,6 +743,14 @@ macro_rules! make_state_part_kinds { | |||
|             $(pub(crate) $type_field: StatePartIndex<$TypeKind>,)* | ||||
|         } | ||||
| 
 | ||||
|         impl TypeIndex { | ||||
|             pub(crate) fn offset(self, offset: TypeIndex) -> Self { | ||||
|                 Self { | ||||
|                     $($type_field: self.$type_field.offset(offset.$type_field),)* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         #[derive(Debug)] | ||||
|         pub(crate) struct State { | ||||
|             pub(crate) insns: Interned<Insns<InsnsBuildingDone>>, | ||||
|  | @ -678,20 +920,17 @@ impl<T> Drop for BorrowedStack<'_, T> { | |||
| #[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 empty() -> Self { | ||||
|         Self { | ||||
|             name: Interned::default(), | ||||
|         } | ||||
|     } | ||||
|     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, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -728,6 +967,15 @@ impl<K: StatePartKind> StatePartIndex<K> { | |||
|     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 { | ||||
|             value: self | ||||
|                 .value | ||||
|                 .checked_add(offset.value) | ||||
|                 .expect("offset too big"), | ||||
|             _phantom: PhantomData, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K: StatePartKind> fmt::Debug for StatePartIndex<K> { | ||||
|  | @ -870,6 +1118,13 @@ impl<K: StatePartKind> StatePartIndexRange<K> { | |||
|             _phantom: PhantomData, | ||||
|         }) | ||||
|     } | ||||
|     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 { | ||||
|  | @ -1180,6 +1435,65 @@ impl State { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| fn bigint_pow2(width: usize) -> Interned<BigInt> { | ||||
|     #[derive(Copy, Clone, PartialEq, Eq, Hash)] | ||||
|     struct MyMemoize; | ||||
|     impl Memoize for MyMemoize { | ||||
|         type Input = usize; | ||||
|         type InputOwned = usize; | ||||
|         type Output = Interned<BigInt>; | ||||
| 
 | ||||
|         fn inner(self, input: &Self::Input) -> Self::Output { | ||||
|             (BigInt::one() << *input).intern_sized() | ||||
|         } | ||||
|     } | ||||
|     MyMemoize.get(&width) | ||||
| } | ||||
| 
 | ||||
| fn bigint_mask(width: usize) -> Interned<BigInt> { | ||||
|     #[derive(Copy, Clone, PartialEq, Eq, Hash)] | ||||
|     struct MyMemoize; | ||||
|     impl Memoize for MyMemoize { | ||||
|         type Input = usize; | ||||
|         type InputOwned = usize; | ||||
|         type Output = Interned<BigInt>; | ||||
| 
 | ||||
|         fn inner(self, input: &Self::Input) -> Self::Output { | ||||
|             ((BigInt::one() << *input) - BigInt::one()).intern_sized() | ||||
|         } | ||||
|     } | ||||
|     MyMemoize.get(&width) | ||||
| } | ||||
| 
 | ||||
| fn bigint_not_mask(width: usize) -> Interned<BigInt> { | ||||
|     #[derive(Copy, Clone, PartialEq, Eq, Hash)] | ||||
|     struct MyMemoize; | ||||
|     impl Memoize for MyMemoize { | ||||
|         type Input = usize; | ||||
|         type InputOwned = usize; | ||||
|         type Output = Interned<BigInt>; | ||||
| 
 | ||||
|         fn inner(self, input: &Self::Input) -> Self::Output { | ||||
|             (-BigInt::one() << *input).intern_sized() | ||||
|         } | ||||
|     } | ||||
|     MyMemoize.get(&width) | ||||
| } | ||||
| 
 | ||||
| fn cast_bigint_to_sint(src: &BigInt, dest_width: usize) -> BigInt { | ||||
|     if dest_width == 0 { | ||||
|         BigInt::ZERO | ||||
|     } else if src.bit((dest_width - 1) as u64) { | ||||
|         src | &*bigint_not_mask(dest_width) | ||||
|     } else { | ||||
|         src & &*bigint_mask(dest_width) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn cast_bigint_to_uint(src: &BigInt, dest_width: usize) -> BigInt { | ||||
|     src & &*bigint_mask(dest_width) | ||||
| } | ||||
| 
 | ||||
| impl_insns! { | ||||
|     #[insn = Insn, next_macro = next, branch_macro = branch] | ||||
|     pub(crate) fn State::run(&mut self) -> () { | ||||
|  | @ -1189,235 +1503,299 @@ impl_insns! { | |||
|         main_loop!(); | ||||
|         cleanup! {} | ||||
|     } | ||||
|     CopySmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         state.small_slots[dest] = state.small_slots[src]; | ||||
|         next!(); | ||||
|     } | ||||
|     CopyBig { | ||||
|     Copy { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         src: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let [dest, src] = state.big_slots.get_many_mut([dest, src]); | ||||
|         dest.clone_from(src); | ||||
|         if dest != src { | ||||
|             let [dest, src] = state.big_slots.get_many_mut([dest, src]); | ||||
|             dest.clone_from(src); | ||||
|         } | ||||
|         next!(); | ||||
|     } | ||||
|     SExtSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         /// number of bits in a [`SmallSInt`] that aren't used
 | ||||
|         unused_bit_count: u8, | ||||
|     } => { | ||||
|         let mut value = state.small_slots[src] as SmallSInt; | ||||
|         value <<= unused_bit_count; | ||||
|         value >>= unused_bit_count; | ||||
|         state.small_slots[dest] = value as SmallUInt; | ||||
|         next!(); | ||||
|     } | ||||
|     ZExtSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         /// number of bits in a [`SmallUInt`] that aren't used
 | ||||
|         unused_bit_count: u8, | ||||
|     } => { | ||||
|         let mut value = state.small_slots[src]; | ||||
|         value <<= unused_bit_count; | ||||
|         value >>= unused_bit_count; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     SExtSmallToBig { | ||||
|     CastToSInt { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         /// number of bits in a [`SmallSInt`] that aren't used
 | ||||
|         unused_bit_count: u8, | ||||
|         #[kind = Input] | ||||
|         src: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         dest_width: usize, | ||||
|     } => { | ||||
|         let mut value = state.small_slots[src] as SmallSInt; | ||||
|         value <<= unused_bit_count; | ||||
|         value >>= unused_bit_count; | ||||
|         state.big_slots[dest] = value.into(); | ||||
|         let value = cast_bigint_to_sint(&state.big_slots[src], dest_width); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     ZExtSmallToBig { | ||||
|     CastToUInt { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         /// number of bits in a [`SmallUInt`] that aren't used
 | ||||
|         unused_bit_count: u8, | ||||
|         #[kind = Input] | ||||
|         src: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         dest_width: usize, | ||||
|     } => { | ||||
|         let mut value = state.small_slots[src]; | ||||
|         value <<= unused_bit_count; | ||||
|         value >>= unused_bit_count; | ||||
|         state.big_slots[dest] = value.into(); | ||||
|         let value = cast_bigint_to_uint(&state.big_slots[src], dest_width); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     AndSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = lhs & rhs; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     OrSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = lhs | rhs; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     XorSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = lhs ^ rhs; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     NotSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let value = state.small_slots[src]; | ||||
|         state.small_slots[dest] = !value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpEqSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = (lhs == rhs) as SmallUInt; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpNeSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = (lhs != rhs) as SmallUInt; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpLTSmallUInt { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = (lhs < rhs) as SmallUInt; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpLESmallUInt { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = (lhs <= rhs) as SmallUInt; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpLTSmallSInt { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs] as SmallSInt; | ||||
|         let rhs = state.small_slots[rhs] as SmallSInt; | ||||
|         let value = (lhs < rhs) as SmallUInt; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpLESmallSInt { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs] as SmallSInt; | ||||
|         let rhs = state.small_slots[rhs] as SmallSInt; | ||||
|         let value = (lhs <= rhs) as SmallUInt; | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     AddSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = lhs.wrapping_add(rhs); | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     SubSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = lhs.wrapping_sub(rhs); | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     NegSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         src: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let value = state.small_slots[src]; | ||||
|         let value = value.wrapping_neg(); | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     NegBig { | ||||
|     And { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] & &state.big_slots[rhs]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Or { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] | &state.big_slots[rhs]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Xor { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] ^ &state.big_slots[rhs]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     NotS { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         src: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = !&state.big_slots[src]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     NotU { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         src: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         width: usize, | ||||
|     } => { | ||||
|         let value = &state.big_slots[src] ^ &*bigint_mask(width); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Neg { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         src: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = -&state.big_slots[src]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     MulSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         lhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         rhs: StatePartIndex<StatePartKindSmallSlots>, | ||||
|     } => { | ||||
|         let lhs = state.small_slots[lhs]; | ||||
|         let rhs = state.small_slots[rhs]; | ||||
|         let value = lhs.wrapping_mul(rhs); | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     ConstSmall { | ||||
|         dest: StatePartIndex<StatePartKindSmallSlots>, | ||||
|         value: SmallUInt, | ||||
|     } => { | ||||
|         state.small_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     ConstBig { | ||||
|     Add { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] + &state.big_slots[rhs]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     SubS { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] - &state.big_slots[rhs]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     SubU { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         dest_width: usize, | ||||
|     } => { | ||||
|         let mut value = &state.big_slots[lhs] - &state.big_slots[rhs]; | ||||
|         value &= &*bigint_mask(dest_width); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Mul { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] * &state.big_slots[rhs]; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Div { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = state.big_slots[lhs].checked_div(&state.big_slots[rhs]).unwrap_or(BigInt::ZERO); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Rem { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         // no checked_rem?!
 | ||||
|         let value = if state.big_slots[rhs].is_zero() { | ||||
|             BigInt::ZERO | ||||
|         } else { | ||||
|             &state.big_slots[lhs] % &state.big_slots[rhs] | ||||
|         }; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     DynShl { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] << state.big_slots[rhs].to_usize().expect("shl by invalid value"); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     DynShr { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         assert!(!state.big_slots[rhs].is_negative(), "shr by invalid value"); | ||||
|         let value = state.big_slots[rhs].to_usize().map_or(BigInt::ZERO, |rhs| &state.big_slots[lhs] >> rhs); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Shl { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         rhs: usize, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] << rhs; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Shr { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         rhs: usize, | ||||
|     } => { | ||||
|         let value = &state.big_slots[lhs] >> rhs; | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpEq { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let lhs = &state.big_slots[lhs]; | ||||
|         let rhs = &state.big_slots[rhs]; | ||||
|         let value = BigInt::from(lhs == rhs); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpNe { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let lhs = &state.big_slots[lhs]; | ||||
|         let rhs = &state.big_slots[rhs]; | ||||
|         let value = BigInt::from(lhs != rhs); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpLt { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let lhs = &state.big_slots[lhs]; | ||||
|         let rhs = &state.big_slots[rhs]; | ||||
|         let value = BigInt::from(lhs < rhs); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     CmpLe { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         lhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Input] | ||||
|         rhs: StatePartIndex<StatePartKindBigSlots>, | ||||
|     } => { | ||||
|         let lhs = &state.big_slots[lhs]; | ||||
|         let rhs = &state.big_slots[rhs]; | ||||
|         let value = BigInt::from(lhs <= rhs); | ||||
|         state.big_slots[dest] = value; | ||||
|         next!(); | ||||
|     } | ||||
|     Const { | ||||
|         #[kind = Output] | ||||
|         dest: StatePartIndex<StatePartKindBigSlots>, | ||||
|         #[kind = Immediate] | ||||
|         value: Interned<BigInt>, | ||||
|     } => { | ||||
|         state.big_slots[dest].clone_from(&value); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue