Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ crates/lib/core/assets/core.masl

# These are files generated by MacOS
**/.DS_Store
._*

# File present in Intellij IDE's.
.idea/
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#### Enhancements

- Added `DebugVar` decorator for tracking source-level variables during execution, and `debug_info` section in MASP packages for storing type definitions, source file paths, and function metadata to support source-level debugging.
- Added `procedure_names` to `DebugInfo` for storing procedure name mappings by MAST root digest, enabling debuggers to resolve human-readable procedure names during execution (#[2474](https://github.com/0xMiden/miden-vm/pull/2474)).

#### Fixes
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ pub mod prettier {

mod operations;
pub use operations::{
AssemblyOp, DebugOptions, Decorator, DecoratorList, Operation, opcode_constants::*,
AssemblyOp, DebugOptions, DebugVarInfo, DebugVarLocation, Decorator, DecoratorList, Operation,
opcode_constants::*,
};

pub mod stack;
Expand Down
117 changes: 116 additions & 1 deletion core/src/mast/serialization/decorator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
string_table::{StringTable, StringTableBuilder},
};
use crate::{
AssemblyOp, DebugOptions, Decorator,
AssemblyOp, DebugOptions, DebugVarInfo, DebugVarLocation, Decorator,
utils::{
ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
},
Expand Down Expand Up @@ -123,6 +123,65 @@ impl DecoratorInfo {
let value = data_reader.read_u16()?;
Ok(Decorator::Debug(DebugOptions::AdvStackTop(value)))
},
EncodedDecoratorVariant::DebugVar => {
// Read variable name
let name_idx = data_reader.read_usize()?;
let name = string_table.read_string(name_idx)?;

// Read value location tag and data
let location_tag = data_reader.read_u8()?;
let value_location = match location_tag {
0 => DebugVarLocation::Stack(data_reader.read_u8()?),
1 => DebugVarLocation::Memory(data_reader.read_u32()?),
2 => {
let value = data_reader.read_u64()?;
DebugVarLocation::Const(crate::Felt::new(value))
},
3 => DebugVarLocation::Local(data_reader.read_u16()?),
4 => {
let len = data_reader.read_u16()? as usize;
let bytes = data_reader.read_vec(len)?;
DebugVarLocation::Expression(bytes)
},
_ => {
return Err(DeserializationError::InvalidValue(format!(
"invalid DebugVarLocation tag: {location_tag}"
)));
},
};

let mut debug_var = DebugVarInfo::new(name, value_location);

// Read optional type_id
if data_reader.read_bool()? {
debug_var.set_type_id(data_reader.read_u32()?);
}

// Read optional arg_index (1-based, stored as raw u32)
if data_reader.read_bool()? {
let arg_index = data_reader.read_u32()?;
// set_arg_index expects a non-zero value for 1-based indices
if arg_index > 0 {
debug_var.set_arg_index(arg_index);
}
}

// Read optional source location
if data_reader.read_bool()? {
use miden_debug_types::{ColumnNumber, FileLineCol, LineNumber, Uri};
let uri_idx = data_reader.read_usize()?;
let uri = Uri::from(string_table.read_arc_str(uri_idx)?);
let line = data_reader.read_u32()?;
let column = data_reader.read_u32()?;
debug_var.set_location(FileLineCol::new(
uri,
LineNumber::new(line).unwrap_or_default(),
ColumnNumber::new(column).unwrap_or_default(),
));
}

Ok(Decorator::DebugVar(debug_var))
},
}
}
}
Expand Down Expand Up @@ -168,6 +227,7 @@ pub enum EncodedDecoratorVariant {
DebugOptionsLocalInterval,
DebugOptionsAdvStackTop,
Trace,
DebugVar,
}

impl EncodedDecoratorVariant {
Expand Down Expand Up @@ -198,6 +258,7 @@ impl From<&Decorator> for EncodedDecoratorVariant {
DebugOptions::AdvStackTop(_) => Self::DebugOptionsAdvStackTop,
},
Decorator::Trace(_) => Self::Trace,
Decorator::DebugVar(_) => Self::DebugVar,
}
}
}
Expand Down Expand Up @@ -308,6 +369,60 @@ impl DecoratorDataBuilder {
Decorator::Trace(value) => {
self.decorator_data.extend(value.to_le_bytes());

Some(data_offset)
},
Decorator::DebugVar(debug_var) => {
// Write variable name
let name_offset = self.string_table_builder.add_string(debug_var.name());
self.decorator_data.write_usize(name_offset);

// Write value location with tag
match debug_var.value_location() {
DebugVarLocation::Stack(pos) => {
self.decorator_data.push(0); // tag
self.decorator_data.push(*pos);
},
DebugVarLocation::Memory(addr) => {
self.decorator_data.push(1); // tag
self.decorator_data.extend(addr.to_le_bytes());
},
DebugVarLocation::Const(felt) => {
self.decorator_data.push(2); // tag
// Serialize Felt as u64
self.decorator_data.extend(felt.as_int().to_le_bytes());
},
DebugVarLocation::Local(idx) => {
self.decorator_data.push(3); // tag
self.decorator_data.extend(idx.to_le_bytes());
},
DebugVarLocation::Expression(bytes) => {
self.decorator_data.push(4); // tag
self.decorator_data.extend((bytes.len() as u16).to_le_bytes());
self.decorator_data.extend(bytes);
},
}

// Write optional type_id
self.decorator_data.write_bool(debug_var.type_id().is_some());
if let Some(type_id) = debug_var.type_id() {
self.decorator_data.extend(type_id.to_le_bytes());
}

// Write optional arg_index (serialize NonZeroU32 as u32)
self.decorator_data.write_bool(debug_var.arg_index().is_some());
if let Some(arg_index) = debug_var.arg_index() {
self.decorator_data.extend(arg_index.get().to_le_bytes());
}

// Write optional source location
self.decorator_data.write_bool(debug_var.location().is_some());
if let Some(loc) = debug_var.location() {
let uri_offset = self.string_table_builder.add_string(loc.uri.as_str());
self.decorator_data.write_usize(uri_offset);
self.decorator_data.extend(loc.line.to_u32().to_le_bytes());
self.decorator_data.extend(loc.column.to_u32().to_le_bytes());
}

Some(data_offset)
},
}
Expand Down
1 change: 1 addition & 0 deletions core/src/mast/serialization/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ fn confirm_operation_and_decorator_structure() {
DebugOptions::AdvStackTop(_) => (),
},
Decorator::Trace(_) => (),
Decorator::DebugVar(_) => (),
};
}

Expand Down
Loading