Struct Encoding
pub struct Encoding<A: Arch, C> {
pub bits: Vec<Bit>,
pub errors: Vec<bool>,
pub parts: Vec<Part<A>>,
pub dataflows: Dataflows<A, C>,
pub write_ordering: Vec<WriteOrdering>,
}
Expand description
Fields§
§bits: Vec<Bit>
The bitpattern
errors: Vec<bool>
errors[N]
is true if the analysis for bits[N]
produced an error, and the correct Bit
was inferred from context.
parts: Vec<Part<A>>
A part mapping that maps the value of parts to registers/memory computations or immediate values that can be filled in the dataflows
.
dataflows: Dataflows<A, C>
The dataflows of the encoding.
write_ordering: Vec<WriteOrdering>
Describes the ordering in which outputs must be written in case overlapping outputs are possible. If there are multiple applicable orderings, they should all be applied. If multiple orderings apply, they may not conflict.
Implementations§
§impl<A: Arch, C> Encoding<A, C>
impl<A: Arch, C> Encoding<A, C>
pub fn unchecked_instr(&self, part_values: &[u64]) -> Instruction
pub fn unchecked_instr(&self, part_values: &[u64]) -> Instruction
Returns the instruction corresponding to the provided part values, without checking whether the provided part values are valid.
If the provided part values are invalid, a garbage instruction is returned.
pub fn bitpattern_as_filter(&self) -> InstructionFilter
pub fn bitpattern_as_filter(&self) -> InstructionFilter
Converts the bitpattern to a single filter. Does not account for invalid part values.
If you want filters that match the covered instructions exactly, use Encoding::filters
instead.
pub fn prefix_matches(
&self,
instr: &Instruction,
num_bits_to_check: usize,
) -> bool
pub fn prefix_matches( &self, instr: &Instruction, num_bits_to_check: usize, ) -> bool
Returns true if the first num_bits_to_check
of instr
match the encoding.
pub fn part_values_to_instr(&self, part_values: &[Option<u64>]) -> Instruction
pub fn part_values_to_instr(&self, part_values: &[Option<u64>]) -> Instruction
Computes the Instruction
that corresponds to the part values provided.
When a part value is None
, the current part value of the Encoding is picked.
You must ensure that the part values are valid for this encoding.
Passing invalid part values produces an Instruction
that is not covered by the encoding.
pub fn all_part_values_to_instr(&self, part_values: &[u64]) -> Instruction
pub fn all_part_values_to_instr(&self, part_values: &[u64]) -> Instruction
Computes the Instruction
that corresponds to the part values provided.
You must ensure that the part values are valid for this encoding.
Passing invalid part values produces an Instruction
that is not covered by the encoding.
pub fn part_bit_indices(
&self,
part_index: usize,
) -> impl Iterator<Item = usize> + '_
pub fn part_bit_indices( &self, part_index: usize, ) -> impl Iterator<Item = usize> + '_
Returns the bit indices of the part.
In other words, returns all indices for which self.bits[N] == Bit::Part(part_index)
.
pub fn overlapping_outputs(
&self,
) -> impl Iterator<Item = (usize, HashSet<usize>)> + '_
pub fn overlapping_outputs( &self, ) -> impl Iterator<Item = (usize, HashSet<usize>)> + '_
Iterates over all of output indices, and a HashSet
of overlapping output indices.
An output index is only yielded if it is overlapping with at least one other output index.
Outputs overlap if their destinations overlap. See Dest::overlaps
.
pub fn instr(&self) -> &Instruction
pub fn instr(&self) -> &Instruction
Returns the current Instruction
of the encoding.
While encodings cover a group of instructions, the dataflows and memory accesses are always instantiated for a specific instruction.
The Encoding::canonicalize
function changes the current instruction to the instruction where all part have the lowest valid value.
This means that the Instruction
of an encoding typically has mostly 0s for the bits that are parts or DontCare bits.
pub fn covers_some_instr(&self) -> bool
pub fn covers_some_instr(&self) -> bool
Determines if there is any instruction that is covered by this encoding.
pub fn filters(&self) -> Vec<InstructionFilter>
pub fn filters(&self) -> Vec<InstructionFilter>
Returns a Vec
of filters that describe exactly which instructions are covered by this encoding.
The filters may overlap.
pub fn all_outputs_have_computations(&self) -> bool
pub fn all_outputs_have_computations(&self) -> bool
Returns true if all dataflow outputs have a computation.
pub fn map_computations<CNew>(
&self,
f: impl Fn(&Inputs<A>, &C) -> Option<CNew>,
) -> Encoding<A, CNew>
pub fn map_computations<CNew>( &self, f: impl Fn(&Inputs<A>, &C) -> Option<CNew>, ) -> Encoding<A, CNew>
Remaps the computations to a new value.
pub fn set_computation(&mut self, index: usize, computation: C)
pub fn set_computation(&mut self, index: usize, computation: C)
Replaces the computation for the output in position index
with computation
.
pub fn find_best_reg_choices(
&self,
_alter_sizes: bool,
eval: impl Fn(&[u64]) -> usize,
) -> Option<Vec<Option<u64>>>
pub fn find_best_reg_choices( &self, _alter_sizes: bool, eval: impl Fn(&[u64]) -> usize, ) -> Option<Vec<Option<u64>>>
Determines the part values that give the “best” register assignments for analysis.
The “best” assignment in this case, is an assignment where as many different registers as possible are used. This allows encoding analysis and synthesis to produce better results.
pub fn extract_parts(&self, instr: &Instruction) -> Vec<u64>
pub fn extract_parts(&self, instr: &Instruction) -> Vec<u64>
Returns the part values for the provided instr
.
You must make sure that instr
is covered by this encoding.
In many cases, this function will panic if it is invoked with an instruction not covered by this encoding.
It will not panic if all fixed bits match, but one of the part values is not a valid value according to the part mapping.
pub fn integrity_check(&self) -> Result<(), IntegrityError>
pub fn integrity_check(&self) -> Result<(), IntegrityError>
Verifies whether the encoding is internally consistent.
pub fn split_flag_output(&mut self)
pub fn split_flag_output(&mut self)
Splits all flag outputs in the dataflows into a separate output for each destination register byte.
pub fn preview_make_bit_fixed(&self, bit_index: usize) -> (usize, usize)
pub fn preview_make_bit_fixed(&self, bit_index: usize) -> (usize, usize)
returns what kinds of mapping will be removed: (good_mapping, invalid_mapping)
pub fn is_bit_involved_with_address_reg_or_computation(&self, bit: Bit) -> bool
pub fn is_bit_involved_with_address_reg_or_computation(&self, bit: Bit) -> bool
Returns true if the provided bit
is involved in the computation of a memory address, as a register or memory computation.
Otherwise, returns false.
Note: If the bit
is an immediate value that is used in the computation of a memory address, false is returned.
pub fn is_bit_involved_with_dataflow_reg(&self, bit: Bit) -> bool
pub fn is_bit_involved_with_dataflow_reg(&self, bit: Bit) -> bool
Returns true if the provided bit
affects a register used in a dataflow.
pub fn is_bit_imm(&self, bit: Bit) -> bool
pub fn is_bit_imm(&self, bit: Bit) -> bool
Returns true if the provided bit
is part of an immediate value.
pub fn is_bit_dataflow_imm(&self, bit: Bit) -> bool
pub fn is_bit_dataflow_imm(&self, bit: Bit) -> bool
Returns true if the provided bit
is part of an immediate value that is used in at least one dataflow.
pub fn part_value_locations(
&self,
) -> impl Iterator<Item = (usize, FlowValueLocation)> + '_
pub fn part_value_locations( &self, ) -> impl Iterator<Item = (usize, FlowValueLocation)> + '_
Iterates over all (part_index, loc)
tuples, where part_index
is the index of a part in the encoding and loc
is a location where that part is used.
The same part_index
may occur multiple times with different values for loc
.
§impl<A: Arch, C: Clone + Debug> Encoding<A, C>
impl<A: Arch, C: Clone + Debug> Encoding<A, C>
pub fn instantiate(
&self,
part_values: &[u64],
) -> Result<Dataflows<A, C>, InstantiationError>
pub fn instantiate( &self, part_values: &[u64], ) -> Result<Dataflows<A, C>, InstantiationError>
Instantiates the encoding with the provided part values. Returns the dataflows for the instruction that corresponds to these part values.
Use Self::extract_parts
to convert a covered Instruction
into part values.
pub fn random_instrs<'a>(
&'a self,
part_value: &'a [Option<u64>],
rng: &'a mut impl Rng,
) -> impl Iterator<Item = Instruction> + 'a
pub fn random_instrs<'a>( &'a self, part_value: &'a [Option<u64>], rng: &'a mut impl Rng, ) -> impl Iterator<Item = Instruction> + 'a
Iterates over covered instructions randomly. May yield the same instruction multiple times. Does not terminate.
part_values
can be used to restrict the yielded instructions to have fixed part values.
Even if all part_values
are set, different instructions might be yielded if one or more bits are Bit::DontCare
.
§impl<A: Arch, C: Computation> Encoding<A, C>
impl<A: Arch, C: Computation> Encoding<A, C>
pub fn instantiate_partially(
&self,
part_values: &[Option<u64>],
) -> Result<Encoding<A, C>, InstantiationError>
pub fn instantiate_partially( &self, part_values: &[Option<u64>], ) -> Result<Encoding<A, C>, InstantiationError>
Returns a new encoding where the parts for which part_values
is set to Some(..)
are instantiated.
pub fn make_bit_fixed(
&mut self,
bit_index: usize,
) -> Result<(), InstantiationError>
pub fn make_bit_fixed( &mut self, bit_index: usize, ) -> Result<(), InstantiationError>
Replaces the bit at position bit_index
with a fixed bit.
The fixed bit is taken from Self::instr
.
pub fn remove_byte(&mut self, index: usize)
pub fn remove_byte(&mut self, index: usize)
Removes the byte at position index
(counting from the left) from the encoding.
Panics if this would remove any bitpatterns.
If you want to remove a byte that contains parts, first call Self::make_bit_fixed
for each part bit in that byte.
pub fn best_instr(&self) -> Option<Instruction>
pub fn best_instr(&self) -> Option<Instruction>
Determines the best instruction to use for encoding analysis.
The primary criteria to determine the “best” instruction are:
- it uses as many different registers as possible
- fills immediate values such that there are at least two bits 1 and two bits 0 in each byte.
pub fn num_wildcard_bits(&self) -> usize
pub fn num_wildcard_bits(&self) -> usize
Returns the number of bits that aren’t Fixed
in the encoding.
This is equivalent to the number of Part
bits and DontCare
bits.
pub fn num_dontcare_bits(&self) -> usize
pub fn num_dontcare_bits(&self) -> usize
Returns the number of bits that are DontCare
in the encoding.
pub fn iter_instrs<'a>(
&'a self,
fixed_value: &'a [Option<u64>],
iter_dontcare: bool,
) -> impl Iterator<Item = Instruction> + 'a
pub fn iter_instrs<'a>( &'a self, fixed_value: &'a [Option<u64>], iter_dontcare: bool, ) -> impl Iterator<Item = Instruction> + 'a
Iterates over all possible instructions that match the encoding.
If fixed_value[N]
is Some(val)
, then only instructions where part N
is val are returned.
pub fn canonicalize(&self) -> Encoding<A, C>
pub fn canonicalize(&self) -> Encoding<A, C>
Converts the encoding into a canonical form. This sets all parts to the lowest valid value.
pub fn restrict_to(
&self,
filter: &InstructionFilter,
) -> Result<Self, RestrictError>
pub fn restrict_to( &self, filter: &InstructionFilter, ) -> Result<Self, RestrictError>
Reduces the scope of the encoding such that it covers no more instructions than (but potentially less than) the provided filter
.
pub fn remove_unused_inputs(self) -> Encoding<A, C>
pub fn remove_unused_inputs(self) -> Encoding<A, C>
Removes all inputs in the dataflows that are not used in the computations. If a dataflow has no computation, the inputs are not modified.
pub fn remove_identity_assignments(self) -> Encoding<A, C>
pub fn remove_identity_assignments(self) -> Encoding<A, C>
Removes all dataflows that are always identity assignments. I.e., A := A
.
If a dataflow does not have a computation, it is not removed.
This primarily occurs in flag outputs, because these are split after enumeration.
Trait Implementations§
§impl<'de, A: Arch, C> Deserialize<'de> for Encoding<A, C>where
C: Deserialize<'de>,
impl<'de, A: Arch, C> Deserialize<'de> for Encoding<A, C>where
C: Deserialize<'de>,
§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
§impl<A: Arch, C: Computation> Display for Encoding<A, C>
impl<A: Arch, C: Computation> Display for Encoding<A, C>
§impl<A, C> JsonSchema for Encoding<A, C>
impl<A, C> JsonSchema for Encoding<A, C>
§fn schema_name() -> String
fn schema_name() -> String
§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
§fn json_schema(gen: &mut SchemaGenerator) -> Schema
fn json_schema(gen: &mut SchemaGenerator) -> Schema
§fn is_referenceable() -> bool
fn is_referenceable() -> bool
$ref
keyword. Read moreimpl<A: Eq + Arch, C: Eq> Eq for Encoding<A, C>
impl<A: Arch, C> StructuralPartialEq for Encoding<A, C>
Auto Trait Implementations§
impl<A, C> Freeze for Encoding<A, C>
impl<A, C> RefUnwindSafe for Encoding<A, C>
impl<A, C> Send for Encoding<A, C>where
C: Send,
impl<A, C> Sync for Encoding<A, C>where
C: Sync,
impl<A, C> Unpin for Encoding<A, C>
impl<A, C> UnwindSafe for Encoding<A, C>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more