[−][src]Trait peepmatic_runtime::instruction_set::InstructionSet
A trait for interfacing with actual instruction sequences.
This trait enables both:
-
peepmatic-runtime
to be used bycranelift-codegen
without a circular dependency frompeepmatic-runtime
tocranelift-codegen
to get access to Cranelift's IR types, and -
enables us to write local tests that exercise peephole optimizers on a simple, testing-only instruction set without pulling in all of Cranelift.
Finally, this should also make the task of adding support for Cranelift's
new MachInst
and vcode backend easier, since all that needs to be done is
"just" implementing this trait. (And probably add/modify some
peepmatic_runtime::operation::Operation
s as well).
Safety
See doc comment for instruction_result_bit_width
.
Associated Types
type Context
[src]
Mutable context passed into all trait methods. Can be whatever you want!
In practice, this is a FuncCursor
for cranelift-codegen
's trait
implementation.
type Operator: 'static + Copy + Debug + Eq + Hash + Into<NonZeroU32>
[src]
An operator.
type Instruction: Copy + Debug + Eq
[src]
An instruction (or identifier for an instruction).
Required methods
pub fn replace_instruction(
&self,
context: &mut Self::Context,
old: Self::Instruction,
new: Part<Self::Instruction>
) -> Self::Instruction
[src]
&self,
context: &mut Self::Context,
old: Self::Instruction,
new: Part<Self::Instruction>
) -> Self::Instruction
Replace the old
instruction with new
.
new
is either a Part::Instruction
or a constant Part::Boolean
or
Part::Integer
. In the former case, it can directly replace old
. In
the latter case, implementations of this trait should transparently
create an iconst
or bconst
instruction to wrap the given constant.
new
will never be Part::ConditionCode
.
pub fn operator<E>(
&self,
context: &mut Self::Context,
instr: Self::Instruction,
operands: &mut E
) -> Option<Self::Operator> where
E: Extend<Part<Self::Instruction>>,
[src]
&self,
context: &mut Self::Context,
instr: Self::Instruction,
operands: &mut E
) -> Option<Self::Operator> where
E: Extend<Part<Self::Instruction>>,
Get the given instruction's operator.
If the instruction isn't supported, then None
should be returned.
Additionally, if Some
is returned, then the instruction's operands
must be pushed in order into operands
. E.g. calling this method on
(iadd $x $y)
would return Some(iadd)
and extend operands
with
[$x, $y]
.
pub fn make_inst_1(
&self,
context: &mut Self::Context,
root: Self::Instruction,
operator: Self::Operator,
type: Type,
a: Part<Self::Instruction>
) -> Self::Instruction
[src]
&self,
context: &mut Self::Context,
root: Self::Instruction,
operator: Self::Operator,
type: Type,
a: Part<Self::Instruction>
) -> Self::Instruction
Make a unary instruction.
If the type is not given, then it should be inferred.
pub fn make_inst_2(
&self,
context: &mut Self::Context,
root: Self::Instruction,
operator: Self::Operator,
type: Type,
a: Part<Self::Instruction>,
b: Part<Self::Instruction>
) -> Self::Instruction
[src]
&self,
context: &mut Self::Context,
root: Self::Instruction,
operator: Self::Operator,
type: Type,
a: Part<Self::Instruction>,
b: Part<Self::Instruction>
) -> Self::Instruction
Make a binary instruction.
Operands are given as immediates first and arguments following
them. Condition codes are treated as immediates. So if we are creating
an iadd_imm
instruction, then a
will be the constant integer
immediate and b
will be the instruction whose result is the dynamic
argument.
pub fn make_inst_3(
&self,
context: &mut Self::Context,
root: Self::Instruction,
operator: Self::Operator,
type: Type,
a: Part<Self::Instruction>,
b: Part<Self::Instruction>,
c: Part<Self::Instruction>
) -> Self::Instruction
[src]
&self,
context: &mut Self::Context,
root: Self::Instruction,
operator: Self::Operator,
type: Type,
a: Part<Self::Instruction>,
b: Part<Self::Instruction>,
c: Part<Self::Instruction>
) -> Self::Instruction
Make a ternary instruction.
Operands are given as immediates first and arguments following
them. Condition codes are treated as immediates. So if we are creating
an icmp
instruction, then a
will be the condition code, and b
and
c
will be instructions whose results are the dynamic arguments.
pub fn instruction_to_constant(
&self,
context: &mut Self::Context,
inst: Self::Instruction
) -> Option<Constant>
[src]
&self,
context: &mut Self::Context,
inst: Self::Instruction
) -> Option<Constant>
Try to resolve the given instruction into a constant value.
If we can tell that the instruction returns a constant value, then
return that constant value as either a Part::Boolean
or
Part::Integer
. Otherwise, return None
.
pub fn instruction_result_bit_width(
&self,
context: &mut Self::Context,
inst: Self::Instruction
) -> u8
[src]
&self,
context: &mut Self::Context,
inst: Self::Instruction
) -> u8
Get the bit width of the given instruction's result.
Safety
There is code that makes memory-safety assumptions that the result is always one of 1, 8, 16, 32, 64, or 128. Implementors must uphold this.
pub fn native_word_size_in_bits(&self, context: &mut Self::Context) -> u8
[src]
Get the size of a native word in bits.