miden_debug_engine/exec/
host.rs1use alloc::{boxed::Box, collections::VecDeque, sync::Arc, vec::Vec};
2use core::num::NonZeroU32;
3
4use miden_assembly_syntax::debuginfo::SourceManager;
5use miden_core::{
6 Word,
7 events::{EventId, EventName},
8};
9use miden_debug_types::{Location, SourceFile, SourceSpan};
10use miden_mast_package::Package;
11use miden_processor::{
12 BaseHost, ExecutionError, LoadedMastForest, MastForestStore, MemMastForestStore,
13 ProcessorState, SyncHost,
14 advice::AdviceMutation,
15 event::{EventError, EventHandler, EventHandlerRegistry},
16};
17
18use super::advice::clone_advice_mutations;
19use crate::Event;
20
21pub struct DebuggerHost<S: SourceManager + ?Sized> {
25 store: MemMastForestStore,
26 event_handlers: EventHandlerRegistry,
27 #[allow(clippy::type_complexity)]
28 on_assert_failed: Option<Box<dyn FnMut(&ProcessorState<'_>, u32)>>,
29 source_manager: Arc<S>,
30 event_replay: VecDeque<Vec<AdviceMutation>>,
31 event_recording: Option<Vec<Vec<AdviceMutation>>>,
32}
33impl<S> DebuggerHost<S>
34where
35 S: SourceManager + ?Sized,
36{
37 pub fn new(source_manager: Arc<S>) -> Self {
39 Self {
40 store: Default::default(),
41 event_handlers: EventHandlerRegistry::default(),
42 on_assert_failed: None,
43 source_manager,
44 event_replay: VecDeque::new(),
45 event_recording: None,
46 }
47 }
48
49 pub fn set_event_replay(&mut self, events: VecDeque<Vec<AdviceMutation>>) {
55 self.event_replay = events;
56 }
57
58 pub fn with_event_advice_mutations_recording(mut self) -> Self {
68 self.event_recording = Some(Vec::new());
69 self
70 }
71
72 pub fn take_recorded_event_mutations(&mut self) -> Vec<Vec<AdviceMutation>> {
77 self.event_recording.as_mut().map(core::mem::take).unwrap_or_default()
78 }
79
80 pub fn register_assert_failed_tracer<F>(&mut self, callback: F)
82 where
83 F: FnMut(&ProcessorState<'_>, u32) + 'static,
84 {
85 self.on_assert_failed = Some(Box::new(callback));
86 }
87
88 pub fn handle_assert_failed(
93 &mut self,
94 process: &ProcessorState<'_>,
95 err_code: Option<NonZeroU32>,
96 ) {
97 if let Some(handler) = self.on_assert_failed.as_mut() {
98 handler(process, err_code.map(|nz| nz.get()).unwrap_or_default());
99 }
100 }
101
102 pub fn load_package(&mut self, package: Arc<Package>) {
104 let mast = package.mast_forest().clone();
105 let debug_info = package.debug_info();
106 self.store
107 .insert_loaded(LoadedMastForest::with_package_debug_info(mast, debug_info));
108 }
109
110 pub fn load_mast_forest(&mut self, forest: LoadedMastForest) {
112 self.store.insert_loaded(forest);
113 }
114
115 pub fn register_event_handler(
117 &mut self,
118 event: EventName,
119 handler: Arc<dyn EventHandler>,
120 ) -> Result<(), ExecutionError> {
121 self.event_handlers.register(event, handler)
122 }
123}
124
125impl<S> BaseHost for DebuggerHost<S>
126where
127 S: SourceManager + ?Sized,
128{
129 fn get_label_and_source_file(
130 &self,
131 location: &Location,
132 ) -> (SourceSpan, Option<Arc<SourceFile>>) {
133 let maybe_file = self.source_manager.get_by_uri(location.uri());
134 let span = self.source_manager.location_to_span(location.clone()).unwrap_or_default();
135 (span, maybe_file)
136 }
137
138 fn resolve_event(&self, event_id: EventId) -> Option<&EventName> {
139 self.event_handlers.resolve_event(event_id)
140 }
141}
142
143impl<S> SyncHost for DebuggerHost<S>
144where
145 S: SourceManager + ?Sized,
146{
147 fn get_mast_forest(&self, node_digest: &Word) -> Option<LoadedMastForest> {
148 self.store.get(node_digest)
149 }
150
151 fn on_event(
152 &mut self,
153 process: &ProcessorState<'_>,
154 ) -> Result<Vec<AdviceMutation>, EventError> {
155 let event_id = EventId::from_felt(process.get_stack_item(0));
156 let is_builtin_event = Event::from(event_id).has_builtin_handler();
157 let replay_mutations = self.event_replay.pop_front();
158 let is_replaying = replay_mutations.is_some();
159
160 if let Some(mutations) = replay_mutations {
161 if !is_builtin_event {
162 return Ok(mutations);
164 }
165
166 if is_builtin_event {
169 assert!(
170 mutations.is_empty(),
171 "debug events must not be associated with mutations from replay"
172 );
173 }
174 }
175
176 let result = match self.event_handlers.handle_event(event_id, process) {
177 Ok(Some(mutations)) => Ok(mutations),
178 Ok(None) => {
179 #[derive(Debug, thiserror::Error)]
180 #[error("no event handler registered")]
181 struct UnhandledEvent;
182
183 Err(UnhandledEvent.into())
184 }
185 Err(err) => Err(err),
186 };
187
188 if !is_replaying
189 && let (Some(log), Ok(mutations)) = (self.event_recording.as_mut(), &result)
190 {
191 log.push(clone_advice_mutations(mutations));
192 }
193 result
194 }
195}