Skip to main content

instruction_execution

Attribute Macro instruction_execution 

Source
#[instruction_execution]
Expand description

Processes #[instruction_execution] attribute on enum execution implementation.

It must be applied to implementation of traits ExecutableInstructionOperands, ExecutableInstructionCsr and ExecutableInstruction, whose definition is already annotated with #[instruction] macro.

Similarly to that macro, this macro will process the contents of trait implementations.

ExecutableInstructionOperands::get_rs1_rs2_operands() method will be generated from scratch.

ExecutableInstruction::execute(), ExecutableInstructionCsr::prepare_csr_read() and ExecutableInstructionCsr::prepare_csr_write() methods will end up containing both inherited and own execution logic according to the ordering set in #[instruction].

There are constraints on the ExecutableInstruction::execute() method body, it must have one or both (but nothing else) of the following:

  • matching in the following style: match self { Self::Variant { .. } }
    • note that Self must be used instead of the explicit type name, such that it works when inherited
  • ExecutionResult::ContinueNoWrite expression.

The composed execute() body is not kept as one large match. Instead, each match arm (both own and inherited) is turned into its own #[inline(always)] free function, generated right next to execute(), and execute() itself is reduced to a lean match that dispatches to those functions (with the impl’s generic parameters specified explicitly via turbofish, since a free function has no Self for them to be inferred from). This is purely an implementation detail; those functions are not meant to be used or referred to directly.

Alongside execute(), an implementation of ThreadedExecutableInstruction is generated for the same enum, out of the very same arms. It is done in a somewhat opaque way here with the hopes that it would become possible to move the ThreadedExecutableInstruction::execute_threaded() method into ExecutableInstruction trait at some point. Right now it is not possible to mix const and non-const methods in the same trait.

If execute() carries #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(..))], it is stripped from execute() itself (which becomes a plain dispatcher, so the attribute would no longer serve its purpose there) and placed on every one of those generated functions instead, so each variant’s execution logic is checked for panics individually. Since this depends on execute() in the implementation currently being processed specifically carrying this attribute, an implementation that inherits from a lower-level one that has it, but does not itself repeat it will not get it applied to its own generated functions either.

Also requires process_instruction_macros() in build.rs to function, see #[instruction] macro documentation.

ExecutableInstructionCsr::prepare_csr_read() and ExecutableInstructionCsr::prepare_csr_write() methods can’t contain return in them, similarly to instruction decoding implementation processed by #[instruction] macro.