fuel_vm/interpreter/
ecal.rs

1//! See `fuel-vm/examples/external.rs` for example usage.
2
3use fuel_asm::{
4    PanicReason,
5    RegId,
6};
7
8use crate::{
9    constraints::reg_key::{
10        SystemRegisters,
11        split_registers,
12    },
13    error::SimpleResult,
14    interpreter::NotSupportedEcal,
15};
16
17use super::{
18    Interpreter,
19    Memory,
20    internal::inc_pc,
21};
22
23/// ECAL opcode handler.
24///
25/// This can be cloned...
26/// * when the whole VM instance is cloned, for any reason
27/// * for each predicate when running predicates for a tx
28pub trait EcalHandler: Clone
29where
30    Self: Sized,
31{
32    /// Whether to increment PC after executing ECAL. If this is false,
33    /// the handler must increment PC itself.
34    const INC_PC: bool = true;
35
36    /// ECAL opcode handler
37    fn ecal<M, S, Tx, V>(
38        vm: &mut Interpreter<M, S, Tx, Self, V>,
39        a: RegId,
40        b: RegId,
41        c: RegId,
42        d: RegId,
43    ) -> SimpleResult<()>
44    where
45        M: Memory;
46}
47
48/// Default ECAL opcode handler function, which just errors immediately.
49impl EcalHandler for NotSupportedEcal {
50    fn ecal<M, S, Tx, V>(
51        _: &mut Interpreter<M, S, Tx, Self, V>,
52        _: RegId,
53        _: RegId,
54        _: RegId,
55        _: RegId,
56    ) -> SimpleResult<()> {
57        Err(PanicReason::EcalError)?
58    }
59}
60
61impl<M, S, Tx, Ecal, V> Interpreter<M, S, Tx, Ecal, V>
62where
63    M: Memory,
64    Ecal: EcalHandler,
65{
66    /// Executes ECAL opcode handler function and increments PC
67    pub(crate) fn external_call(
68        &mut self,
69        a: RegId,
70        b: RegId,
71        c: RegId,
72        d: RegId,
73    ) -> SimpleResult<()> {
74        Ecal::ecal(self, a, b, c, d)?;
75        let (SystemRegisters { pc, .. }, _) = split_registers(&mut self.registers);
76        if Ecal::INC_PC {
77            Ok(inc_pc(pc)?)
78        } else {
79            Ok(())
80        }
81    }
82}
83
84impl<M, S, Tx, Ecal, V> Interpreter<M, S, Tx, Ecal, V>
85where
86    Ecal: EcalHandler,
87{
88    /// Read access to the ECAL state
89    pub fn ecal_state(&self) -> &Ecal {
90        &self.ecal_state
91    }
92
93    /// Write access to the ECAL state
94    pub fn ecal_state_mut(&mut self) -> &mut Ecal {
95        &mut self.ecal_state
96    }
97}