Skip to content

Commit e55b5a8

Browse files
authored
feat: recursion working in brillig (#1854)
* feat: recursion working in brillig * Update crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs * fix: removed redundant clone * Update crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs * fix: merge change
1 parent b2e71bb commit e55b5a8

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[package]
2+
authors = [""]
3+
compiler_version = "0.1"
4+
5+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x = "10"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Tests a very simple program.
2+
//
3+
// The feature being tested is brillig recursion
4+
fn main(x: u32) {
5+
assert(fibonacci(x) == 55);
6+
}
7+
8+
unconstrained fn fibonacci(x : u32) -> u32 {
9+
if x <= 1 {
10+
x
11+
} else {
12+
fibonacci(x - 1) + fibonacci(x - 2)
13+
}
14+
}

crates/noirc_evaluator/src/brillig/brillig_ir/artifact.rs

+9-16
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,17 @@ impl BrilligArtifact {
7373
}
7474
}
7575

76-
/// Creates an entry point artifact wrapping the bytecode of the function provided.
77-
pub(crate) fn to_entry_point_artifact(artifact: &BrilligArtifact) -> BrilligArtifact {
78-
let mut entry_point_artifact =
79-
BrilligArtifact::new(artifact.arguments.clone(), artifact.return_parameters.clone());
76+
/// Creates an entry point artifact that will jump to the function label provided.
77+
pub(crate) fn new_entry_point_artifact(
78+
arguments: Vec<BrilligParameter>,
79+
return_parameters: Vec<BrilligParameter>,
80+
target_function: Label,
81+
) -> BrilligArtifact {
82+
let mut entry_point_artifact = BrilligArtifact::new(arguments, return_parameters);
8083
entry_point_artifact.entry_point_instruction();
8184

82-
entry_point_artifact.add_unresolved_jumps_and_calls(artifact);
83-
entry_point_artifact.byte_code.extend_from_slice(&artifact.byte_code);
85+
entry_point_artifact
86+
.add_unresolved_external_call(BrilligOpcode::Call { location: 0 }, target_function);
8487

8588
entry_point_artifact.exit_point_instruction();
8689
entry_point_artifact
@@ -126,16 +129,6 @@ impl BrilligArtifact {
126129
// We want all functions to follow the calling convention of returning
127130
// their results in the first `n` registers. So we modify the bytecode of the
128131
// function to move the return values to the first `n` registers once completed.
129-
//
130-
// Swap the stop opcode with a jump to the exit point section
131-
132-
let stop_position =
133-
self.byte_code.iter().position(|opcode| matches!(opcode, BrilligOpcode::Stop));
134-
135-
let stop_position = stop_position.expect("expected a stop opcode");
136-
137-
let exit_section = self.index_of_next_opcode();
138-
self.byte_code[stop_position] = BrilligOpcode::Jump { location: exit_section };
139132

140133
// TODO: this _seems_ like an abstraction leak, we need to know about the reserved
141134
// TODO: registers in order to do this.

crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
33
use std::collections::HashMap;
44

5-
use crate::brillig::{brillig_ir::artifact::BrilligArtifact, Brillig};
5+
use crate::brillig::{
6+
brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext,
7+
brillig_ir::artifact::BrilligArtifact, Brillig,
8+
};
69

710
use self::acir_ir::{
811
acir_variable::{AcirContext, AcirType, AcirVar},
@@ -338,7 +341,11 @@ impl Context {
338341

339342
fn gen_brillig_for(&self, func: &Function, brillig: &Brillig) -> Vec<Opcode> {
340343
// Create the entry point artifact
341-
let mut entry_point = BrilligArtifact::to_entry_point_artifact(&brillig[func.id()]);
344+
let mut entry_point = BrilligArtifact::new_entry_point_artifact(
345+
BrilligFunctionContext::parameters(func),
346+
BrilligFunctionContext::return_values(func),
347+
BrilligFunctionContext::function_id_to_function_label(func.id()),
348+
);
342349
// Link the entry point with all dependencies
343350
while let Some(unresolved_fn_label) = entry_point.first_unresolved_function_call() {
344351
let artifact = &brillig

0 commit comments

Comments
 (0)