Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
f55d717
Start #7897
aakoshh Apr 2, 2025
e1c966f
FunctionContext::gen_expr
aakoshh Apr 2, 2025
290542d
Add Scope with type producers
aakoshh Apr 2, 2025
08cc1e2
Produce a type from available variables
aakoshh Apr 2, 2025
97c719a
Produce the array index from random expressions
aakoshh Apr 2, 2025
2e413a4
Produce a target from a tuple
aakoshh Apr 2, 2025
7ae8e34
Supress unused warnings
aakoshh Apr 2, 2025
0c85c82
Separate locals and global scope
aakoshh Apr 2, 2025
39eda06
Compose objects from expressions
aakoshh Apr 2, 2025
eb440dc
Try improve readability with shorter names
aakoshh Apr 2, 2025
774faf6
Deref references
aakoshh Apr 3, 2025
e51391a
Generate unary
aakoshh Apr 3, 2025
12580d1
Generate binary
aakoshh Apr 3, 2025
94f3385
Refactor freq
aakoshh Apr 3, 2025
dbcc6f1
Block and Let
aakoshh Apr 3, 2025
42228a3
If expr
aakoshh Apr 3, 2025
1ab57ba
Register locals
aakoshh Apr 3, 2025
3910f1c
If as statement
aakoshh Apr 3, 2025
12adf63
Semi
aakoshh Apr 3, 2025
248003d
Drop
aakoshh Apr 3, 2025
3b1e6fb
Factor out frequencies into the config
aakoshh Apr 3, 2025
44a4f0b
Show mutability in AST print
aakoshh Apr 3, 2025
9e6baec
Assign
aakoshh Apr 3, 2025
2dd4b68
push/pop scopes for if-then-else
aakoshh Apr 3, 2025
89edf54
Reduce function size
aakoshh Apr 3, 2025
1d19a5f
Separate freq module
aakoshh Apr 4, 2025
c8af28a
Separate scope module
aakoshh Apr 4, 2025
0dca936
Test scope cloning and types produced
aakoshh Apr 4, 2025
7a5316f
Add ScopeStack
aakoshh Apr 4, 2025
5eab799
Redistribute frequencies
aakoshh Apr 4, 2025
6545dd6
Tweaks to weights, fix blocks in condition
aakoshh Apr 4, 2025
3736ac0
Rename if_then to if
aakoshh Apr 4, 2025
8ea40ff
For loop
aakoshh Apr 4, 2025
028d2ab
Remove unused
aakoshh Apr 4, 2025
d6e7e52
TODO ticket numbers
aakoshh Apr 4, 2025
27f6551
Tweak budgets to try to avoid trivial unit ifs
aakoshh Apr 4, 2025
027027b
Merge remote-tracking branch 'origin/master' into af/7879-ast-fuzz-fn…
aakoshh Apr 4, 2025
cf3b3ec
Merge branch 'master' into af/7879-ast-fuzz-fn-body
rkarabut Apr 6, 2025
c702d81
Fix name
aakoshh Apr 7, 2025
46546c8
Merge branch 'af/7879-ast-fuzz-fn-body' of github.com:noir-lang/noir …
aakoshh Apr 7, 2025
1337539
Comments about ordering freq.enabled_when
aakoshh Apr 7, 2025
c3bf260
Better test case for redistribution
aakoshh Apr 7, 2025
6944621
Print the AST, inputs, ACIR and Brillig upon failure
aakoshh Apr 7, 2025
e013d53
Don't fail if the assertion payload is the same
aakoshh Apr 7, 2025
85ac778
Fix clippy
aakoshh Apr 7, 2025
5d59aca
Add name and type to globals so we can see what the AST is
aakoshh Apr 7, 2025
c8fdb82
Merge branch 'master' into af/7879-ast-fuzz-fn-body
aakoshh Apr 7, 2025
87c2cb9
Fix the failing monomorphization test
aakoshh Apr 7, 2025
3a9b8d1
Print the SSA during compilation if the debug flag is on
aakoshh Apr 7, 2025
1ddece1
Stop using i128 in unary and binary ops
aakoshh Apr 7, 2025
4c9f8a7
Only consider binary op inputs which are compatible with the output
aakoshh Apr 7, 2025
434635a
Merge remote-tracking branch 'origin/master' into af/7879-ast-fuzz-fn…
aakoshh Apr 7, 2025
c633d2a
Binary ops only work on numeric types
aakoshh Apr 7, 2025
d99e0c9
Merge branch 'master' into af/7879-ast-fuzz-fn-body
rkarabut Apr 8, 2025
9229d8b
Cast binary result to target if needed
aakoshh Apr 8, 2025
cdd4da8
Merge branch 'af/7879-ast-fuzz-fn-body' of github.com:noir-lang/noir …
aakoshh Apr 8, 2025
fe84562
Consider division by zero and unsatisified constrain equal
aakoshh Apr 8, 2025
56991a3
Don't generate negative i128 literals
aakoshh Apr 8, 2025
a1f125d
Add GITHUB_TOKEN for downloading prost_prebuilt
aakoshh Apr 8, 2025
9244871
Add GITHUB_TOKEN for downloading prost_prebuilt
aakoshh Apr 8, 2025
31a3d3c
Print the error in debug format when one of them failed
aakoshh Apr 8, 2025
54d7cf1
Separate env vars for printing AST and SSA. Budget limited by data
aakoshh Apr 8, 2025
9a084c7
Don't generate i1 for globals
aakoshh Apr 8, 2025
697b0f5
More types that don't work in global
aakoshh Apr 8, 2025
2bfb47f
Treat modulo as arithmetic
aakoshh Apr 8, 2025
4545562
No need to cast to bool
aakoshh Apr 8, 2025
d1b3bf1
Merge branch 'master' into af/7879-ast-fuzz-fn-body
aakoshh Apr 9, 2025
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
5 changes: 4 additions & 1 deletion .github/workflows/formatting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ jobs:

