Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/pulley/src/interp/debug.rs
1692 views
1
//! Primitive support for debugging Pulley
2
//!
3
//! This `Debug` visitor defined in this module is what's actually used as part
4
//! of the interpreter loop in Pulley. Due to the code size impact of always
5
//! including this and the runtime overhead of always checking a flag this is
6
//! enabled/disabled via a `const DEBUG` below. This is currently only really
7
//! suitable for one-off debugging while developing locally.
8
//!
9
//! The hope is that this'll eventually evolve into something more useful, but
10
//! for now it's a quick-and-easy way to dump all the instructions that are
11
//! executed as well as the values in various registers.
12
//!
13
//! If debugging is disabled, or in `#[no_std]` mode, then this module should
14
//! compile away (e.g. a "zero cost abstraction").
15
16
use super::Interpreter;
17
use crate::decode::{ExtendedOpVisitor, OpVisitor};
18
use crate::imms::*;
19
use crate::regs::*;
20
use alloc::string::ToString;
21
22
// Whether or not debugging is enabled at all.
23
const DEBUG: bool = false;
24
25
// Whether or not these registers are dumped between each instruction.
26
const DEBUG_X_REGS: bool = true;
27
const DEBUG_F_REGS: bool = false;
28
29
#[cfg(not(feature = "std"))]
30
macro_rules! print {
31
($($t:tt)*) => ({ let _ = format_args!($($t)*); })
32
}
33
#[cfg(not(feature = "std"))]
34
macro_rules! println {
35
() => ();
36
($($t:tt)*) => ({ let _ = format_args!($($t)*); })
37
}
38
39
#[repr(transparent)]
40
pub(super) struct Debug<'a>(pub Interpreter<'a>);
41
42
macro_rules! debug_then_delegate {
43
(
44
$(
45
$( #[$attr:meta] )*
46
$snake_name:ident = $name:ident $( {
47
$(
48
$( #[$field_attr:meta] )*
49
$field:ident : $field_ty:ty
50
),*
51
} )? ;
52
)*
53
) => {
54
$(
55
$( #[$attr] )*
56
fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return {
57
if DEBUG {
58
println!(
59
concat!(
60
stringify!($snake_name),
61
$(
62
$(
63
" ",
64
stringify!($field),
65
"={:?}",
66
)*
67
)?
68
),
69
$($($field),*)?
70
);
71
}
72
self.0.$snake_name($( $($field),* )?)
73
}
74
)*
75
}
76
}
77
78
impl<'a> OpVisitor for Debug<'a> {
79
type BytecodeStream = <Interpreter<'a> as OpVisitor>::BytecodeStream;
80
type Return = <Interpreter<'a> as OpVisitor>::Return;
81
82
fn bytecode(&mut self) -> &mut Self::BytecodeStream {
83
self.0.bytecode()
84
}
85
86
fn before_visit(&mut self) {
87
self.0.record_executing_pc_for_profiling();
88
if !DEBUG {
89
return;
90
}
91
print!("\t{:?}\t", self.bytecode().as_ptr());
92
}
93
94
fn after_visit(&mut self) {
95
if !DEBUG {
96
return;
97
}
98
if DEBUG_X_REGS {
99
for (i, regs) in self.0.state.x_regs.chunks(4).enumerate() {
100
print!("\t\t");
101
for (j, reg) in regs.iter().enumerate() {
102
let n = i * 4 + j;
103
let val = reg.get_u64();
104
let reg = XReg::new(n as u8).unwrap().to_string();
105
print!(" {reg:>3}={val:#018x}");
106
}
107
println!();
108
}
109
}
110
if DEBUG_F_REGS {
111
for (i, regs) in self.0.state.f_regs.chunks(4).enumerate() {
112
print!("\t\t");
113
for (j, reg) in regs.iter().enumerate() {
114
let n = i * 4 + j;
115
let val = reg.get_f64().to_bits();
116
let reg = FReg::new(n as u8).unwrap().to_string();
117
print!(" {reg:>3}={val:#018x}");
118
}
119
println!();
120
}
121
}
122
}
123
124
for_each_op!(debug_then_delegate);
125
}
126
127
impl<'a> ExtendedOpVisitor for Debug<'a> {
128
for_each_extended_op!(debug_then_delegate);
129
}
130
131