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
6/// OpenVM instruction. 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
9    /// processed, presented as 32-bit chunks. The [process_custom](Self::process_custom) should
10    /// determine if it knows how to transpile the next contiguous section of RISC-V
11    /// instructions into an [`Instruction`]. It returns `None` if it cannot transpile.
12    /// Otherwise it returns `TranspilerOutput { instructions, used_u32s }` to indicate that
13    /// `instruction_stream[..used_u32s]` should be transpiled into `instructions`.
14    fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>>;
15}
16
17pub struct TranspilerOutput<F> {
18    pub instructions: Vec<Option<Instruction<F>>>,
19    pub used_u32s: usize,
20}
21
22impl<F> TranspilerOutput<F> {
23    pub fn one_to_one(instruction: Instruction<F>) -> Self {
24        Self {
25            instructions: vec![Some(instruction)],
26            used_u32s: 1,
27        }
28    }
29
30    pub fn many_to_one(instruction: Instruction<F>, used_u32s: usize) -> Self {
31        Self {
32            instructions: vec![Some(instruction)],
33            used_u32s,
34        }
35    }
36
37    pub fn gap(gap_length: usize, used_u32s: usize) -> Self {
38        Self {
39            instructions: (0..gap_length).map(|_| None).collect(),
40            used_u32s,
41        }
42    }
43}