openvm_transpiler/extension.rs
1use openvm_instructions::instruction::Instruction;
2
3/// Trait to add custom RISC-V instruction transpilation to OpenVM instruction format.
4/// RISC-V instructions always come in 32-bit chunks.
5/// An important feature is that multiple 32-bit RISC-V instructions can be transpiled into a single OpenVM instruction.
6/// See [process_custom](Self::process_custom) for details.
7pub trait TranspilerExtension<F> {
8 /// The `instruction_stream` provides a view of the remaining RISC-V instructions to be processed,
9 /// presented as 32-bit chunks. The [process_custom](Self::process_custom) should determine if it knows how to transpile
10 /// the next contiguous section of RISC-V instructions into an [`Instruction`].
11 /// It returns `None` if it cannot transpile. Otherwise it returns `TranspilerOutput { instructions, used_u32s }` to indicate that
12 /// `instruction_stream[..used_u32s]` should be transpiled into `instructions`.
13 fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>>;
14}
15
16pub struct TranspilerOutput<F> {
17 pub instructions: Vec<Option<Instruction<F>>>,
18 pub used_u32s: usize,
19}
20
21impl<F> TranspilerOutput<F> {
22 pub fn one_to_one(instruction: Instruction<F>) -> Self {
23 Self {
24 instructions: vec![Some(instruction)],
25 used_u32s: 1,
26 }
27 }
28
29 pub fn many_to_one(instruction: Instruction<F>, used_u32s: usize) -> Self {
30 Self {
31 instructions: vec![Some(instruction)],
32 used_u32s,
33 }
34 }
35
36 pub fn gap(gap_length: usize, used_u32s: usize) -> Self {
37 Self {
38 instructions: (0..gap_length).map(|_| None).collect(),
39 used_u32s,
40 }
41 }
42}