miden_debug_engine/exec/
query.rs1use alloc::vec::Vec;
2
3use miden_core::{Felt, Word};
4use miden_processor::{ContextId, MemoryError, ProcessorState, trace::RowIndex};
5use smallvec::SmallVec;
6
7use super::trace::MemoryReadError;
8use crate::{FromMidenRepr, NativePtr};
9
10pub trait DebugQuery {
11 fn state(&self) -> ProcessorState<'_>;
12 fn current_context(&self) -> ContextId;
13 fn current_clock(&self) -> RowIndex;
14
15 fn read_memory_word(&self, addr: u32) -> Result<Option<Word>, MemoryError> {
17 self.state().get_mem_word(self.current_context(), addr)
18 }
19
20 #[track_caller]
22 fn read_memory_element(&self, addr: u32) -> Option<Felt> {
23 self.state().get_mem_value(self.current_context(), addr)
24 }
25
26 fn read_bytes_for_type(
29 &self,
30 addr: NativePtr,
31 ty: &miden_assembly_syntax::ast::types::Type,
32 ) -> Result<Vec<u8>, MemoryReadError> {
33 let size = ty.size_in_bytes();
34 read_memory_bytes(addr, size, |addr| Ok(self.read_memory_element(addr).unwrap_or_default()))
35 }
36
37 #[track_caller]
39 fn read_from_rust_memory<T>(&self, addr: u32) -> Option<T>
40 where
41 T: core::any::Any + FromMidenRepr,
42 {
43 let ptr = NativePtr::from_ptr(addr);
44 assert_eq!(ptr.offset, 0, "support for unaligned reads is not yet implemented");
45 let size = <T as FromMidenRepr>::size_in_felts();
46 let mut felts = SmallVec::<[_; 4]>::with_capacity(size);
47 for index in 0..(size as u32) {
48 felts.push(self.read_memory_element(ptr.addr.checked_add(index)?).unwrap_or_default());
51 }
52 Some(T::from_felts(&felts))
53 }
54}
55
56pub(crate) fn read_memory_bytes<E>(
60 ptr: NativePtr,
61 size: usize,
62 mut read_elem: impl FnMut(u32) -> Result<Felt, E>,
63) -> Result<Vec<u8>, E>
64where
65 E: From<MemoryReadError>,
66{
67 if size == 0 {
68 return Ok(Vec::new());
69 }
70
71 let start = usize::from(ptr.offset);
72 let end = start.checked_add(size).ok_or_else(|| E::from(MemoryReadError::OutOfBounds))?;
73 let num_elements = end.div_ceil(4);
74
75 let mut bytes = Vec::with_capacity(num_elements.saturating_mul(4));
76 for index in 0..num_elements {
77 let index = u32::try_from(index).map_err(|_| E::from(MemoryReadError::OutOfBounds))?;
78 let elem_addr = ptr
79 .addr
80 .checked_add(index)
81 .ok_or_else(|| E::from(MemoryReadError::OutOfBounds))?;
82 bytes.extend(felt_to_le_bytes(read_elem(elem_addr)?));
83 }
84
85 Ok(bytes[start..end].to_vec())
86}
87
88pub(crate) fn felt_to_le_bytes(elem: Felt) -> [u8; 4] {
89 ((elem.as_canonical_u64() & u32::MAX as u64) as u32).to_le_bytes()
90}