Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(acir_gen): Brillig stdlib #4848

Merged
merged 28 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
42a6aa0
working initial mvp of brillig stdlib
vezenovm Apr 19, 2024
699650e
cleanup Brillig stdlib context and tests
vezenovm Apr 19, 2024
a663f54
comment cleanup and fmt
vezenovm Apr 19, 2024
04e3aa8
one more unit test and a fix
vezenovm Apr 19, 2024
5ddef4e
new method as to not go through every call to resolve every time
vezenovm Apr 19, 2024
1a2948a
fix add_call_to_resolve logic
vezenovm Apr 19, 2024
4f9cb15
Merge branch 'master' into mv/brillig-stdlib
vezenovm Apr 19, 2024
0b6f18e
add some comments and rename
vezenovm Apr 19, 2024
5038fa6
Merge remote-tracking branch 'origin/mv/brillig-stdlib' into mv/brill…
vezenovm Apr 19, 2024
c5be1c0
cargo fmt
vezenovm Apr 19, 2024
c1b064b
Merge branch 'master' into mv/brillig-stdlib
vezenovm Apr 22, 2024
a8f3154
Update compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
vezenovm Apr 22, 2024
4b1e686
Update compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
vezenovm Apr 22, 2024
a4c4fc3
Update compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
vezenovm Apr 22, 2024
743ee7a
Update compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
vezenovm Apr 22, 2024
79ca68d
Update compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
vezenovm Apr 22, 2024
737e6f5
remove deref
vezenovm Apr 22, 2024
417f013
imporve entry(..).or_default() usage
vezenovm Apr 22, 2024
34c895c
cleanup brillig call resolution in into_acir
vezenovm Apr 22, 2024
97c2cfa
use v2
vezenovm Apr 22, 2024
e3c80ba
Merge branch 'master' into mv/brillig-stdlib
vezenovm Apr 22, 2024
f71869a
use PLACEHOLDER_BRILLIG_INDEX
vezenovm Apr 22, 2024
b276d9d
Merge remote-tracking branch 'origin/mv/brillig-stdlib' into mv/brill…
vezenovm Apr 22, 2024
6f599f2
update tests to do v1 div v2
vezenovm Apr 22, 2024
33f60bf
Update compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
vezenovm Apr 22, 2024
a1a6539
Merge branch 'master' into mv/brillig-stdlib
TomAFrench Apr 22, 2024
5e05897
Merge branch 'master' into mv/brillig-stdlib
TomAFrench Apr 22, 2024
72b3a2c
chore: fix merge conflict
TomAFrench Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion acvm-repo/acir/src/circuit/brillig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct Brillig {
/// This is purely a wrapper struct around a list of Brillig opcode's which represents
/// a full Brillig function to be executed by the Brillig VM.
/// This is stored separately on a program and accessed through a [BrilligPointer].
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Debug)]
pub struct BrilligBytecode {
pub bytecode: Vec<BrilligOpcode>,
}
16 changes: 11 additions & 5 deletions compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::big_int::BigIntContext;
use super::generated_acir::GeneratedAcir;
use super::generated_acir::{BrilligStdlibFunc, GeneratedAcir, PLACEHOLDER_BRILLIG_INDEX};
use crate::brillig::brillig_gen::brillig_directive;
use crate::brillig::brillig_ir::artifact::GeneratedBrillig;
use crate::errors::{InternalError, RuntimeError, SsaReport};
Expand Down Expand Up @@ -326,13 +326,15 @@ impl AcirContext {
// Compute the inverse with brillig code
let inverse_code = brillig_directive::directive_invert();

let results = self.brillig(
let results = self.brillig_call(
predicate,
inverse_code,
&inverse_code,
vec![AcirValue::Var(var, AcirType::field())],
vec![AcirType::field()],
true,
false,
PLACEHOLDER_BRILLIG_INDEX,
Some(BrilligStdlibFunc::Inverse),
)?;
let inverted_var = Self::expect_one_var(results);

Expand Down Expand Up @@ -711,16 +713,18 @@ impl AcirContext {
}

let [q_value, r_value]: [AcirValue; 2] = self
.brillig(
.brillig_call(
predicate,
brillig_directive::directive_quotient(bit_size + 1),
&brillig_directive::directive_quotient(bit_size + 1),
vec![
AcirValue::Var(lhs, AcirType::unsigned(bit_size)),
AcirValue::Var(rhs, AcirType::unsigned(bit_size)),
],
vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)],
true,
false,
PLACEHOLDER_BRILLIG_INDEX,
Some(BrilligStdlibFunc::Quotient(bit_size + 1)),
)?
.try_into()
.expect("quotient only returns two values");
Expand Down Expand Up @@ -1565,6 +1569,7 @@ impl AcirContext {
attempt_execution: bool,
unsafe_return_values: bool,
brillig_function_index: u32,
brillig_stdlib_func: Option<BrilligStdlibFunc>,
) -> Result<Vec<AcirValue>, RuntimeError> {
let brillig_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> {
match i {
Expand Down Expand Up @@ -1618,6 +1623,7 @@ impl AcirContext {
brillig_inputs,
brillig_outputs,
brillig_function_index,
brillig_stdlib_func,
);

fn range_constraint_value(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ use acvm::{
use iter_extended::vecmap;
use num_bigint::BigUint;

/// Brillig calls such as for the Brillig std lib are resolved only after code generation is finished.
/// This index should be used when adding a Brillig call during code generation.
/// Code generation should then keep track of that unresolved call opcode which will be resolved with the
/// correct function index after code generation.
pub(crate) const PLACEHOLDER_BRILLIG_INDEX: u32 = 0;

#[derive(Debug, Default)]
/// The output of the Acir-gen pass, which should only be produced for entry point Acir functions
pub(crate) struct GeneratedAcir {
Expand Down Expand Up @@ -62,6 +68,29 @@ pub(crate) struct GeneratedAcir {
/// Name for the corresponding entry point represented by this Acir-gen output.
/// Only used for debugging and benchmarking purposes
pub(crate) name: String,

/// Maps the opcode index to a Brillig std library function call.
/// As to avoid passing the ACIR gen shared context into each individual ACIR
/// we can instead keep this map and resolve the Brillig calls at the end of code generation.
pub(crate) brillig_stdlib_func_locations: BTreeMap<OpcodeLocation, BrilligStdlibFunc>,
vezenovm marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub(crate) enum BrilligStdlibFunc {
Inverse,
// The Brillig quotient code is different depending upon the bit size.
Quotient(u32),
}

impl BrilligStdlibFunc {
pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig {
match self {
BrilligStdlibFunc::Inverse => brillig_directive::directive_invert(),
BrilligStdlibFunc::Quotient(bit_size) => {
brillig_directive::directive_quotient(*bit_size)
}
}
}
}

impl GeneratedAcir {
Expand Down Expand Up @@ -456,7 +485,14 @@ impl GeneratedAcir {
let inverse_code = brillig_directive::directive_invert();
let inputs = vec![BrilligInputs::Single(expr)];
let outputs = vec![BrilligOutputs::Simple(inverted_witness)];
self.brillig(Some(Expression::one()), inverse_code, inputs, outputs);
self.brillig_call(
Some(Expression::one()),
&inverse_code,
inputs,
outputs,
PLACEHOLDER_BRILLIG_INDEX,
Some(BrilligStdlibFunc::Inverse),
);

inverted_witness
}
Expand Down Expand Up @@ -625,10 +661,16 @@ impl GeneratedAcir {
inputs: Vec<BrilligInputs>,
outputs: Vec<BrilligOutputs>,
brillig_function_index: u32,
stdlib_func: Option<BrilligStdlibFunc>,
) {
let opcode =
AcirOpcode::BrilligCall { id: brillig_function_index, inputs, outputs, predicate };
self.push_opcode(opcode);
if let Some(stdlib_func) = stdlib_func {
self.brillig_stdlib_func_locations
.insert(self.last_acir_opcode_location(), stdlib_func);
}

for (brillig_index, call_stack) in generated_brillig.locations.iter() {
self.locations.insert(
OpcodeLocation::Brillig {
Expand All @@ -649,6 +691,22 @@ impl GeneratedAcir {
}
}

// We can only resolve the Brillig stdlib after having processed the entire ACIR
pub(crate) fn resolve_brillig_stdlib_call(
&mut self,
opcode_location: OpcodeLocation,
brillig_function_index: u32,
) {
let acir_index = match opcode_location {
OpcodeLocation::Acir(index) => index,
_ => panic!("should not have brillig index"),
};
match &mut self.opcodes[acir_index] {
AcirOpcode::BrilligCall { id, .. } => *id = brillig_function_index,
_ => panic!("expected brillig call opcode"),
}
}

pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation {
OpcodeLocation::Acir(self.opcodes.len() - 1)
}
Expand Down
Loading
Loading