diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/Nargo.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/Nargo.toml new file mode 100644 index 00000000000..e0b467ce5da --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/Nargo.toml @@ -0,0 +1,5 @@ +[package] +authors = [""] +compiler_version = "0.1" + +[dependencies] \ No newline at end of file diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/Prover.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/Prover.toml new file mode 100644 index 00000000000..3a627b9188b --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/Prover.toml @@ -0,0 +1 @@ +x = "10" diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/src/main.nr new file mode 100644 index 00000000000..974d26165b6 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_recursion/src/main.nr @@ -0,0 +1,14 @@ +// Tests a very simple program. +// +// The feature being tested is brillig recursion +fn main(x: u32) { + assert(fibonacci(x) == 55); +} + +unconstrained fn fibonacci(x : u32) -> u32 { + if x <= 1 { + x + } else { + fibonacci(x - 1) + fibonacci(x - 2) + } +} diff --git a/crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 6ccb7cc0b16..2eaeee8f636 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -73,14 +73,17 @@ impl BrilligArtifact { } } - /// Creates an entry point artifact wrapping the bytecode of the function provided. - pub(crate) fn to_entry_point_artifact(artifact: &BrilligArtifact) -> BrilligArtifact { - let mut entry_point_artifact = - BrilligArtifact::new(artifact.arguments.clone(), artifact.return_parameters.clone()); + /// Creates an entry point artifact that will jump to the function label provided. + pub(crate) fn new_entry_point_artifact( + arguments: Vec, + return_parameters: Vec, + target_function: Label, + ) -> BrilligArtifact { + let mut entry_point_artifact = BrilligArtifact::new(arguments, return_parameters); entry_point_artifact.entry_point_instruction(); - entry_point_artifact.add_unresolved_jumps_and_calls(artifact); - entry_point_artifact.byte_code.extend_from_slice(&artifact.byte_code); + entry_point_artifact + .add_unresolved_external_call(BrilligOpcode::Call { location: 0 }, target_function); entry_point_artifact.exit_point_instruction(); entry_point_artifact @@ -126,16 +129,6 @@ impl BrilligArtifact { // We want all functions to follow the calling convention of returning // their results in the first `n` registers. So we modify the bytecode of the // function to move the return values to the first `n` registers once completed. - // - // Swap the stop opcode with a jump to the exit point section - - let stop_position = - self.byte_code.iter().position(|opcode| matches!(opcode, BrilligOpcode::Stop)); - - let stop_position = stop_position.expect("expected a stop opcode"); - - let exit_section = self.index_of_next_opcode(); - self.byte_code[stop_position] = BrilligOpcode::Jump { location: exit_section }; // TODO: this _seems_ like an abstraction leak, we need to know about the reserved // TODO: registers in order to do this. diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index 510481df3c7..307bcce5a35 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -2,7 +2,10 @@ use std::collections::HashMap; -use crate::brillig::{brillig_ir::artifact::BrilligArtifact, Brillig}; +use crate::brillig::{ + brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext, + brillig_ir::artifact::BrilligArtifact, Brillig, +}; use self::acir_ir::{ acir_variable::{AcirContext, AcirType, AcirVar}, @@ -338,7 +341,11 @@ impl Context { fn gen_brillig_for(&self, func: &Function, brillig: &Brillig) -> Vec { // Create the entry point artifact - let mut entry_point = BrilligArtifact::to_entry_point_artifact(&brillig[func.id()]); + let mut entry_point = BrilligArtifact::new_entry_point_artifact( + BrilligFunctionContext::parameters(func), + BrilligFunctionContext::return_values(func), + BrilligFunctionContext::function_id_to_function_label(func.id()), + ); // Link the entry point with all dependencies while let Some(unresolved_fn_label) = entry_point.first_unresolved_function_call() { let artifact = &brillig