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}