Skip to content

Commit

Permalink
Merge pull request #1160 from 0xPolygonMiden/andrew-add-procrefed-fun…
Browse files Browse the repository at this point in the history
…c-to-callset

Use dynamic calls after `procref`
  • Loading branch information
Fumuran authored Nov 29, 2023
2 parents f6bc75f + cf3ae33 commit 4582326
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
10 changes: 8 additions & 2 deletions assembly/src/assembler/instruction/procedures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,10 @@ impl Assembler {
context: &mut AssemblyContext,
span: &mut SpanBuilder,
) -> Result<Option<CodeBlock>, AssemblyError> {
// get root of the compiled local procedure
let proc_root = context.get_local_procedure(proc_idx)?.mast_root();
// get root of the compiled local procedure and add it to the callset to be able to use
// dynamic instructions with this procedure later
let proc_root = context.register_local_call(proc_idx, false)?.mast_root();

// create an array with `Push` operations containing root elements
let ops: Vec<Operation> = proc_root.iter().map(|elem| Operation::Push(*elem)).collect();
span.add_ops(ops)
Expand All @@ -163,6 +165,10 @@ impl Assembler {
let proc_cache = self.proc_cache.borrow();
let proc = proc_cache.get_by_id(proc_id).expect("procedure not in cache");

// add the root of the procedure to the callset to be able to use dynamic instructions with
// this procedure later
context.register_external_call(proc, false)?;

// get root of the cimported procedure
let proc_root = proc.mast_root();
// create an array with `Push` operations containing root elements
Expand Down
2 changes: 1 addition & 1 deletion docs/src/user_docs/assembly/code_organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ dynexec
This causes the VM to do the following:

1. Read the top 4 elements of the stack to get the hash of the dynamic target (leaving the stack unchanged).
2. Execute the code block which hashes to the specified target. The VM must know the specified code block and hash (they must be in the CodeBlockTable of the executing Program).
2. Execute the code block which hashes to the specified target. The VM must know the specified code block and hash: they must be in the CodeBlockTable of the executing Program. Hashes can be put into the CodeBlockTable manually, or by executing `call`, `syscall`, or `procref` instructions.

Dynamic code execution in a new context can be achieved similarly by setting the top $4$ elements of the stack to the hash of the dynamic code block and then executing the following instruction:

Expand Down
32 changes: 32 additions & 0 deletions miden/tests/integration/flow_control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,38 @@ fn simple_dyn_exec() {
);
}

#[test]
fn dynexec_with_procref() {
let program_source = "
use.std::math::u64
proc.foo
push.1.2
u32wrapping_add
end
begin
procref.foo
dynexec
procref.u64::wrapping_add
dynexec
end";

let mut test = build_test!(program_source, &[]);
test.libraries = vec![StdLibrary::default().into()];

test.expect_stack(&[
1719755471,
1057995821,
3,
12973202366681443424,
7933716460165146367,
14382661273226268231,
15818904913409383971,
]);
}

#[test]
fn simple_dyncall() {
let program_source = "
Expand Down

0 comments on commit 4582326

Please sign in to comment.