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