- name: Run `cargo doc`
run: cargo doc --no-deps --document-private-items --workspace
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

eslint:
name: eslint
Expand Down Expand Up @@ -125,6 +127,8 @@ jobs:

- name: Build Nargo
run: cargo build --package nargo_cli --release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Package artifacts
run: |
Expand Down Expand Up @@ -184,4 +188,3 @@ jobs:
env:
# We treat any skipped or failing jobs as a failure for the workflow as a whole.
FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}

1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ impl SharedContext {
GlobalsGraph::default(),
);
let mut globals = BTreeMap::default();
for (id, global) in program.globals.iter() {
for (id, (_, _, global)) in program.globals.iter() {
let values = context.codegen_expression(global).unwrap();
globals.insert(*id, values);
}
Expand Down
28 changes: 26 additions & 2 deletions compiler/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,7 @@ impl Expression {

pub type BinaryOp = Located<BinaryOpKind>;

#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, Clone)]
#[cfg_attr(test, derive(strum_macros::EnumIter))]
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, Clone, strum_macros::EnumIter)]
pub enum BinaryOpKind {
Add,
Subtract,
Expand Down Expand Up @@ -339,6 +338,31 @@ impl BinaryOpKind {
)
}

/// `==` and `!=`
pub fn is_equality(self) -> bool {
matches!(self, BinaryOpKind::Equal | BinaryOpKind::NotEqual)
}

/// `+`, `-`, `*`, `/` and `%`
pub fn is_arithmetic(self) -> bool {
matches!(
self,
BinaryOpKind::Add
| BinaryOpKind::Subtract
| BinaryOpKind::Multiply
| BinaryOpKind::Divide
| BinaryOpKind::Modulo
)
}

pub fn is_bitwise(self) -> bool {
matches!(self, BinaryOpKind::And | BinaryOpKind::Or | BinaryOpKind::Xor)
}

pub fn is_bitshift(self) -> bool {
matches!(self, BinaryOpKind::ShiftLeft | BinaryOpKind::ShiftRight)
}

