Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: recursion working in brillig
Browse files Browse the repository at this point in the history
sirasistant committed Jul 4, 2023
1 parent 1d1e424 commit 9c690ef
Showing 5 changed files with 38 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = "10"
Original file line number Diff line number Diff line change
@@ -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)
}
}
24 changes: 10 additions & 14 deletions crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs
Original file line number Diff line number Diff line change
@@ -74,13 +74,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 {
pub(crate) fn new_entry_point_artifact(
arguments: Vec<BrilligParameter>,
return_parameters: Vec<BrilligParameter>,
target_function: Label,
) -> BrilligArtifact {
let mut entry_point_artifact =
BrilligArtifact::new(artifact.arguments.clone(), artifact.return_parameters.clone());
BrilligArtifact::new(arguments.clone(), return_parameters.clone());
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 +130,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.
@@ -161,6 +155,8 @@ impl BrilligArtifact {
/// Brillig artifact (self).
pub(crate) fn link_with(&mut self, func_label: Label, obj: &BrilligArtifact) {
// Add the unresolved jumps of the linked function to this artifact.
println!("Linking with {}", func_label);
println!("Current bytecode: {:?}", self.byte_code);
self.add_unresolved_jumps_and_calls(obj);

let mut byte_code = obj.byte_code.clone();
10 changes: 8 additions & 2 deletions crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@
use std::collections::HashMap;

use crate::brillig::{brillig_ir::artifact::BrilligArtifact, Brillig};
use crate::brillig::{
brillig_gen::brillig_fn::FunctionContext, brillig_ir::artifact::BrilligArtifact, Brillig,
};

use self::acir_ir::{
acir_variable::{AcirContext, AcirType, AcirVar},
@@ -217,7 +219,11 @@ impl Context {
let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg));

// Create the entry point artifact
let mut entry_point = BrilligArtifact::to_entry_point_artifact(&brillig[*id]);
let mut entry_point = BrilligArtifact::new_entry_point_artifact(
FunctionContext::parameters(func),
FunctionContext::return_values(func),
FunctionContext::function_id_to_function_label(*id),
);
// Link the entry point with all dependencies
while let Some(unresolved_fn_label) = entry_point.first_unresolved_function_call() {
let artifact = &brillig.find_by_function_label(unresolved_fn_label.clone()).expect("Cannot find linked fn {unresolved_fn_label}");

0 comments on commit 9c690ef

Please sign in to comment.