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