pub fn is_valid_for_field_type(self) -> bool {
matches!(
self,
Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl From<IntegerBitSize> for u32 {
}
}

#[derive(Debug)]
pub struct InvalidIntegerBitSizeError(pub u32);

impl TryFrom<u32> for IntegerBitSize {
Expand Down
8 changes: 4 additions & 4 deletions compiler/noirc_frontend/src/monomorphization/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ pub struct Program {
pub main_function_signature: FunctionSignature,
pub return_location: Option<Location>,
pub return_visibility: Visibility,
pub globals: BTreeMap<GlobalId, Expression>,
pub globals: BTreeMap<GlobalId, (String, Type, Expression)>,
pub debug_variables: DebugVariables,
pub debug_functions: DebugFunctions,
pub debug_types: DebugTypes,
Expand All @@ -381,7 +381,7 @@ impl Program {
main_function_signature: FunctionSignature,
return_location: Option<Location>,
return_visibility: Visibility,
globals: BTreeMap<GlobalId, Expression>,
globals: BTreeMap<GlobalId, (String, Type, Expression)>,
debug_variables: DebugVariables,
debug_functions: DebugFunctions,
debug_types: DebugTypes,
Expand Down Expand Up @@ -444,8 +444,8 @@ impl std::ops::IndexMut<FuncId> for Program {
impl std::fmt::Display for Program {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut printer = super::printer::AstPrinter::default();
for (id, expr) in &self.globals {
printer.print_global(id, expr, f)?;
for (id, global) in &self.globals {
printer.print_global(id, global, f)?;
}
for function in &self.functions {
printer.print_function(function, f)?;
Expand Down
5 changes: 2 additions & 3 deletions compiler/noirc_frontend/src/monomorphization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct Monomorphizer<'interner> {
/// Globals are keyed by their unique ID because they are never duplicated during monomorphization.
globals: HashMap<node_interner::GlobalId, GlobalId>,

finished_globals: HashMap<GlobalId, ast::Expression>,
finished_globals: HashMap<GlobalId, (String, ast::Type, ast::Expression)>,

/// Queue of functions to monomorphize next each item in the queue is a tuple of:
/// (old_id, new_monomorphized_id, any type bindings to apply, the trait method if old_id is from a trait impl, is_unconstrained, location)
Expand Down Expand Up @@ -1103,9 +1103,8 @@ impl<'interner> Monomorphizer<'interner> {
if !is_closure {
let new_id = self.next_global_id();
self.globals.insert(id, new_id);

self.finished_globals.insert(new_id, expr);
let typ = Self::convert_type(typ, location)?;
self.finished_globals.insert(new_id, (name.clone(), typ.clone(), expr));
let ident = ast::Ident {
location: Some(location),
definition: Definition::Global(new_id),
Expand Down
23 changes: 16 additions & 7 deletions compiler/noirc_frontend/src/monomorphization/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::ast::UnaryOp;

use super::ast::{Definition, Expression, Function, GlobalId, LValue, While};
use super::ast::{Definition, Expression, Function, GlobalId, LValue, Type, While};
use iter_extended::vecmap;
use std::fmt::{Display, Formatter};

Expand All @@ -15,11 +15,10 @@ impl AstPrinter {
pub fn print_global(
&mut self,
id: &GlobalId,
expr: &Expression,
(name, typ, expr): &(String, Type, Expression),
f: &mut Formatter,
) -> std::fmt::Result {
// At the moment globals don't carry their name, nor a type.
write!(f, "global $g{} = ", id.0)?;
write!(f, "global {}$g{}: {} = ", name, id.0, typ)?;
self.print_expr(expr, f)?;
write!(f, ";")?;
self.next_line(f)
Expand All @@ -33,8 +32,12 @@ impl AstPrinter {

write!(
f,
"fn {}$f{}({}) -> {} {{",
function.name, function.id, params, function.return_type
"{}fn {}$f{}({}) -> {} {{",
if function.unconstrained { "unconstrained " } else { "" },
function.name,
function.id,
params,
function.return_type
)?;
self.indent_level += 1;
self.print_expr_expect_block(&function.body, f)?;
Expand Down Expand Up @@ -75,7 +78,13 @@ impl AstPrinter {
}
Expression::Call(call) => self.print_call(call, f),
Expression::Let(let_expr) => {
write!(f, "let {}${} = ", let_expr.name, let_expr.id.0)?;
write!(
f,
"let {}{}${} = ",
if let_expr.mutable { "mut " } else { "" },
let_expr.name,
let_expr.id.0
)?;
self.print_expr(&let_expr.expression, f)
}
Expression::Constrain(expr, ..) => {
Expand Down
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"bindgen",
"bitand",
"bitmask",
"bitshift",
"bitsize",
"blackbox",
"boilerplate",
Expand Down Expand Up @@ -108,6 +109,7 @@
"foralls",
"formatcp",
"fpath",
"freqs",
"frontends",
"fuzzer",
"fxhash",
Expand Down
9 changes: 9 additions & 0 deletions test_programs/execution_success/loop/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ fn main(six_as_u32: u32) {
assert_eq(loop_excl(4), six_as_u32);
assert_eq(loop_incl(3), six_as_u32);
assert(plain_loop() == six_as_u32);
assert(never_loop() == 0);
}

fn loop_excl(x: u32) -> u32 {
Expand All @@ -30,3 +31,11 @@ fn plain_loop() -> u32 {
}
sum
}

fn never_loop() -> u32 {
let mut sum = 0;
for i in 4..0 {
sum = sum + i;
}
sum
}
1 change: 1 addition & 0 deletions tooling/ast_fuzzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ proptest.workspace = true
strum.workspace = true

acir.workspace = true
acvm.workspace = true
bn254_blackbox_solver.workspace = true
nargo.workspace = true
noirc_abi.workspace = true
Expand Down
6 changes: 3 additions & 3 deletions tooling/ast_fuzzer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ orig_vs_mutant
and execute it with some time or execution limits:

```shell
cargo +nightly fuzz run init_vs_final -- -runs=1000 -max_total_time=60 -max_len=1048576
cargo +nightly fuzz run acir_vs_brillig -- -runs=1000 -max_total_time=60 -max_len=1048576
```

If there is an error, `cargo fuzz` will capture the artifacts required for a repeated run under the `artifacts` directory, and will print the command to run it again, which can be done with something like this:

```shell
NOIR_AST_FUZZER_DEBUG=1 cargo +nightly fuzz run -O init_vs_final fuzz/artifacts/init_vs_final/crash-fa077fcded882761fcf273eda7f429a833a80a7d
cargo +nightly fuzz run -O acir_vs_brillig fuzz/artifacts/acir_vs_brillig/crash-9270e36f612ed9022ede3496c97c24cebb6e2301
```

Note that `cargo fuzz` requires `nightly` build, which can be either turned on with the `cargo +nightly` flag, or by running `rustup default nightly`. Also note that `cargo fuzz run` automatically creates a `--release` build, there is no need for an explicit flag to be passed.

The `NOIR_AST_FUZZER_DEBUG` env var can be used to print the AST before compilation.
The `NOIR_AST_FUZZER_SHOW_AST` env var can be used to print the AST before compilation, in case the compiler crashes on the generated program. Otherwise if the execution fails, the output will include the AST, the inputs, and the ACIR/Brillig opcodes.
22 changes: 3 additions & 19 deletions tooling/ast_fuzzer/fuzz/fuzz_targets/acir_vs_brillig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,19 @@

#![no_main]

use acir::circuit::ExpressionWidth;
use color_eyre::eyre::{self, Context};
use libfuzzer_sys::arbitrary::Unstructured;
use libfuzzer_sys::fuzz_target;
use noir_ast_fuzzer::Config;
use noir_ast_fuzzer::compare::CompareMutants;
use noir_ast_fuzzer_fuzz::create_ssa_or_die;
use noirc_evaluator::brillig::BrilligOptions;
use noirc_evaluator::ssa;
use noir_ast_fuzzer_fuzz::{compare_results, create_ssa_or_die, default_ssa_options};

fuzz_target!(|data: &[u8]| {
fuzz(&mut Unstructured::new(data)).unwrap();
});

fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {
let options = ssa::SsaEvaluatorOptions {
ssa_logging: ssa::SsaLogging::None,
brillig_options: BrilligOptions::default(),
print_codegen_timings: false,
expression_width: ExpressionWidth::default(),
emit_ssa: None,
skip_underconstrained_check: true,
skip_brillig_constraints_check: true,
enable_brillig_constraints_check_lookback: false,
inliner_aggressiveness: 0,
max_bytecode_increase_percent: None,
};

let options = default_ssa_options();
let inputs = CompareMutants::arb(
u,
Config::default(),
Expand All @@ -47,6 +32,5 @@ fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {

let result = inputs.exec().wrap_err("exec")?;

let _ = result.return_value_or_err()?;
Ok(())
compare_results(&inputs, &result, |inputs| [&inputs.program.0, &inputs.program.1])
}
20 changes: 3 additions & 17 deletions tooling/ast_fuzzer/fuzz/fuzz_targets/init_vs_final.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,20 @@
//! and the fully optimized version.
#![no_main]

use acir::circuit::ExpressionWidth;
use color_eyre::eyre::{self, Context};
use libfuzzer_sys::arbitrary::Unstructured;
use libfuzzer_sys::fuzz_target;
use noir_ast_fuzzer::Config;
use noir_ast_fuzzer::compare::ComparePasses;
use noir_ast_fuzzer_fuzz::create_ssa_or_die;
use noirc_evaluator::brillig::BrilligOptions;
use noir_ast_fuzzer_fuzz::{compare_results, create_ssa_or_die, default_ssa_options};
use noirc_evaluator::ssa;

fuzz_target!(|data: &[u8]| {
fuzz(&mut Unstructured::new(data)).unwrap();
});

fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {
let options = ssa::SsaEvaluatorOptions {
ssa_logging: ssa::SsaLogging::None,
brillig_options: BrilligOptions::default(),
print_codegen_timings: false,
expression_width: ExpressionWidth::default(),
emit_ssa: None,
skip_underconstrained_check: true,
skip_brillig_constraints_check: true,
enable_brillig_constraints_check_lookback: false,
inliner_aggressiveness: 0,
max_bytecode_increase_percent: None,
};
let options = default_ssa_options();

// TODO(#7873): What we really want is to do the minimum number of passes on the SSA to leave it as close to the initial SSA as possible.
// For now just test with min/max inliner aggressiveness.
Expand All @@ -54,6 +41,5 @@ fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {

let result = inputs.exec().wrap_err("exec")?;

let _ = result.return_value_or_err()?;
Ok(())
compare_results(&inputs, &result, |inputs| [&inputs.program])
}
22 changes: 3 additions & 19 deletions tooling/ast_fuzzer/fuzz/fuzz_targets/orig_vs_mutant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,19 @@
//! execution result does not change.
#![no_main]

use acir::circuit::ExpressionWidth;
use color_eyre::eyre::{self, Context};
use libfuzzer_sys::arbitrary::Unstructured;
use libfuzzer_sys::fuzz_target;
use noir_ast_fuzzer::Config;
use noir_ast_fuzzer::compare::CompareMutants;
use noir_ast_fuzzer_fuzz::create_ssa_or_die;
use noirc_evaluator::brillig::BrilligOptions;
use noirc_evaluator::ssa;
use noir_ast_fuzzer_fuzz::{compare_results, create_ssa_or_die, default_ssa_options};

fuzz_target!(|data: &[u8]| {
fuzz(&mut Unstructured::new(data)).unwrap();
});

fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {
let options = ssa::SsaEvaluatorOptions {
ssa_logging: ssa::SsaLogging::None,
brillig_options: BrilligOptions::default(),
print_codegen_timings: false,
expression_width: ExpressionWidth::default(),
emit_ssa: None,
skip_underconstrained_check: true,
skip_brillig_constraints_check: true,
enable_brillig_constraints_check_lookback: false,
inliner_aggressiveness: 0,
max_bytecode_increase_percent: None,
};

let options = default_ssa_options();
let inputs = CompareMutants::arb(
u,
Config::default(),
Expand All @@ -42,6 +27,5 @@ fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {

let result = inputs.exec().wrap_err("exec")?;

let _ = result.return_value_or_err()?;
Ok(())
compare_results(&inputs, &result, |inputs| [&inputs.program.0, &inputs.program.1])
}
Loading
Loading