fuel_vm/state/debug.rs
1use fuel_asm::Instruction;
2use fuel_types::{
3 ContractId,
4 Word,
5};
6
7use crate::consts::VM_MAX_RAM;
8
9#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11/// Breakpoint description that binds a tuple `(contract, $pc)` to a debugger
12/// implementation.
13///
14/// Breakpoints should be context-sensitive; hence, should target contract Ids.
15///
16/// For script/predicate verification, the contract id should be zero.
17pub struct Breakpoint {
18 contract: ContractId,
19 pc: Word,
20}
21
22impl Breakpoint {
23 pub(crate) const fn raw(contract: ContractId, pc: Word) -> Self {
24 Self { contract, pc }
25 }
26
27 /// Create a new contract breakpoint
28 ///
29 /// The `$pc` is provided in op count and internally is multiplied by the op
30 /// size. Also, the op count is always relative to `$is` so it should
31 /// consider only the bytecode of the contract.
32 ///
33 /// Panics if the `pc` cannot ever fit into the VM memory.
34 pub const fn new(contract: ContractId, pc: Word) -> Self {
35 let pc = pc.saturating_mul(Instruction::SIZE as Word);
36 assert!(pc <= VM_MAX_RAM, "Breakpoint cannot fit into vm memory");
37 Self::raw(contract, pc)
38 }
39
40 /// Create a new script breakpoint
41 ///
42 /// The `$pc` is provided in op count and internally is multiplied by the op
43 /// size
44 pub fn script(pc: Word) -> Self {
45 let contract = Default::default();
46
47 Self::new(contract, pc)
48 }
49
50 /// Contract that will trigger the breakpoint.
51 pub const fn contract(&self) -> &ContractId {
52 &self.contract
53 }
54
55 /// Program counter that will trigger the breakpoint.
56 pub const fn pc(&self) -> Word {
57 self.pc
58 }
59}
60
61#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63/// State evaluation of the interpreter that will describe if a program should
64/// break or continue.
65pub enum DebugEval {
66 /// This evaluation should break the program in the location described in
67 /// `Breakpoint`.
68 Breakpoint(Breakpoint),
69 /// This evaluation should not break the program.
70 #[default]
71 Continue,
72}
73
74impl From<Breakpoint> for DebugEval {
75 fn from(b: Breakpoint) -> Self {
76 Self::Breakpoint(b)
77 }
78}
79
80impl DebugEval {
81 /// Flag whether the program execution should break.
82 pub const fn should_continue(&self) -> bool {
83 matches!(self, Self::Continue)
84 }
85
86 /// Return a breakpoint description if the current evaluation should break;
87 /// return `None` otherwise.
88 pub const fn breakpoint(&self) -> Option<&Breakpoint> {
89 match self {
90 Self::Breakpoint(b) => Some(b),
91 _ => None,
92 }
93 }
94}