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