miden_debug/debug/
native_ptr.rs

1/// This represents a descriptor for a pointer translated from the IR into a form suitable for
2/// referencing data in Miden's linear memory.
3#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4pub struct NativePtr {
5    /// This is the address of the element containing the first byte of data
6    ///
7    /// Each element is assumed to be a 32-bit value/chunk
8    pub addr: u32,
9    /// This is the byte offset into the 32-bit chunk referenced by `index`
10    ///
11    /// This offset is where the data referenced by the pointer actually starts.
12    pub offset: u8,
13    /// This is the assumed address space of the pointer value.
14    ///
15    /// This address space is unknown by default, but can be specified if known statically.
16    /// The address space determines whether the pointer is valid in certain contexts. For
17    /// example, attempting to load a pointer with address space 0 is invalid if not operating
18    /// in the root context.
19    ///
20    /// Currently this has no effect, but is here as we expand support for multiple memories.
21    pub addrspace: miden_assembly_syntax::ast::types::AddressSpace,
22}
23impl NativePtr {
24    pub fn new(addr: u32, offset: u8) -> Self {
25        Self {
26            addr,
27            offset,
28            addrspace: Default::default(),
29        }
30    }
31
32    /// Translates a raw pointer (assumed to be in a byte-addressable address space) to a native
33    /// pointer value, in the default [hir::AddressSpace].
34    pub fn from_ptr(addr: u32) -> Self {
35        // The native word address for `addr` is derived by splitting the byte-addressable space
36        // into 32-bit chunks, each chunk belonging to a single field element, i.e. each element
37        // of the native address space represents 32 bits of byte-addressable memory.
38        //
39        // By dividing `addr` by 4, we get the element address where the data starts.
40        let eaddr = addr / 4;
41        // If our address is not element-aligned, we need to determine what byte offset contains
42        // the first byte of the data.
43        let offset = (addr % 4) as u8;
44        Self {
45            addr: eaddr,
46            offset,
47            addrspace: Default::default(),
48        }
49    }
50
51    /// Returns true if this pointer is aligned to a word boundary
52    pub const fn is_word_aligned(&self) -> bool {
53        self.offset == 0 && self.addr.is_multiple_of(4)
54    }
55
56    /// Returns true if this pointer is aligned to a field element boundary
57    pub const fn is_element_aligned(&self) -> bool {
58        self.offset == 0
59    }
60}