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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::call::CallFrame;
use crate::consts::*;
use crate::context::Context;
use crate::state::Debugger;
use fuel_tx::{Receipt, Transaction};
use fuel_types::Word;
mod alu;
mod blockchain;
mod constructors;
mod contract;
mod crypto;
mod executors;
mod flow;
mod frame;
mod gas;
mod initialization;
mod internal;
mod log;
mod memory;
mod metadata;
mod transaction;
#[cfg(feature = "debug")]
mod debug;
#[cfg(feature = "profile-any")]
use crate::profiler::{InstructionLocation, Profiler};
pub use memory::MemoryRange;
pub use metadata::InterpreterMetadata;
#[derive(Debug, Clone)]
pub struct Interpreter<S> {
registers: [Word; VM_REGISTER_COUNT],
memory: Vec<u8>,
frames: Vec<CallFrame>,
receipts: Vec<Receipt>,
tx: Transaction,
storage: S,
debugger: Debugger,
context: Context,
block_height: u32,
#[cfg(feature = "profile-any")]
profiler: Profiler,
}
impl<S> Interpreter<S> {
pub fn memory(&self) -> &[u8] {
self.memory.as_slice()
}
pub const fn registers(&self) -> &[Word] {
&self.registers
}
pub(crate) fn call_stack(&self) -> &[CallFrame] {
self.frames.as_slice()
}
pub const fn debugger(&self) -> &Debugger {
&self.debugger
}
#[allow(dead_code)]
pub(crate) const fn is_unsafe_math(&self) -> bool {
self.registers[REG_FLAG] & 0x01 == 0x01
}
#[allow(dead_code)]
pub(crate) const fn is_wrapping(&self) -> bool {
self.registers[REG_FLAG] & 0x02 == 0x02
}
pub fn receipts(&self) -> &[Receipt] {
self.receipts.as_slice()
}
#[cfg(feature = "profile-any")]
fn current_location(&self) -> InstructionLocation {
use crate::consts::*;
InstructionLocation::new(
self.frames.last().map(|frame| *frame.to()),
self.registers[REG_PC] - self.registers[REG_IS],
)
}
}
impl<S> From<Interpreter<S>> for Transaction {
fn from(vm: Interpreter<S>) -> Self {
vm.tx
}
}
impl<S> AsRef<S> for Interpreter<S> {
fn as_ref(&self) -> &S {
&self.storage
}
}
impl<S> AsMut<S> for Interpreter<S> {
fn as_mut(&mut self) -> &mut S {
&mut self.storage
}
}