Skip to content

Commit

Permalink
[1 changes] chore: fix examples (noir-lang/noir#5357)
Browse files Browse the repository at this point in the history
chore: `static_assert` error message fix and split into is-dynamic and is-false (noir-lang/noir#5353)
fix: ignore calls to `Intrinsic::AsWitness` during brillig codegen (noir-lang/noir#5350)
fix: address compiler warnings coming from stdlib (noir-lang/noir#5351)
feat: `static_assert` builtin (noir-lang/noir#5342)
feat: Sync from aztec-packages (noir-lang/noir#5347)
chore: replace `regression_5202` with more manageably sized program (noir-lang/noir#5345)
feat: disable nargo color output if stderr is tty (noir-lang/noir#5346)
  • Loading branch information
AztecBot committed Jun 29, 2024
1 parent ed815a3 commit a863c1d
Show file tree
Hide file tree
Showing 170 changed files with 3,128 additions and 1,013 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f2f8ecc833d4725d0829f9c339389c90d1a4fbcd
6936a52bb4de2170b6e4c41afd9cf4327d4fbeb1
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
7 changes: 3 additions & 4 deletions noir/noir-repo/aztec_macros/src/transforms/note_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt
type_span: note_struct.name.span(),
generics: vec![],
methods: vec![],
where_clause: vec![],
};
module.impls.push(default_impl.clone());
module.impls.last_mut().unwrap()
Expand Down Expand Up @@ -562,8 +563,7 @@ fn generate_note_properties_struct_source(
.filter_map(|(field_name, _)| {
if field_name != note_header_field_name {
Some(format!(
"{}: dep::aztec::note::note_getter_options::PropertySelector",
field_name
"{field_name}: dep::aztec::note::note_getter_options::PropertySelector"
))
} else {
None
Expand Down Expand Up @@ -670,8 +670,7 @@ fn generate_note_deserialize_content_source(
}
} else {
format!(
"{}: dep::aztec::note::note_header::NoteHeader::empty()",
note_header_field_name
"{note_header_field_name}: dep::aztec::note::note_header::NoteHeader::empty()"
)
}
})
Expand Down
6 changes: 4 additions & 2 deletions noir/noir-repo/aztec_macros/src/transforms/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub fn inject_context_in_storage(module: &mut SortedModule) -> Result<(), AztecM
r#struct.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)"))
})
.unwrap();
storage_struct.generics.push(ident("Context"));
storage_struct.generics.push(ident("Context").into());
storage_struct
.fields
.iter_mut()
Expand Down Expand Up @@ -243,9 +243,11 @@ pub fn generate_storage_implementation(
span: Some(Span::default()),
},
type_span: Span::default(),
generics: vec![generic_context_ident],
generics: vec![generic_context_ident.into()],

methods: vec![(init, Span::default())],

where_clause: vec![],
};
module.impls.push(storage_impl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn stdlib_does_not_produce_constant_warnings() -> Result<(), ErrorsAndWarnings>
let ((), warnings) =
noirc_driver::check_crate(&mut context, root_crate_id, false, false, false)?;

assert_eq!(warnings, Vec::new(), "stdlib is producing warnings");
assert_eq!(warnings, Vec::new(), "stdlib is producing {} warnings", warnings.len());

Ok(())
}
6 changes: 5 additions & 1 deletion noir/noir-repo/compiler/noirc_errors/src/reporter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::io::IsTerminal;

use crate::{FileDiagnostic, Location, Span};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::Files;
Expand Down Expand Up @@ -148,7 +150,9 @@ pub fn report<'files>(
call_stack: &[Location],
deny_warnings: bool,
) -> bool {
let writer = StandardStream::stderr(ColorChoice::Always);
let color_choice =
if std::io::stderr().is_terminal() { ColorChoice::Auto } else { ColorChoice::Never };
let writer = StandardStream::stderr(color_choice);
let config = codespan_reporting::term::Config::default();

let stack_trace = stack_trace(files, call_stack);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use acvm::{acir::AcirField, FieldElement};
use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet};
use iter_extended::vecmap;
use num_bigint::BigUint;
use std::rc::Rc;

use super::brillig_black_box::convert_black_box_call;
use super::brillig_block_variables::BlockVariables;
Expand Down Expand Up @@ -582,6 +583,11 @@ impl<'block> BrilligBlock<'block> {
1,
);
}

// `Intrinsic::AsWitness` is used to provide hints to acir-gen on optimal expression splitting.
// It is then useless in the brillig runtime and so we can ignore it
Value::Intrinsic(Intrinsic::AsWitness) => (),

_ => {
unreachable!("unsupported function call type {:?}", dfg[*func])
}
Expand Down Expand Up @@ -1629,7 +1635,7 @@ impl<'block> BrilligBlock<'block> {
new_variable
}
}
Value::Array { array, .. } => {
Value::Array { array, typ } => {
if let Some(variable) = self.variables.get_constant(value_id, dfg) {
variable
} else {
Expand Down Expand Up @@ -1664,23 +1670,7 @@ impl<'block> BrilligBlock<'block> {

// Write the items

// Allocate a register for the iterator
let iterator_register =
self.brillig_context.make_usize_constant_instruction(0_usize.into());

for element_id in array.iter() {
let element_variable = self.convert_ssa_value(*element_id, dfg);
// Store the item in memory
self.store_variable_in_array(pointer, iterator_register, element_variable);
// Increment the iterator
self.brillig_context.codegen_usize_op_in_place(
iterator_register.address,
BrilligBinaryOp::Add,
1,
);
}

self.brillig_context.deallocate_single_addr(iterator_register);
self.initialize_constant_array(array, typ, dfg, pointer);

new_variable
}
Expand All @@ -1705,6 +1695,125 @@ impl<'block> BrilligBlock<'block> {
}
}

fn initialize_constant_array(
&mut self,
data: &im::Vector<ValueId>,
typ: &Type,
dfg: &DataFlowGraph,
pointer: MemoryAddress,
) {
if data.is_empty() {
return;
}
let item_types = typ.clone().element_types();

// Find out if we are repeating the same item over and over
let first_item = data.iter().take(item_types.len()).copied().collect();
let mut is_repeating = true;

for item_index in (item_types.len()..data.len()).step_by(item_types.len()) {
let item: Vec<_> = (0..item_types.len()).map(|i| data[item_index + i]).collect();
if first_item != item {
is_repeating = false;
break;
}
}

// If all the items are single address, and all have the same initial value, we can initialize the array in a runtime loop.
// Since the cost in instructions for a runtime loop is in the order of magnitude of 10, we only do this if the item_count is bigger than that.
let item_count = data.len() / item_types.len();

if item_count > 10
&& is_repeating
&& item_types.iter().all(|typ| matches!(typ, Type::Numeric(_)))
{
self.initialize_constant_array_runtime(
item_types, first_item, item_count, pointer, dfg,
);
} else {
self.initialize_constant_array_comptime(data, dfg, pointer);
}
}

fn initialize_constant_array_runtime(
&mut self,
item_types: Rc<Vec<Type>>,
item_to_repeat: Vec<ValueId>,
item_count: usize,
pointer: MemoryAddress,
dfg: &DataFlowGraph,
) {
let mut subitem_to_repeat_variables = Vec::with_capacity(item_types.len());
for subitem_id in item_to_repeat.into_iter() {
subitem_to_repeat_variables.push(self.convert_ssa_value(subitem_id, dfg));
}

let data_length_variable = self
.brillig_context
.make_usize_constant_instruction((item_count * item_types.len()).into());

// If this is an array with complex subitems, we need a custom step in the loop to write all the subitems while iterating.
if item_types.len() > 1 {
let step_variable =
self.brillig_context.make_usize_constant_instruction(item_types.len().into());

let subitem_pointer =
SingleAddrVariable::new_usize(self.brillig_context.allocate_register());

let initializer_fn = |ctx: &mut BrilligContext<_>, iterator: SingleAddrVariable| {
ctx.mov_instruction(subitem_pointer.address, iterator.address);
for subitem in subitem_to_repeat_variables.into_iter() {
Self::store_variable_in_array_with_ctx(ctx, pointer, subitem_pointer, subitem);
ctx.codegen_usize_op_in_place(subitem_pointer.address, BrilligBinaryOp::Add, 1);
}
};

self.brillig_context.codegen_loop_with_bound_and_step(
data_length_variable.address,
step_variable.address,
initializer_fn,
);

self.brillig_context.deallocate_single_addr(step_variable);
self.brillig_context.deallocate_single_addr(subitem_pointer);
} else {
let subitem = subitem_to_repeat_variables.into_iter().next().unwrap();

let initializer_fn = |ctx: &mut _, iterator_register| {
Self::store_variable_in_array_with_ctx(ctx, pointer, iterator_register, subitem);
};

self.brillig_context.codegen_loop(data_length_variable.address, initializer_fn);
}

self.brillig_context.deallocate_single_addr(data_length_variable);
}

fn initialize_constant_array_comptime(
&mut self,
data: &im::Vector<crate::ssa::ir::map::Id<Value>>,
dfg: &DataFlowGraph,
pointer: MemoryAddress,
) {
// Allocate a register for the iterator
let iterator_register =
self.brillig_context.make_usize_constant_instruction(0_usize.into());

for element_id in data.iter() {
let element_variable = self.convert_ssa_value(*element_id, dfg);
// Store the item in memory
self.store_variable_in_array(pointer, iterator_register, element_variable);
// Increment the iterator
self.brillig_context.codegen_usize_op_in_place(
iterator_register.address,
BrilligBinaryOp::Add,
1,
);
}

self.brillig_context.deallocate_single_addr(iterator_register);
}

/// Converts an SSA `ValueId` into a `MemoryAddress`. Initializes if necessary.
fn convert_ssa_single_addr_value(
&mut self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ impl<F: AcirField + DebugToString> BrilligContext<F> {
self.stop_instruction();
}

/// This codegen will issue a loop that will iterate iteration_count times
/// This codegen will issue a loop do for (let iterator_register = 0; i < loop_bound; i += step)
/// The body of the loop should be issued by the caller in the on_iteration closure.
pub(crate) fn codegen_loop(
pub(crate) fn codegen_loop_with_bound_and_step(
&mut self,
iteration_count: MemoryAddress,
loop_bound: MemoryAddress,
step: MemoryAddress,
on_iteration: impl FnOnce(&mut BrilligContext<F>, SingleAddrVariable),
) {
let iterator_register = self.make_usize_constant_instruction(0_u128.into());
Expand All @@ -52,13 +53,13 @@ impl<F: AcirField + DebugToString> BrilligContext<F> {

// Loop body

// Check if iterator < iteration_count
// Check if iterator < loop_bound
let iterator_less_than_iterations =
SingleAddrVariable { address: self.allocate_register(), bit_size: 1 };

self.memory_op_instruction(
iterator_register.address,
iteration_count,
loop_bound,
iterator_less_than_iterations.address,
BrilligBinaryOp::LessThan,
);
Expand All @@ -72,8 +73,13 @@ impl<F: AcirField + DebugToString> BrilligContext<F> {
// Call the on iteration function
on_iteration(self, iterator_register);

// Increment the iterator register
self.codegen_usize_op_in_place(iterator_register.address, BrilligBinaryOp::Add, 1);
// Add step to the iterator register
self.memory_op_instruction(
iterator_register.address,
step,
iterator_register.address,
BrilligBinaryOp::Add,
);

self.jump_instruction(loop_label);

Expand All @@ -85,6 +91,18 @@ impl<F: AcirField + DebugToString> BrilligContext<F> {
self.deallocate_single_addr(iterator_register);
}

/// This codegen will issue a loop that will iterate iteration_count times
/// The body of the loop should be issued by the caller in the on_iteration closure.
pub(crate) fn codegen_loop(
&mut self,
iteration_count: MemoryAddress,
on_iteration: impl FnOnce(&mut BrilligContext<F>, SingleAddrVariable),
) {
let step = self.make_usize_constant_instruction(1_u128.into());
self.codegen_loop_with_bound_and_step(iteration_count, step.address, on_iteration);
self.deallocate_single_addr(step);
}

/// This codegen will issue an if-then branch that will check if the condition is true
/// and if so, perform the instructions given in `f(self, true)` and otherwise perform the
/// instructions given in `f(self, false)`. A boolean is passed instead of two separate
Expand Down
9 changes: 9 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ pub enum RuntimeError {
UnknownLoopBound { call_stack: CallStack },
#[error("Argument is not constant")]
AssertConstantFailed { call_stack: CallStack },
#[error("The static_assert message is not constant")]
StaticAssertDynamicMessage { call_stack: CallStack },
#[error("Argument is dynamic")]
StaticAssertDynamicPredicate { call_stack: CallStack },
#[error("Argument is false")]
StaticAssertFailed { call_stack: CallStack },
#[error("Nested slices are not supported")]
NestedSlice { call_stack: CallStack },
#[error("Big Integer modulus do no match")]
Expand Down Expand Up @@ -120,6 +126,9 @@ impl RuntimeError {
| RuntimeError::UnInitialized { call_stack, .. }
| RuntimeError::UnknownLoopBound { call_stack }
| RuntimeError::AssertConstantFailed { call_stack }
| RuntimeError::StaticAssertDynamicMessage { call_stack }
| RuntimeError::StaticAssertDynamicPredicate { call_stack }
| RuntimeError::StaticAssertFailed { call_stack }
| RuntimeError::IntegerOutOfBounds { call_stack, .. }
| RuntimeError::UnsupportedIntegerSize { call_stack, .. }
| RuntimeError::NestedSlice { call_stack, .. }
Expand Down
5 changes: 4 additions & 1 deletion noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ pub(crate) fn optimize_into_acir(
// Run mem2reg with the CFG separated into blocks
.run_pass(Ssa::mem2reg, "After Mem2Reg:")
.run_pass(Ssa::as_slice_optimization, "After `as_slice` optimization")
.try_run_pass(Ssa::evaluate_assert_constant, "After Assert Constant:")?
.try_run_pass(
Ssa::evaluate_static_assert_and_assert_constant,
"After `static_assert` and `assert_constant`:",
)?
.try_run_pass(Ssa::unroll_loops_iteratively, "After Unrolling:")?
.run_pass(Ssa::simplify_cfg, "After Simplifying:")
.run_pass(Ssa::flatten_cfg, "After Flattening:")
Expand Down
17 changes: 15 additions & 2 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,22 @@ impl DataFlowGraph {
}
}

/// True if the given ValueId refers to a constant value
/// True if the given ValueId refers to a (recursively) constant value
pub(crate) fn is_constant(&self, argument: ValueId) -> bool {
!matches!(&self[self.resolve(argument)], Value::Instruction { .. } | Value::Param { .. })
match &self[self.resolve(argument)] {
Value::Instruction { .. } | Value::Param { .. } => false,
Value::Array { array, .. } => array.iter().all(|element| self.is_constant(*element)),
_ => true,
}
}

/// True that the input is a non-zero `Value::NumericConstant`
pub(crate) fn is_constant_true(&self, argument: ValueId) -> bool {
if let Some(constant) = self.get_numeric_constant(argument) {
!constant.is_zero()
} else {
false
}
}
}

Expand Down
Loading

0 comments on commit a863c1d

Please sign in to comment.