Skip to content

Commit

Permalink
chore: resolve immutable array merge differences (#1617)
Browse files Browse the repository at this point in the history
* chore(ssa refactor): Switch to immutable arrays (#1578)

* Represent SSA arrays with im::Vector

* Get tests passing

* Implement assign with immutable arrays

* Add constant folding pass

* Update comments

* Clippy

* Update comment

* Update type of array

* Update crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>

* Undo formatting changes in instruction.rs

* Massive acir_gen update

* Refactor acir array operations into a shared function

* Appease clippy

* Update to_radix and to_bits in acir_gen to return arrays

* Disable assert

* Fix convert_type for arrays

* Include AcirType in AcirValue::Var variant

* Fix black box functions

* Appease clippy

* Fix simple_radix

* Add doc comments

---------

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>

* feat: Make for-loop range be a polymorphic integer instead of just Field in unconstrained functions (#1583)

* make ranges be polymorphic integers

* make behavior consistent

* remove closure

* change index_type

* Update crates/noirc_frontend/src/hir/type_check/expr.rs

---------

Co-authored-by: jfecher <jake@aztecprotocol.com>

* chore(ssa refactor): fix brillig post master merge

* chore(ssa refactor): accidental merge undelete

---------

Co-authored-by: jfecher <jake@aztecprotocol.com>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: kevaundray <kevtheappdev@gmail.com>
  • Loading branch information
4 people authored Jun 9, 2023
1 parent 5995b30 commit 1a9d33c
Show file tree
Hide file tree
Showing 24 changed files with 869 additions and 809 deletions.
43 changes: 43 additions & 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 crates/nargo_cli/src/cli/prove_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) struct ProveCommand {
verifier_name: String,

/// Verify proof after proving
#[arg(short, long)]
#[arg(long)]
verify: bool,

#[clap(flatten)]
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ iter-extended.workspace = true
thiserror.workspace = true
num-bigint = "0.4"
num-traits = "0.2.8"
im = "15.1"

[dev-dependencies]
rand="0.8.5"
2 changes: 1 addition & 1 deletion crates/noirc_evaluator/src/brillig/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub(crate) fn type_of_binary_operation(lhs_type: Type, rhs_type: Type) -> Type {
);
Type::Numeric(lhs_type)
}
_ => {
(lhs_type, rhs_type) => {
unreachable!(
"ICE: Binary operation between types {:?} and {:?} is not allowed",
lhs_type, rhs_type
Expand Down
4 changes: 2 additions & 2 deletions crates/noirc_evaluator/src/brillig/brillig_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ impl BrilligGen {
let result_register = self.get_or_create_register(result_ids[0]);
self.convert_ssa_binary(binary, dfg, result_register);
}
Instruction::Allocate { size } => {
Instruction::Allocate => {
let pointer_register =
self.get_or_create_register(dfg.instruction_results(instruction_id)[0]);
self.allocate_array(pointer_register, *size);
self.allocate_array(pointer_register, 1);
}
Instruction::Store { address, value } => {
let address_register = self.convert_ssa_value(*address, dfg);
Expand Down
3 changes: 1 addition & 2 deletions crates/noirc_evaluator/src/ssa_refactor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ pub mod ssa_gen;
/// form and performing optimizations there. When finished,
/// convert the final SSA into ACIR and return it.
pub(crate) fn optimize_into_acir(program: Program, allow_log_ops: bool) -> GeneratedAcir {
let func_signature = program.main_function_signature.clone();
let ssa = ssa_gen::generate_ssa(program).print("Initial SSA:");
let brillig = ssa.to_brillig();
ssa.inline_functions()
Expand All @@ -44,7 +43,7 @@ pub(crate) fn optimize_into_acir(program: Program, allow_log_ops: bool) -> Gener
.print("After Mem2Reg:")
.fold_constants()
.print("After Constant Folding:")
.into_acir(func_signature, brillig, allow_log_ops)
.into_acir(brillig, allow_log_ops)
}

/// Compiles the Program into ACIR and applies optimizations to the arithmetic gates
Expand Down
87 changes: 1 addition & 86 deletions crates/noirc_evaluator/src/ssa_refactor/abi_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,92 +2,7 @@ use std::collections::BTreeMap;

use acvm::acir::native_types::Witness;
use iter_extended::{btree_map, vecmap};
use noirc_abi::{Abi, AbiParameter, AbiType, FunctionSignature};

/// Traverses the parameters to the program to infer the lengths of any arrays that occur.
///
/// This is needed for the acir_gen pass, because while the SSA representation of the program
/// knows the positions at which any arrays occur in the parameters to main, it does not know the
/// lengths of said arrays.
///
/// This function returns the lengths ordered such as to correspond to the ordering used by the
/// SSA representation. This allows the lengths to be consumed as array params are encountered in
/// the SSA.
pub(crate) fn collate_array_info(abi_params: &[AbiParameter]) -> Vec<(usize, AbiType)> {
let mut acc = Vec::new();
for abi_param in abi_params {
collate_array_info_recursive(&mut acc, &abi_param.typ);
}
acc
}

/// The underlying recursive implementation of `collate_array_info`
///
/// This does a depth-first traversal of the abi until an array (or string) is encountered, at
/// which point arrays are handled differently depending on the element type:
/// - arrays of fields, integers or booleans produce an array of the specified length
/// - arrays of structs produce an array of the specified length for each field of the flatten
/// struct (which reflects a simplification made during monomorphization)
fn collate_array_info_recursive(acc: &mut Vec<(usize, AbiType)>, abi_type: &AbiType) {
match abi_type {
AbiType::Array { length, typ: elem_type } => {
let elem_type = elem_type.as_ref();
match elem_type {
AbiType::Array { .. } => {
unreachable!("2D arrays are not supported");
}
AbiType::Struct { .. } => {
// monomorphization converts arrays of structs into an array per flattened
// struct field.
let mut destructured_array_types = Vec::new();
flatten_abi_type_recursive(&mut destructured_array_types, elem_type);
for abi_type in destructured_array_types {
acc.push((*length as usize, abi_type));
}
}
AbiType::String { .. } => {
unreachable!("Arrays of strings are not supported");
}
AbiType::Boolean | AbiType::Field | AbiType::Integer { .. } => {
// Simple 1D array
acc.push((*length as usize, elem_type.clone()));
}
}
}
AbiType::Struct { fields } => {
for (_, field_type) in fields {
collate_array_info_recursive(acc, field_type);
}
}
AbiType::String { length } => {
// Strings are implemented as u8 arrays
let element_type = AbiType::Integer { sign: noirc_abi::Sign::Unsigned, width: 8 };
acc.push((*length as usize, element_type));
}
AbiType::Boolean | AbiType::Field | AbiType::Integer { .. } => {
// Do not produce arrays
}
}
}

/// Used for flattening a struct into its ordered constituent field types. This is needed for
/// informing knowing the bit widths of any array sets that were destructured from an array of
/// structs. For this reason, any array encountered within this function are considered to be
/// nested within a struct and are therefore disallowed. This is acceptable because this function
/// will only be applied to structs which have been found in an array.
fn flatten_abi_type_recursive(acc: &mut Vec<AbiType>, abi_type: &AbiType) {
match abi_type {
AbiType::Array { .. } | AbiType::String { .. } => {
unreachable!("2D arrays are unsupported")
}
AbiType::Boolean | AbiType::Integer { .. } | AbiType::Field => acc.push(abi_type.clone()),
AbiType::Struct { fields } => {
for (_, field_type) in fields {
flatten_abi_type_recursive(acc, field_type);
}
}
}
}
use noirc_abi::{Abi, AbiParameter, FunctionSignature};

/// Arranges a function signature and a generated circuit's return witnesses into a
/// `noirc_abi::Abi`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub(crate) mod acir_variable;
pub(crate) mod errors;
pub(crate) mod generated_acir;
pub(crate) mod memory;
Loading

0 comments on commit 1a9d33c

Please sign in to comment.