Skip to content

Commit

Permalink
feat: Sync from noir (#6023)
Browse files Browse the repository at this point in the history
Automated pull of development from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
chore: rework workspace structure for utils crates
(noir-lang/noir#4886)
feat: add variable size sha256
(noir-lang/noir#4920)
chore: delete flake.lock (noir-lang/noir#4855)
chore: Add error conversion from `InterpreterError`
(noir-lang/noir#4896)
chore: delete dead code (noir-lang/noir#4906)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <tom@tomfren.ch>
  • Loading branch information
AztecBot and TomAFrench committed Apr 25, 2024
1 parent 3671932 commit 078aa61
Show file tree
Hide file tree
Showing 30 changed files with 315 additions and 371 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0cf2e2a1b8d247bed03ba5b7b1be5cd30f0d51b2
7ea0e914625789e65b0d5908f7f0b76a9fd32652
10 changes: 5 additions & 5 deletions avm-transpiler/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions noir/noir-repo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions noir/noir-repo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ members = [
# Aztec Macro crate for metaprogramming
"aztec_macros",
# Compiler crates
"compiler/noirc_arena",
"compiler/noirc_evaluator",
"compiler/noirc_frontend",
"compiler/noirc_errors",
"compiler/noirc_driver",
"compiler/noirc_printable_type",
"compiler/fm",
"compiler/wasm",
# Utility crates used by the Noir compiler
"compiler/utils/arena",
"compiler/utils/iter-extended",
# Crates related to tooling built ontop of the Noir compiler
# Crates related to tooling built on top of the Noir compiler
"tooling/backend_interface",
"tooling/bb_abstraction_leaks",
"tooling/lsp",
Expand All @@ -35,6 +33,8 @@ members = [
"acvm-repo/brillig_vm",
"acvm-repo/blackbox_solver",
"acvm-repo/bn254_blackbox_solver",
# Utility crates
"utils/iter-extended",
]
default-members = ["tooling/nargo_cli", "tooling/acvm_cli"]
resolver = "2"
Expand All @@ -61,9 +61,8 @@ acvm_blackbox_solver = { version = "0.44.0", path = "acvm-repo/blackbox_solver",
bn254_blackbox_solver = { version = "0.44.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false }

# Noir compiler workspace dependencies
arena = { path = "compiler/utils/arena" }
fm = { path = "compiler/fm" }
iter-extended = { path = "compiler/utils/iter-extended" }
noirc_arena = { path = "compiler/noirc_arena" }
noirc_driver = { path = "compiler/noirc_driver" }
noirc_errors = { path = "compiler/noirc_errors" }
noirc_evaluator = { path = "compiler/noirc_evaluator" }
Expand All @@ -80,6 +79,9 @@ noirc_abi = { path = "tooling/noirc_abi" }
bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" }
acvm_cli = { path = "tooling/acvm_cli" }

# Misc utils crates
iter-extended = { path = "utils/iter-extended" }

# LSP
async-lsp = { version = "0.1.0", default-features = false }
lsp-types = "0.94.1"
Expand Down
2 changes: 1 addition & 1 deletion noir/noir-repo/acvm-repo/acvm_js/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function run_if_available {
require_command jq
require_command cargo
require_command wasm-bindgen
# require_command wasm-opt
#require_command wasm-opt

self_path=$(dirname "$(readlink -f "$0")")
pname=$(cargo read-manifest | jq -r '.name')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "arena"
name = "noirc_arena"
version.workspace = true
authors.workspace = true
edition.workspace = true
Expand Down
9 changes: 1 addition & 8 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@

use std::collections::BTreeSet;

use crate::{
brillig::Brillig,
errors::{RuntimeError, SsaReport},
};
use crate::errors::{RuntimeError, SsaReport};
use acvm::acir::{
circuit::{
brillig::BrilligBytecode, Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs,
Expand Down Expand Up @@ -318,10 +315,6 @@ impl SsaBuilder {
Ok(self.print(msg))
}

fn to_brillig(&self, print_brillig_trace: bool) -> Brillig {
self.ssa.to_brillig(print_brillig_trace)
}

fn print(self, msg: &str) -> Self {
if self.print_ssa_passes {
println!("{msg}\n{}", self.ssa);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,55 +420,6 @@ impl GeneratedAcir {
Ok(limb_witnesses)
}

/// Returns an expression which represents `lhs * rhs`
///
/// If one has multiplicative term and the other is of degree one or more,
/// the function creates [intermediate variables][`Witness`] accordingly.
/// There are two cases where we can optimize the multiplication between two expressions:
/// 1. If the sum of the degrees of both expressions is at most 2, then we can just multiply them
/// as each term in the result will be degree-2.
/// 2. If one expression is a constant, then we can just multiply the constant with the other expression
///
/// (1) is because an [`Expression`] can hold at most a degree-2 univariate polynomial
/// which is what you get when you multiply two degree-1 univariate polynomials.
pub(crate) fn mul_with_witness(&mut self, lhs: &Expression, rhs: &Expression) -> Expression {
use std::borrow::Cow;
let lhs_is_linear = lhs.is_linear();
let rhs_is_linear = rhs.is_linear();

// Case 1: The sum of the degrees of both expressions is at most 2.
//
// If one of the expressions is constant then it does not increase the degree when multiplying by another expression.
// If both of the expressions are linear (degree <=1) then the product will be at most degree 2.
let both_are_linear = lhs_is_linear && rhs_is_linear;
let either_is_const = lhs.is_const() || rhs.is_const();
if both_are_linear || either_is_const {
return (lhs * rhs).expect("Both expressions are degree <= 1");
}

// Case 2: One or both of the sides needs to be reduced to a degree-1 univariate polynomial
let lhs_reduced = if lhs_is_linear {
Cow::Borrowed(lhs)
} else {
Cow::Owned(self.get_or_create_witness(lhs).into())
};

// If the lhs and rhs are the same, then we do not need to reduce
// rhs, we only need to square the lhs.
if lhs == rhs {
return (&*lhs_reduced * &*lhs_reduced)
.expect("Both expressions are reduced to be degree <= 1");
};

let rhs_reduced = if rhs_is_linear {
Cow::Borrowed(rhs)
} else {
Cow::Owned(self.get_or_create_witness(rhs).into())
};

(&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree <= 1")
}

/// Adds an inversion brillig opcode.
///
/// This code will invert `expr` without applying constraints
Expand Down
19 changes: 8 additions & 11 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3277,18 +3277,15 @@ mod test {
// This check right now expects to only call one Brillig function.
let mut num_normal_brillig_calls = 0;
for (i, opcode) in opcodes.iter().enumerate() {
match opcode {
Opcode::BrilligCall { id, .. } => {
if brillig_stdlib_function_locations.get(&OpcodeLocation::Acir(i)).is_some() {
// We should have already checked Brillig stdlib functions and only want to check normal Brillig calls here
continue;
}
// We only generate one normal Brillig call so we should expect a function ID of `0`
let expected_id = 0u32;
assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}");
num_normal_brillig_calls += 1;
if let Opcode::BrilligCall { id, .. } = opcode {
if brillig_stdlib_function_locations.get(&OpcodeLocation::Acir(i)).is_some() {
// We should have already checked Brillig stdlib functions and only want to check normal Brillig calls here
continue;
}
_ => {}
// We only generate one normal Brillig call so we should expect a function ID of `0`
let expected_id = 0u32;
assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}");
num_normal_brillig_calls += 1;
}
}

Expand Down
67 changes: 0 additions & 67 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use noirc_frontend::monomorphization::ast::{FuncId, Program};
use crate::errors::RuntimeError;
use crate::ssa::function_builder::FunctionBuilder;
use crate::ssa::ir::basic_block::BasicBlockId;
use crate::ssa::ir::dfg::DataFlowGraph;
use crate::ssa::ir::function::{Function, RuntimeType};
use crate::ssa::ir::function::{FunctionId as IrFunctionId, InlineType};
use crate::ssa::ir::instruction::BinaryOp;
Expand Down Expand Up @@ -1005,72 +1004,6 @@ fn operator_requires_swapped_operands(op: BinaryOpKind) -> bool {
matches!(op, Greater | LessEqual)
}

/// If the operation requires its result to be truncated because it is an integer, the maximum
/// number of bits that result may occupy is returned.
fn operator_result_max_bit_size_to_truncate(
op: BinaryOpKind,
lhs: ValueId,
rhs: ValueId,
dfg: &DataFlowGraph,
) -> Option<u32> {
let lhs_type = dfg.type_of_value(lhs);
let rhs_type = dfg.type_of_value(rhs);

let get_bit_size = |typ| match typ {
Type::Numeric(NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size }) => {
Some(bit_size)
}
_ => None,
};

let lhs_bit_size = get_bit_size(lhs_type)?;
let rhs_bit_size = get_bit_size(rhs_type)?;
use BinaryOpKind::*;
match op {
Add => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1),
Subtract => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1),
Multiply => {
if lhs_bit_size == 1 || rhs_bit_size == 1 {
// Truncation is unnecessary as multiplication by a boolean value cannot cause an overflow.
None
} else {
Some(lhs_bit_size + rhs_bit_size)
}
}

ShiftLeft => {
if let Some(rhs_constant) = dfg.get_numeric_constant(rhs) {
// Happy case is that we know precisely by how many bits the the integer will
// increase: lhs_bit_size + rhs
return Some(lhs_bit_size + (rhs_constant.to_u128() as u32));
}
// Unhappy case is that we don't yet know the rhs value, (even though it will
// eventually have to resolve to a constant). The best we can is assume the value of
// rhs to be the maximum value of it's numeric type. If that turns out to be larger
// than the native field's bit size, we full back to using that.

// The formula for calculating the max bit size of a left shift is:
// lhs_bit_size + 2^{rhs_bit_size} - 1
// Inferring the max bit size of left shift from its operands can result in huge
// number, that might not only be larger than the native field's max bit size, but
// furthermore might not be representable as a u32. Hence we use overflow checks and
// fallback to the native field's max bits.
let field_max_bits = FieldElement::max_num_bits();
let (rhs_bit_size_pow_2, overflows) = 2_u32.overflowing_pow(rhs_bit_size);
if overflows {
return Some(field_max_bits);
}
let (max_bits_plus_1, overflows) = rhs_bit_size_pow_2.overflowing_add(lhs_bit_size);
if overflows {
return Some(field_max_bits);
}
let max_bit_size = std::cmp::min(max_bits_plus_1 - 1, field_max_bits);
Some(max_bit_size)
}
_ => None,
}
}

/// Converts the given operator to the appropriate BinaryOp.
/// Take care when using this to insert a binary instruction: this requires
/// checking operator_requires_not and operator_requires_swapped_operands
Expand Down
2 changes: 1 addition & 1 deletion noir/noir-repo/compiler/noirc_frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ license.workspace = true

[dependencies]
acvm.workspace = true
noirc_arena.workspace = true
noirc_errors.workspace = true
noirc_printable_type.workspace = true
fm.workspace = true
arena.workspace = true
iter-extended.workspace = true
chumsky.workspace = true
thiserror.workspace = true
Expand Down
Loading

0 comments on commit 078aa61

Please sign in to comment.