liblisa::encoding

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

Dataflows and semantics for a group of similar instructions. An encoding matches at least one instruction. If an encoding matches an instruction, it can be instantiated for that instruction.

Instantiation computes the Dataflows for a specific instruction.

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>

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

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

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

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

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> + '_

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>)> + '_

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

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

Determines if there is any instruction that is covered by this encoding.

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

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>

Remaps the computations to a new value.

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

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>

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>

Verifies whether the encoding is internally consistent.

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)

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

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

Returns true if the provided bit affects a register used in a dataflow.

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

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)> + '_

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>

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

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>

pub fn fix(&mut self) -> bool

Automatically fixes some consistency issues in an encoding.

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>

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)

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>

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

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

Returns the number of bits that are DontCare in the encoding.

pub fn part_size(&self, index: usize) -> usize

Returns the number of Part bits in the encoding.

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>

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>

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>

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>

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<A: Clone + Arch, C: Clone> Clone for Encoding<A, C>

§

fn clone(&self) -> Encoding<A, C>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl<A: Debug + Arch, C: Debug> Debug for Encoding<A, C>

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

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

Deserialize this value from the given Serde deserializer. Read more
§

impl<A: Arch, C: Computation> Display for Encoding<A, C>

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl<A: Hash + Arch, C: Hash> Hash for Encoding<A, C>

§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
§

impl<A, C> JsonSchema for Encoding<A, C>
where A: JsonSchema + Arch, A::Reg: JsonSchema, C: JsonSchema,

§

fn schema_name() -> String

The name of the generated JSON Schema. Read more
§

fn schema_id() -> Cow<'static, str>

Returns a string that uniquely identifies the schema produced by this type. Read more
§

fn json_schema(gen: &mut SchemaGenerator) -> Schema

Generates a JSON Schema for this type. Read more
§

fn is_referenceable() -> bool

Whether JSON Schemas generated for this type should be re-used where possible using the $ref keyword. Read more
§

impl<A: PartialEq + Arch, C: PartialEq> PartialEq for Encoding<A, C>

§

fn eq(&self, other: &Encoding<A, C>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl<A: Arch, C> Serialize for Encoding<A, C>
where C: Serialize,

§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
§

impl<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>
where <A as Arch>::Reg: RefUnwindSafe, C: RefUnwindSafe,

§

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>
where <A as Arch>::Reg: Unpin, C: Unpin,

§

impl<A, C> UnwindSafe for Encoding<A, C>
where <A as Arch>::Reg: UnwindSafe, C: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> DynClone for T
where T: Clone,

source§

fn __clone_box(&self, _: Private) -> *mut ()

§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

§

const WITNESS: W = W::MAKE

A constant of the type witness
§

impl<T> Identity for T
where T: ?Sized,

§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,