use miden_core::FMP_INIT_VALUE;
use miden_utils_testing::build_debug_test;
#[test]
fn test_debug_stack() {
let stack_inputs = [1, 2, 3, 4]; let source = "
begin
# Check 0 handling
debug.stack.0
# Print the initial stack
debug.stack.4
# => [4, 3, 2, 1]
# Check overflow by increasing the stack to 28 elements
repeat.12
push.42
end
# There are 28 items, there should be 8 more elements we don't print
debug.stack.20
dropw dropw dropw
# There are 16 elements, the last 4 should be EMPTY
debug.stack.20
# Push an element and print the first 7 elements.
# The last should be 0 since the stack was padded with zeros until 16
push.5 debug.stack.7
# => [5, 4, 3, 2, 1, 0]
# Shrink stack to 12 elements and print the whole output
# We should get 16 elements since zeros are pushed until the size is 16
drop dropw debug.stack
# => [0, ..., 0]
end";
let test = build_debug_test!(source, &stack_inputs);
let (_stack, output) = test.execute_with_debug_buffer().expect("execution failed");
insta::assert_snapshot!(output, @r"
Stack state before step 5:
├── 0: 1
├── 1: 2
├── 2: 3
├── 3: 4
├── 4: 0
├── 5: 0
├── 6: 0
├── 7: 0
├── 8: 0
├── 9: 0
├── 10: 0
├── 11: 0
├── 12: 0
├── 13: 0
├── 14: 0
└── 15: 0
Stack state in interval [0, 3] before step 5:
├── 0: 1
├── 1: 2
├── 2: 3
├── 3: 4
└── (12 more items)
Stack state in interval [0, 19] before step 22:
├── 0: 42
├── 1: 42
├── 2: 42
├── 3: 42
├── 4: 42
├── 5: 42
├── 6: 42
├── 7: 42
├── 8: 42
├── 9: 42
├── 10: 42
├── 11: 42
├── 12: 1
├── 13: 2
├── 14: 3
├── 15: 4
├── 16: 0
├── 17: 0
├── 18: 0
├── 19: 0
└── (8 more items)
Stack state before step 34:
├── 0: 1
├── 1: 2
├── 2: 3
├── 3: 4
├── 4: 0
├── 5: 0
├── 6: 0
├── 7: 0
├── 8: 0
├── 9: 0
├── 10: 0
├── 11: 0
├── 12: 0
├── 13: 0
├── 14: 0
├── 15: 0
├── 16: EMPTY
├── 17: EMPTY
├── 18: EMPTY
└── 19: EMPTY
Stack state in interval [0, 6] before step 35:
├── 0: 5
├── 1: 1
├── 2: 2
├── 3: 3
├── 4: 4
├── 5: 0
├── 6: 0
└── (10 more items)
Stack state before step 44:
├── 0: 0
├── 1: 0
├── 2: 0
├── 3: 0
├── 4: 0
├── 5: 0
├── 6: 0
├── 7: 0
├── 8: 0
├── 9: 0
├── 10: 0
├── 11: 0
├── 12: 0
├── 13: 0
├── 14: 0
└── 15: 0
");
}
#[test]
fn test_debug_mem() {
let stack_inputs = [5, 3, 2, 1];
let source = "
begin
mem_store.0 mem_store.1 mem_store.2 # => [0->1, 1->2, 2->3]
debug.mem
debug.mem.2 # => [2->3]
debug.mem.6 # => EMPTY
debug.mem.1.2 # => [1->2, 2->3]
mem_store.4 # => [4->5]
debug.mem
debug.mem.2.5 # [3, 0, 5, 0]
debug.mem.12.14 # [EMPTY, ..., EMPTY]
end";
let test = build_debug_test!(source, &stack_inputs);
let (_stack, output) = test.execute_with_debug_buffer().expect("execution failed");
insta::assert_snapshot!(output, @r"
Memory state before step 15 for the context 0:
├── 0x00000000: 5
├── 0x00000001: 3
├── 0x00000002: 2
├── 0x00000003: 0
├── 0xfffffffc: 0
├── 0xfffffffd: 0
├── 0xfffffffe: 2147483648
└── 0xffffffff: 0
Memory state before step 15 for the context 0 at address 0x00000002: 2
Memory state before step 15 for the context 0 at address 0x00000006: EMPTY
Memory state before step 15 for the context 0 in the interval [1, 2]:
├── 0x00000001: 3
└── 0x00000002: 2
Memory state before step 21 for the context 0:
├── 0x00000000: 5
├── 0x00000001: 3
├── 0x00000002: 2
├── 0x00000003: 0
├── 0x00000004: 1
├── 0x00000005: 0
├── 0x00000006: 0
├── 0x00000007: 0
├── 0xfffffffc: 0
├── 0xfffffffd: 0
├── 0xfffffffe: 2147483648
└── 0xffffffff: 0
Memory state before step 21 for the context 0 in the interval [2, 5]:
├── 0x00000002: 2
├── 0x00000003: 0
├── 0x00000004: 1
└── 0x00000005: 0
Memory state before step 21 for the context 0 in the interval [12, 14]:
├── 0x0000000c: EMPTY
├── 0x0000000d: EMPTY
└── 0x0000000e: EMPTY
");
}
#[test]
fn test_debug_local() {
let fmp_init_value_u64 = FMP_INIT_VALUE.as_canonical_u64();
let stack_inputs = [5, 3, 2, 1];
let local_addr_4 = fmp_init_value_u64 + 8 - 8 + 4;
let source = format!(
"
@locals(6)
proc test
# Get address of third local to show it has been initialized to an arbitrary value
locaddr.4 push.{local_addr_4} assert_eq
loc_store.0 loc_store.1 loc_store.2 # => [0->1, 1->2, 2->3]
debug.mem
debug.local
debug.local.2 # => 3
debug.local.4 # => 42 (garbage)
debug.local.1.2 # => [2, 3]
loc_store.4 # Overwrite previous garbage value => [4->5]
debug.local
debug.local.4 # => 5 (not garbage)
debug.local.6 # => EMPTY (out of bounds)
debug.local.2.6 # => [3, 0, 5, 0, EMPTY]
end
begin
# Write a garbage value to show it is not 0 by default
push.42 mem_store.{local_addr_4}
exec.test
debug.mem
end"
);
let test = build_debug_test!(source, &stack_inputs);
let (_stack, output) = test.execute_with_debug_buffer().expect("execution failed");
insta::assert_snapshot!(output, @r"
Memory state before step 43 for the context 0:
├── 0x80000000: 5
├── 0x80000001: 3
├── 0x80000002: 2
├── 0x80000003: 0
├── 0x80000004: 42
├── 0x80000005: 0
├── 0x80000006: 0
├── 0x80000007: 0
├── 0xfffffffc: 0
├── 0xfffffffd: 0
├── 0xfffffffe: 2147483656
└── 0xffffffff: 0
State of procedure locals [0, 5] before step 43:
├── 0: 5
├── 1: 3
├── 2: 2
├── 3: 0
├── 4: 42
└── 5: 0
State of procedure local 2 before step 43: 2
State of procedure local 4 before step 43: 42
State of procedure locals [1, 2] before step 43:
├── 1: 3
└── 2: 2
State of procedure locals [0, 5] before step 50:
├── 0: 5
├── 1: 3
├── 2: 2
├── 3: 0
├── 4: 1
└── 5: 0
State of procedure local 4 before step 50: 1
State of procedure local 6 before step 50: 0
State of procedure locals [2, 6] before step 50:
├── 2: 2
├── 3: 0
├── 4: 1
├── 5: 0
└── 6: 0
Memory state before step 58 for the context 0:
├── 0x80000000: 5
├── 0x80000001: 3
├── 0x80000002: 2
├── 0x80000003: 0
├── 0x80000004: 1
├── 0x80000005: 0
├── 0x80000006: 0
├── 0x80000007: 0
├── 0xfffffffc: 0
├── 0xfffffffd: 0
├── 0xfffffffe: 2147483648
└── 0xffffffff: 0
");
}
#[test]
fn test_debug_adv_stack() {
let stack_input = [4, 3, 2, 1, 0];
let advice_stack = [8, 7, 6, 5, 4, 3, 2, 1]; let source = "
begin
# => [4, 3, 2, 1, 0]
debug.adv_stack # => [8..1]
debug.adv_stack.2 # => [8, 7]
debug.adv_stack.0 # => [8..1]
# Check that we can output output EMPTY when too many elements are requested
debug.adv_stack.10
padw adv_loadw
# => [8, 7, 6, 5, 4, 3, 2, 1, 0]
debug.adv_stack # => [4, 3, 2, 1]
debug.stack.9
push.[8, 7, 6, 5] assert_eqw
# => [4, 3, 2, 1, 0]
adv_push.1
# => [4, 4, 3, 2, 1, 0]
debug.stack.6
debug.adv_stack # => [3, 2, 1]
# Check that we popped 4
assert_eq
# => [3, 2, 1, 0]
# Pops the remaining elements one-by-one
adv_push.3
# => [1, 2, 3, 3, 2, 1, 0]
debug.stack.7
# Check
push.0 reversew assert_eqw
# advice stack is empty
debug.adv_stack
end";
let test = build_debug_test!(source, &stack_input, &advice_stack);
let (_stack, output) = test.execute_with_debug_buffer().expect("execution failed");
insta::assert_snapshot!(output, @r"
Advice stack state before step 5:
├── 0: 8
├── 1: 7
├── 2: 6
├── 3: 5
├── 4: 4
├── 5: 3
├── 6: 2
└── 7: 1
Advice stack state in interval [0, 1] before step 5:
├── 0: 8
├── 1: 7
└── (6 more items)
Advice stack state before step 5:
├── 0: 8
├── 1: 7
├── 2: 6
├── 3: 5
├── 4: 4
├── 5: 3
├── 6: 2
└── 7: 1
Advice stack state before step 5:
├── 0: 8
├── 1: 7
├── 2: 6
├── 3: 5
├── 4: 4
├── 5: 3
├── 6: 2
├── 7: 1
├── 8: EMPTY
└── 9: EMPTY
Advice stack state before step 10:
├── 0: 4
├── 1: 3
├── 2: 2
└── 3: 1
Stack state in interval [0, 8] before step 10:
├── 0: 8
├── 1: 7
├── 2: 6
├── 3: 5
├── 4: 4
├── 5: 3
├── 6: 2
├── 7: 1
├── 8: 0
└── (11 more items)
Stack state in interval [0, 5] before step 27:
├── 0: 4
├── 1: 4
├── 2: 3
├── 3: 2
├── 4: 1
├── 5: 0
└── (11 more items)
Advice stack state before step 27:
├── 0: 3
├── 1: 2
└── 2: 1
Stack state in interval [0, 6] before step 32:
├── 0: 1
├── 1: 2
├── 2: 3
├── 3: 3
├── 4: 2
├── 5: 1
├── 6: 0
└── (12 more items)
Advice stack empty before step 49.
");
}