From 688489512b75bd8670e452282c9e5f060f7e9a69 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 20 Jul 2023 16:04:35 -0500 Subject: [PATCH 01/19] Start experiment to merge array and slice types --- crates/noirc_frontend/src/hir/def_map/mod.rs | 8 +- .../src/hir/resolution/resolver.rs | 2 + crates/noirc_frontend/src/hir_def/types.rs | 88 ++++++++++++++----- .../src/monomorphization/mod.rs | 27 +++--- crates/noirc_frontend/src/node_interner.rs | 2 + 5 files changed, 86 insertions(+), 41 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 8bb88abd1e9..cc16746daed 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -93,12 +93,12 @@ impl CrateDefMap { .to_str() .expect("expected std path to be convertible to str"); assert_eq!(path_as_str, "std/lib"); - // There are 2 printlns in the stdlib. If we are using the experimental SSA, we want to keep - // only the unconstrained one. Otherwise we want to keep only the constrained one. - ast.functions.retain(|func| { + // There are 2 printlns in the stdlib. If we are using the experimental SSA, we want to keep + // only the unconstrained one. Otherwise we want to keep only the constrained one. + ast.functions.retain(|func| { func.def.name.0.contents.as_str() != "println" || func.def.is_unconstrained == context.def_interner.experimental_ssa - }); + }); if !context.def_interner.experimental_ssa { ast.module_decls.retain(|ident| { diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index f314cd63e44..fed52928c2a 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -760,6 +760,8 @@ impl<'a> Resolver<'a> { | Type::PolymorphicInteger(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) + | Type::MaybeConstant(_, _) + | Type::NotConstant | Type::Forall(_, _) => (), Type::Array(length, _) => { diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 9441307bf28..a9d3a2ffed8 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -21,9 +21,6 @@ pub enum Type { /// is either a type variable of some kind or a Type::Constant. Array(Box, Box), - /// Slice(E) is a slice with elements of type E. - Slice(Box), - /// A primitive integer type with the given sign, bit count, and whether it is known at compile-time. /// E.g. `u32` would be `Integer(CompTime::No(None), Unsigned, 32)` Integer(CompTime, Signedness, u32), @@ -88,6 +85,19 @@ pub enum Type { /// bind to an integer without special checks to bind it to a non-type. Constant(u64), + /// A type variable kind that is potentially bound to a constant. + /// Array literals are initialized with their lengths as MaybeConstant. + /// If they are not used as slices later on, the MaybeConstant size will + /// default to a Constant size. Otherwise they will be bound to either + /// NotConstant or a Constant, forcing the array literal to be used only + /// as a slice or array respectively. + MaybeConstant(TypeVariable, u64), + + /// The type of a slice is an array of size NotConstant. + /// The size of an array literal is resolved to this if it ever uses operations + /// involving slices. + NotConstant, + /// The result of some type error. Remembering type errors as their own type variant lets /// us avoid issuing repeat type errors for the same item. For example, a lambda with /// an invalid type would otherwise issue a new error each time it is called @@ -227,6 +237,14 @@ impl std::fmt::Display for StructType { #[derive(Debug, Eq, PartialOrd, Ord)] pub struct Shared(Rc>); +impl std::ops::Deref for Shared { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.borrow() + } +} + impl std::hash::Hash for Shared { fn hash(&self, state: &mut H) { self.0.borrow().hash(state); @@ -576,14 +594,14 @@ impl Type { | Type::PolymorphicInteger(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) + | Type::NotConstant + | Type::MaybeConstant(_, _) | Type::Forall(_, _) => false, Type::Array(length, elem) => { elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) } - Type::Slice(elem) => elem.contains_numeric_typevar(target_id), - Type::Tuple(fields) => { fields.iter().any(|field| field.contains_numeric_typevar(target_id)) } @@ -621,8 +639,13 @@ impl std::fmt::Display for Type { Type::FieldElement(comp_time) => { write!(f, "{comp_time}Field") } - Type::Array(len, typ) => write!(f, "[{typ}; {len}]"), - Type::Slice(typ) => write!(f, "[{typ}]"), + Type::Array(len, typ) => { + if let Some(length) = len.evaluate_to_u64() { + write!(f, "[{typ}; {length}]") + } else { + write!(f, "[{typ}]") + } + } Type::Integer(comp_time, sign, num_bits) => match sign { Signedness::Signed => write!(f, "{comp_time}i{num_bits}"), Signedness::Unsigned => write!(f, "{comp_time}u{num_bits}"), @@ -671,6 +694,11 @@ impl std::fmt::Display for Type { Type::MutableReference(element) => { write!(f, "&mut {element}") } + Type::MaybeConstant(binding, x) => match &*binding.borrow() { + TypeBinding::Bound(binding) => binding.fmt(f), + TypeBinding::Unbound(_) => write!(f, "{x}"), + }, + Type::NotConstant => todo!(), } } } @@ -933,13 +961,19 @@ impl Type { other.try_bind_to(binding) } + (MaybeConstant(binding, _), other) | (other, MaybeConstant(binding, _)) => { + if let TypeBinding::Bound(link) = &*binding.borrow() { + return link.try_unify(other, span); + } + + other.try_bind_to(binding) + } + (Array(len_a, elem_a), Array(len_b, elem_b)) => { len_a.try_unify(len_b, span)?; elem_a.try_unify(elem_b, span) } - (Slice(elem_a), Slice(elem_b)) => elem_a.try_unify(elem_b, span), - (Tuple(elements_a), Tuple(elements_b)) => { if elements_a.len() != elements_b.len() { Err(SpanKind::None) @@ -1073,10 +1107,6 @@ impl Type { elem_a.is_subtype_of(elem_b, span) } - (Slice(elem_a), Slice(elem_b)) => elem_a.is_subtype_of(elem_b, span), - - (Array(_, elem_a), Slice(elem_b)) => elem_a.is_subtype_of(elem_b, span), - (Tuple(elements_a), Tuple(elements_b)) => { if elements_a.len() != elements_b.len() { Err(SpanKind::None) @@ -1176,6 +1206,10 @@ impl Type { TypeBinding::Bound(binding) => binding.evaluate_to_u64(), TypeBinding::Unbound(_) => None, }, + Type::MaybeConstant(binding, size) => match &*binding.borrow() { + TypeBinding::Bound(binding) => binding.evaluate_to_u64(), + TypeBinding::Unbound(_) => Some(*size), + }, Type::Array(len, _elem) => len.evaluate_to_u64(), Type::Constant(x) => Some(*x), _ => None, @@ -1226,8 +1260,9 @@ impl Type { Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), Type::Function(_, _) => unreachable!(), - Type::Slice(_) => unreachable!("slices cannot be used in the abi"), Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), + Type::MaybeConstant(_, _) => unreachable!(), + Type::NotConstant => unreachable!(), } } @@ -1309,16 +1344,13 @@ impl Type { let element = Box::new(element.substitute(type_bindings)); Type::Array(size, element) } - Type::Slice(element) => { - let element = Box::new(element.substitute(type_bindings)); - Type::Slice(element) - } Type::String(size) => { let size = Box::new(size.substitute(type_bindings)); Type::String(size) } Type::PolymorphicInteger(_, binding) | Type::NamedGeneric(binding, _) + | Type::MaybeConstant(binding, _) | Type::TypeVariable(binding) => substitute_binding(binding), // Do not substitute fields, it can lead to infinite recursion @@ -1354,6 +1386,7 @@ impl Type { | Type::Bool(_) | Type::Constant(_) | Type::Error + | Type::NotConstant | Type::Unit => self.clone(), } } @@ -1362,12 +1395,12 @@ impl Type { fn occurs(&self, target_id: TypeVariableId) -> bool { match self { Type::Array(len, elem) => len.occurs(target_id) || elem.occurs(target_id), - Type::Slice(element) => element.occurs(target_id), Type::String(len) => len.occurs(target_id), Type::Struct(_, generic_args) => generic_args.iter().any(|arg| arg.occurs(target_id)), Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), Type::PolymorphicInteger(_, binding) | Type::NamedGeneric(binding, _) + | Type::MaybeConstant(binding, _) | Type::TypeVariable(binding) => match &*binding.borrow() { TypeBinding::Bound(binding) => binding.occurs(target_id), TypeBinding::Unbound(id) => *id == target_id, @@ -1385,6 +1418,7 @@ impl Type { | Type::Bool(_) | Type::Constant(_) | Type::Error + | Type::NotConstant | Type::Unit => false, } } @@ -1401,7 +1435,6 @@ impl Type { Array(size, elem) => { Array(Box::new(size.follow_bindings()), Box::new(elem.follow_bindings())) } - Slice(elem) => Slice(Box::new(elem.follow_bindings())), String(size) => String(Box::new(size.follow_bindings())), Struct(def, args) => { let args = vecmap(args, |arg| arg.follow_bindings()); @@ -1409,7 +1442,10 @@ impl Type { } Tuple(args) => Tuple(vecmap(args, |arg| arg.follow_bindings())), - TypeVariable(var) | PolymorphicInteger(_, var) | NamedGeneric(var, _) => { + TypeVariable(var) + | PolymorphicInteger(_, var) + | MaybeConstant(var, _) + | NamedGeneric(var, _) => { if let TypeBinding::Bound(typ) = &*var.borrow() { return typ.follow_bindings(); } @@ -1426,9 +1462,13 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement(_) | Integer(_, _, _) | Bool(_) | Constant(_) | Unit | Error => { - self.clone() - } + FieldElement(_) + | Integer(_, _, _) + | Bool(_) + | Constant(_) + | Unit + | Error + | NotConstant => self.clone(), } } } diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index a3188eaa14a..1ae4ff19e39 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -678,17 +678,16 @@ impl<'interner> Monomorphizer<'interner> { HirType::Unit => ast::Type::Unit, HirType::Array(length, element) => { - let length = length.evaluate_to_u64().unwrap_or(0); - let element = self.convert_type(element.as_ref()); - if self.interner.experimental_ssa { - return ast::Type::Array(length, Box::new(element)); - } - self.aos_to_soa_type(length, element) - } + let element = Box::new(self.convert_type(element.as_ref())); - HirType::Slice(element) => { - let element = self.convert_type(element.as_ref()); - ast::Type::Slice(Box::new(element)) + if let Some(length) = length.evaluate_to_u64() { + if self.interner.experimental_ssa { + return ast::Type::Array(length, element); + } + self.aos_to_soa_type(length, *element) + } else { + ast::Type::Slice(element) + } } HirType::PolymorphicInteger(_, binding) @@ -732,7 +731,10 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::MutableReference(Box::new(element)) } - HirType::Forall(_, _) | HirType::Constant(_) | HirType::Error => { + HirType::Forall(_, _) + | HirType::Constant(_) + | HirType::NotConstant + | HirType::Error => { unreachable!("Unexpected type {} found", typ) } } @@ -778,7 +780,7 @@ impl<'interner> Monomorphizer<'interner> { if let Definition::Oracle(name) = &ident.definition { if name.as_str() == "println" { // Oracle calls are required to be wrapped in an unconstrained function - // Thus, the only argument to the `println` oracle is expected to always be an ident + // Thus, the only argument to the `println` oracle is expected to always be an ident self.append_abi_arg(&hir_arguments[0], &mut arguments); } } @@ -1147,7 +1149,6 @@ fn unwrap_struct_type(typ: &HirType) -> Vec<(String, HirType)> { fn unwrap_array_element_type(typ: &HirType) -> HirType { match typ { HirType::Array(_, elem) => *elem.clone(), - HirType::Slice(elem) => *elem.clone(), HirType::TypeVariable(binding) => match &*binding.borrow() { TypeBinding::Bound(binding) => unwrap_array_element_type(binding), TypeBinding::Unbound(_) => unreachable!(), diff --git a/crates/noirc_frontend/src/node_interner.rs b/crates/noirc_frontend/src/node_interner.rs index 69b313fd538..517113f365a 100644 --- a/crates/noirc_frontend/src/node_interner.rs +++ b/crates/noirc_frontend/src/node_interner.rs @@ -644,6 +644,8 @@ fn get_type_method_key(typ: &Type) -> Option { | Type::Forall(_, _) | Type::Constant(_) | Type::Error + | Type::MaybeConstant(_, _) + | Type::NotConstant | Type::Struct(_, _) => None, } } From 79440f20faf0e1d22b97e93a91b5772ccb11e178 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Fri, 21 Jul 2023 12:07:20 -0500 Subject: [PATCH 02/19] Finish merger of slices and arrays --- .../src/hir/resolution/resolver.rs | 15 ++-- .../noirc_frontend/src/hir/type_check/expr.rs | 14 +++- .../noirc_frontend/src/hir/type_check/stmt.rs | 1 - crates/noirc_frontend/src/hir_def/types.rs | 29 +++++--- .../src/monomorphization/mod.rs | 1 + crates/noirc_frontend/src/node_interner.rs | 2 - noir_stdlib/src/hash/poseidon.nr | 2 +- noir_stdlib/src/slice.nr | 69 ------------------- 8 files changed, 38 insertions(+), 95 deletions(-) diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index fed52928c2a..2388ff718c6 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -329,11 +329,12 @@ impl<'a> Resolver<'a> { UnresolvedType::FieldElement(comp_time) => Type::FieldElement(comp_time), UnresolvedType::Array(size, elem) => { let elem = Box::new(self.resolve_type_inner(*elem, new_variables)); - if self.interner.experimental_ssa && size.is_none() { - return Type::Slice(elem); - } - let resolved_size = self.resolve_array_size(size, new_variables); - Type::Array(Box::new(resolved_size), elem) + let size = if self.interner.experimental_ssa && size.is_none() { + Type::NotConstant + } else { + self.resolve_array_size(size, new_variables) + }; + Type::Array(Box::new(size), elem) } UnresolvedType::Expression(expr) => self.convert_expression_type(expr), UnresolvedType::Integer(comp_time, sign, bits) => Type::Integer(comp_time, sign, bits), @@ -770,10 +771,6 @@ impl<'a> Resolver<'a> { } } - Type::Slice(typ) => { - Self::find_numeric_generics_in_type(typ, found); - } - Type::Tuple(fields) => { for field in fields { Self::find_numeric_generics_in_type(field, found); diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index 1625c8a320f..37517e84187 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -47,8 +47,11 @@ impl<'interner> TypeChecker<'interner> { .cloned() .unwrap_or_else(|| self.interner.next_type_variable()); + let typevar_id = self.interner.next_type_variable_id(); + let typevar = Shared::new(TypeBinding::Unbound(typevar_id)); + let arr_type = Type::Array( - Box::new(Type::Constant(arr.len() as u64)), + Box::new(Type::MaybeConstant(typevar, arr.len() as u64)), Box::new(first_elem_type.clone()), ); @@ -78,6 +81,14 @@ impl<'interner> TypeChecker<'interner> { } HirLiteral::Array(HirArrayLiteral::Repeated { repeated_element, length }) => { let elem_type = self.check_expression(&repeated_element); + let length = match length { + Type::Constant(length) => { + let typevar_id = self.interner.next_type_variable_id(); + let typevar = Shared::new(TypeBinding::Unbound(typevar_id)); + Type::MaybeConstant(typevar, length) + }, + other => other, + }; Type::Array(Box::new(length), Box::new(elem_type)) } HirLiteral::Bool(_) => Type::Bool(CompTime::new(self.interner)), @@ -325,7 +336,6 @@ impl<'interner> TypeChecker<'interner> { // XXX: We can check the array bounds here also, but it may be better to constant fold first // and have ConstId instead of ExprId for constants Type::Array(_, base_type) => *base_type, - Type::Slice(base_type) => *base_type, Type::Error => Type::Error, typ => { let span = self.interner.expr_span(&index_expr.collection); diff --git a/crates/noirc_frontend/src/hir/type_check/stmt.rs b/crates/noirc_frontend/src/hir/type_check/stmt.rs index 4354d4cc77b..d8971f28631 100644 --- a/crates/noirc_frontend/src/hir/type_check/stmt.rs +++ b/crates/noirc_frontend/src/hir/type_check/stmt.rs @@ -194,7 +194,6 @@ impl<'interner> TypeChecker<'interner> { let typ = match result { Type::Array(_, elem_type) => *elem_type, - Type::Slice(elem_type) => *elem_type, Type::Error => Type::Error, other => { // TODO: Need a better span here diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index a9d3a2ffed8..8e62f1831d2 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -237,14 +237,6 @@ impl std::fmt::Display for StructType { #[derive(Debug, Eq, PartialOrd, Ord)] pub struct Shared(Rc>); -impl std::ops::Deref for Shared { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.borrow() - } -} - impl std::hash::Hash for Shared { fn hash(&self, state: &mut H) { self.0.borrow().hash(state); @@ -640,10 +632,10 @@ impl std::fmt::Display for Type { write!(f, "{comp_time}Field") } Type::Array(len, typ) => { - if let Some(length) = len.evaluate_to_u64() { - write!(f, "[{typ}; {length}]") - } else { + if matches!(len.follow_bindings(), Type::NotConstant) { write!(f, "[{typ}]") + } else { + write!(f, "[{typ}; {len}]") } } Type::Integer(comp_time, sign, num_bits) => match sign { @@ -1102,6 +1094,21 @@ impl Type { other.try_bind_to(binding) } + (MaybeConstant(binding, _), other) => { + if let TypeBinding::Bound(link) = &*binding.borrow() { + return link.is_subtype_of(other, span); + } + + other.try_bind_to(binding) + } + (other, MaybeConstant(binding, _)) => { + if let TypeBinding::Bound(link) = &*binding.borrow() { + return other.is_subtype_of(link, span); + } + + other.try_bind_to(binding) + } + (Array(len_a, elem_a), Array(len_b, elem_b)) => { len_a.is_subtype_of(len_b, span)?; elem_a.is_subtype_of(elem_b, span) diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 1ae4ff19e39..d445c285d61 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -733,6 +733,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::Forall(_, _) | HirType::Constant(_) + | HirType::MaybeConstant(..) | HirType::NotConstant | HirType::Error => { unreachable!("Unexpected type {} found", typ) diff --git a/crates/noirc_frontend/src/node_interner.rs b/crates/noirc_frontend/src/node_interner.rs index 517113f365a..868d55eff56 100644 --- a/crates/noirc_frontend/src/node_interner.rs +++ b/crates/noirc_frontend/src/node_interner.rs @@ -614,7 +614,6 @@ enum TypeMethodKey { /// accept only fields or integers, it is just that their names may not clash. FieldOrInt, Array, - Slice, Bool, String, Unit, @@ -628,7 +627,6 @@ fn get_type_method_key(typ: &Type) -> Option { match &typ { Type::FieldElement(_) => Some(FieldOrInt), Type::Array(_, _) => Some(Array), - Type::Slice(_) => Some(Slice), Type::Integer(_, _, _) => Some(FieldOrInt), Type::PolymorphicInteger(_, _) => Some(FieldOrInt), Type::Bool(_) => Some(Bool), diff --git a/noir_stdlib/src/hash/poseidon.nr b/noir_stdlib/src/hash/poseidon.nr index 416f740bbdf..cb1e34927b4 100644 --- a/noir_stdlib/src/hash/poseidon.nr +++ b/noir_stdlib/src/hash/poseidon.nr @@ -101,7 +101,7 @@ fn check_security(rate: Field, width: Field, security: Field) -> bool { } // A*x where A is an n x n matrix in row-major order and x an n-vector -fn apply_matrix(a: [Field], x: [Field; N]) -> [Field; N] { +fn apply_matrix(a: [Field; M], x: [Field; N]) -> [Field; N] { let mut y = x; for i in 0..x.len() { diff --git a/noir_stdlib/src/slice.nr b/noir_stdlib/src/slice.nr index 186d535a264..8e344a40f5e 100644 --- a/noir_stdlib/src/slice.nr +++ b/noir_stdlib/src/slice.nr @@ -32,74 +32,5 @@ impl [T] { /// the removed element #[builtin(slice_remove)] fn remove(_self: Self, _index: Field) -> (Self, T) { } - - #[builtin(array_len)] - fn len(_self: Self) -> comptime Field {} - - #[builtin(arraysort)] - fn sort(_self: Self) -> Self {} - - // Sort with a custom sorting function. - fn sort_via(mut a: Self, ordering: fn(T, T) -> bool) -> Self { - for i in 1 .. a.len() { - for j in 0..i { - if ordering(a[i], a[j]) { - let old_a_j = a[j]; - a[j] = a[i]; - a[i] = old_a_j; - } - } - } - a - } - - // Apply a function to each element of a slice, returning a new slice - // containing the mapped elements. - fn map(self, f: fn(T) -> U) -> [U] { - let mut ret: [U] = []; - for elem in self { - ret = ret.push_back(f(elem)); - } - ret - } - - // Apply a function to each element of the slice and an accumulator value, - // returning the final accumulated value. This function is also sometimes - // called `foldl`, `fold_left`, `reduce`, or `inject`. - fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U { - for elem in self { - accumulator = f(accumulator, elem); - } - accumulator - } - - // Apply a function to each element of the slice and an accumulator value, - // returning the final accumulated value. Unlike fold, reduce uses the first - // element of the given slice as its starting accumulator value. - fn reduce(self, f: fn(T, T) -> T) -> T { - let mut accumulator = self[0]; - for i in 1 .. self.len() { - accumulator = f(accumulator, self[i]); - } - accumulator - } - - // Returns true if all elements in the array satisfy the predicate - fn all(self, predicate: fn(T) -> bool) -> bool { - let mut ret = true; - for elem in self { - ret &= predicate(elem); - } - ret - } - - // Returns true if any element in the array satisfies the predicate - fn any(self, predicate: fn(T) -> bool) -> bool { - let mut ret = false; - for elem in self { - ret |= predicate(elem); - } - ret - } } From 22f2ed3179eebf545c98aa3a7043fcc5acc2c1f3 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Fri, 21 Jul 2023 12:52:43 -0500 Subject: [PATCH 03/19] Implement missing try_bind function --- .../tests/test_data/array_len/src/main.nr | 6 +- crates/noirc_frontend/src/hir_def/types.rs | 62 +++++++++++++++++-- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/crates/nargo_cli/tests/test_data/array_len/src/main.nr b/crates/nargo_cli/tests/test_data/array_len/src/main.nr index 9099cfa2144..2c3cc0aee60 100644 --- a/crates/nargo_cli/tests/test_data/array_len/src/main.nr +++ b/crates/nargo_cli/tests/test_data/array_len/src/main.nr @@ -1,14 +1,14 @@ use dep::std; -fn len_plus_1(array: [T]) -> Field { +fn len_plus_1(array: [T; N]) -> Field { array.len() + 1 } -fn add_lens(a: [T], b: [Field]) -> Field { +fn add_lens(a: [T; N], b: [Field; M]) -> Field { a.len() + b.len() } -fn nested_call(b: [Field]) -> Field { +fn nested_call(b: [Field; N]) -> Field { len_plus_1(b) } diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 8e62f1831d2..0a98ce2dc14 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -769,6 +769,56 @@ impl Type { } } + /// Try to bind a MaybeConstant variable to self, succeeding if self is a Constant, + /// MaybeConstant, or type variable. + pub fn try_bind_to_maybe_constant( + &self, + var: &TypeVariable, + target_length: u64, + ) -> Result<(), SpanKind> { + let target_id = match &*var.borrow() { + TypeBinding::Bound(_) => unreachable!(), + TypeBinding::Unbound(id) => *id, + }; + + match self { + Type::Constant(length) if *length == target_length => { + *var.borrow_mut() = TypeBinding::Bound(self.clone()); + Ok(()) + } + Type::MaybeConstant(binding, length) if *length == target_length => { + let borrow = binding.borrow(); + match &*borrow { + TypeBinding::Bound(typ) => typ.try_bind_to_maybe_constant(var, target_length), + // Avoid infinitely recursive bindings + TypeBinding::Unbound(id) if *id == target_id => Ok(()), + TypeBinding::Unbound(_) => { + drop(borrow); + *var.borrow_mut() = TypeBinding::Bound(self.clone()); + Ok(()) + } + } + } + Type::TypeVariable(binding) => { + let borrow = binding.borrow(); + match &*borrow { + TypeBinding::Bound(typ) => typ.try_bind_to_maybe_constant(var, target_length), + // Avoid infinitely recursive bindings + TypeBinding::Unbound(id) if *id == target_id => Ok(()), + TypeBinding::Unbound(_) => { + drop(borrow); + // MaybeConstant is more specific than TypeVariable so we bind the type + // variable to PolymorphicInt instead. + let clone = Type::MaybeConstant(var.clone(), target_length); + *binding.borrow_mut() = TypeBinding::Bound(clone); + Ok(()) + } + } + } + _ => Err(SpanKind::None), + } + } + /// Try to bind a PolymorphicInt variable to self, succeeding if self is an integer, field, /// other PolymorphicInt type, or type variable. If use_subtype is true, the CompTime fields /// of each will be checked via sub-typing rather than unification. @@ -953,12 +1003,12 @@ impl Type { other.try_bind_to(binding) } - (MaybeConstant(binding, _), other) | (other, MaybeConstant(binding, _)) => { + (MaybeConstant(binding, length), other) | (other, MaybeConstant(binding, length)) => { if let TypeBinding::Bound(link) = &*binding.borrow() { return link.try_unify(other, span); } - other.try_bind_to(binding) + other.try_bind_to_maybe_constant(binding, *length) } (Array(len_a, elem_a), Array(len_b, elem_b)) => { @@ -1094,19 +1144,19 @@ impl Type { other.try_bind_to(binding) } - (MaybeConstant(binding, _), other) => { + (MaybeConstant(binding, length), other) => { if let TypeBinding::Bound(link) = &*binding.borrow() { return link.is_subtype_of(other, span); } - other.try_bind_to(binding) + other.try_bind_to_maybe_constant(binding, *length) } - (other, MaybeConstant(binding, _)) => { + (other, MaybeConstant(binding, length)) => { if let TypeBinding::Bound(link) = &*binding.borrow() { return other.is_subtype_of(link, span); } - other.try_bind_to(binding) + other.try_bind_to_maybe_constant(binding, *length) } (Array(len_a, elem_a), Array(len_b, elem_b)) => { From c550dbb819ff8ccf9761d30449007152b0021f67 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 27 Jul 2023 11:26:49 -0500 Subject: [PATCH 04/19] Add missed case for NotConstant --- .../noirc_frontend/src/hir/type_check/expr.rs | 2 +- crates/noirc_frontend/src/hir_def/types.rs | 4 +++ .../src/monomorphization/mod.rs | 25 ++++++------------- noir_stdlib/src/array.nr | 9 +++++++ 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index 2ad183e36c6..bfdca0f406b 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -86,7 +86,7 @@ impl<'interner> TypeChecker<'interner> { let typevar_id = self.interner.next_type_variable_id(); let typevar = Shared::new(TypeBinding::Unbound(typevar_id)); Type::MaybeConstant(typevar, length) - }, + } other => other, }; Type::Array(Box::new(length), Box::new(elem_type)) diff --git a/crates/noirc_frontend/src/hir_def/types.rs b/crates/noirc_frontend/src/hir_def/types.rs index 785d7f234be..e109308b20b 100644 --- a/crates/noirc_frontend/src/hir_def/types.rs +++ b/crates/noirc_frontend/src/hir_def/types.rs @@ -800,6 +800,10 @@ impl Type { *var.borrow_mut() = TypeBinding::Bound(self.clone()); Ok(()) } + Type::NotConstant => { + *var.borrow_mut() = TypeBinding::Bound(Type::NotConstant); + Ok(()) + } Type::MaybeConstant(binding, length) if *length == target_length => { let borrow = binding.borrow(); match &*borrow { diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 3b370a31fe2..e72359ef7e2 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -22,7 +22,7 @@ use crate::{ }, node_interner::{self, DefinitionKind, NodeInterner, StmtId}, token::Attribute, - CompTime, ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, + CompTime, ContractFunctionType, FunctionKind, TypeBinding, TypeBindings, }; use self::ast::{Definition, FuncId, Function, LocalId, Program}; @@ -589,7 +589,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::Unit => ast::Type::Unit, HirType::Array(length, element) => { - let element = Box::new(self.convert_type(element.as_ref())); + let element = Box::new(Self::convert_type(element.as_ref())); if let Some(length) = length.evaluate_to_u64() { ast::Type::Array(length, element) @@ -671,8 +671,12 @@ impl<'interner> Monomorphizer<'interner> { } } - self.try_evaluate_call(&func, &call.arguments, &return_type) - .unwrap_or(ast::Expression::Call(ast::Call { func, arguments, return_type, location })) + self.try_evaluate_call(&func, &return_type).unwrap_or(ast::Expression::Call(ast::Call { + func, + arguments, + return_type, + location, + })) } /// Adds a function argument that contains type metadata that is required to tell @@ -711,25 +715,12 @@ impl<'interner> Monomorphizer<'interner> { fn try_evaluate_call( &mut self, func: &ast::Expression, - arguments: &[node_interner::ExprId], result_type: &ast::Type, ) -> Option { if let ast::Expression::Ident(ident) = func { if let Definition::Builtin(opcode) = &ident.definition { // TODO(#1736): Move this builtin to the SSA pass return match opcode.as_str() { - "array_len" => { - let typ = self.interner.id_type(arguments[0]); - if let Type::Array(_, _) = typ { - let len = typ.evaluate_to_u64().unwrap(); - Some(ast::Expression::Literal(ast::Literal::Integer( - (len as u128).into(), - ast::Type::Field, - ))) - } else { - None - } - } "modulus_num_bits" => Some(ast::Expression::Literal(ast::Literal::Integer( (FieldElement::max_num_bits() as u128).into(), ast::Type::Field, diff --git a/noir_stdlib/src/array.nr b/noir_stdlib/src/array.nr index 9e44aa03fcc..db349317f91 100644 --- a/noir_stdlib/src/array.nr +++ b/noir_stdlib/src/array.nr @@ -22,6 +22,15 @@ impl [T; N] { a } + // Converts an array into a slice. + fn as_slice(self) -> [T] { + let mut slice = []; + for elem in self { + slice = slice.push_back(elem); + } + slice + } + // Apply a function to each element of an array, returning a new array // containing the mapped elements. fn map(self, f: fn(T) -> U) -> [U; N] { From d06b69c27ae505dfa5f5e42a129c7d1bd472f7f7 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 27 Jul 2023 11:45:55 -0500 Subject: [PATCH 05/19] Fix some tests --- .../tests/test_data_ssa_refactor/array_len/src/main.nr | 6 +++--- noir_stdlib/src/ecdsa_secp256k1.nr | 2 +- noir_stdlib/src/ecdsa_secp256r1.nr | 2 +- noir_stdlib/src/merkle.nr | 4 ++-- noir_stdlib/src/schnorr.nr | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/array_len/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/array_len/src/main.nr index 9099cfa2144..2c3cc0aee60 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/array_len/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/array_len/src/main.nr @@ -1,14 +1,14 @@ use dep::std; -fn len_plus_1(array: [T]) -> Field { +fn len_plus_1(array: [T; N]) -> Field { array.len() + 1 } -fn add_lens(a: [T], b: [Field]) -> Field { +fn add_lens(a: [T; N], b: [Field; M]) -> Field { a.len() + b.len() } -fn nested_call(b: [Field]) -> Field { +fn nested_call(b: [Field; N]) -> Field { len_plus_1(b) } diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index efeceef5df2..c46380e1988 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,2 +1,2 @@ #[foreign(ecdsa_secp256k1)] -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message_hash: [u8]) -> bool {} +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message_hash: [u8; N]) -> bool {} diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index 44df07d3590..77744384f52 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,2 +1,2 @@ #[foreign(ecdsa_secp256r1)] -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message_hash: [u8]) -> bool {} +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message_hash: [u8; N]) -> bool {} diff --git a/noir_stdlib/src/merkle.nr b/noir_stdlib/src/merkle.nr index 1f1a45ffe17..07588a52a5a 100644 --- a/noir_stdlib/src/merkle.nr +++ b/noir_stdlib/src/merkle.nr @@ -3,7 +3,7 @@ // XXX: In the future we can add an arity parameter // Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function. -fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field]) -> Field { +fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field { let n = hash_path.len(); let index_bits = index.to_le_bits(n as u32); let mut current = leaf; @@ -18,4 +18,4 @@ fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field]) -> Field { current = crate::hash::pedersen([hash_left, hash_right])[0]; }; current -} \ No newline at end of file +} diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 5000efd3be4..1e69bcec821 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -1,2 +1,2 @@ #[foreign(schnorr_verify)] -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool {} +fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8; N]) -> bool {} From eb3356170c4b2ec327e3040ebdd6230b906a36c9 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 27 Jul 2023 13:13:42 -0500 Subject: [PATCH 06/19] Fix poseidon test --- crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs | 11 +++-------- .../src/ssa_refactor/ir/instruction.rs | 12 +++--------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs index 5c9fde280a8..4cb95994546 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs @@ -382,14 +382,9 @@ impl DataFlowGraph { /// Returns the Type::Array associated with this ValueId if it refers to an array parameter. /// Otherwise, this returns None. - pub(crate) fn get_array_parameter_type( - &self, - value: ValueId, - ) -> Option<(Rc, usize)> { - match &self.values[self.resolve(value)] { - Value::Param { typ: Type::Array(element_type, size), .. } => { - Some((element_type.clone(), *size)) - } + pub(crate) fn try_get_array_length(&self, value: ValueId) -> Option { + match self.type_of_value(value) { + Type::Array(_, length) => Some(length), _ => None, } } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs index 416c53ba6b4..cec7408ebcd 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs @@ -420,15 +420,9 @@ fn simplify_call(func: ValueId, arguments: &[ValueId], dfg: &mut DataFlowGraph) Intrinsic::ArrayLen => { let slice = dfg.get_array_constant(arguments[0]); if let Some((slice, _)) = slice { - let slice_len = - dfg.make_constant(FieldElement::from(slice.len() as u128), Type::field()); - SimplifiedTo(slice_len) - } else if let Some((_, slice_len)) = dfg.get_array_parameter_type(arguments[0]) { - let slice_len = dfg.make_constant( - FieldElement::from(slice_len as u128), - Type::Numeric(NumericType::NativeField), - ); - SimplifiedTo(slice_len) + SimplifiedTo(dfg.make_constant((slice.len() as u128).into(), Type::field())) + } else if let Some(length) = dfg.try_get_array_length(arguments[0]) { + SimplifiedTo(dfg.make_constant((length as u128).into(), Type::field())) } else { None } From 3e366d8406d5fe27487d3f3df7ab52eedc3744d3 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 27 Jul 2023 14:58:36 -0500 Subject: [PATCH 07/19] Fix evaluation of slice length --- .../test_data_ssa_refactor/slices/src/main.nr | 4 +- .../src/ssa_refactor/ir/dfg.rs | 20 +++----- .../src/ssa_refactor/ir/function_inserter.rs | 6 +-- .../src/ssa_refactor/ir/instruction.rs | 6 ++- .../src/ssa_refactor/ir/value.rs | 10 ++-- .../src/ssa_refactor/opt/flatten_cfg.rs | 32 ++++++------- .../src/ssa_refactor/opt/inlining.rs | 4 +- .../src/ssa_refactor/ssa_builder/mod.rs | 11 ++--- .../src/ssa_refactor/ssa_gen/mod.rs | 20 +++----- .../src/monomorphization/ast.rs | 2 +- .../src/monomorphization/mod.rs | 48 +++++++------------ 11 files changed, 65 insertions(+), 98 deletions(-) diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr index a0460aafb40..f97078a2143 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr @@ -4,7 +4,7 @@ fn main(x : Field, y : pub Field) { /// TODO(#1889): Using slices in if statements where the condition is a witness /// is not yet supported - let mut slice: [Field] = [0; 2]; + let mut slice = [0; 2]; assert(slice[0] == 0); assert(slice[0] != 1); slice[0] = x; @@ -15,7 +15,7 @@ fn main(x : Field, y : pub Field) { assert(slice_plus_10[2] != 8); assert(slice_plus_10.len() == 3); - let mut new_slice: [Field] = []; + let mut new_slice = []; for i in 0..5 { new_slice = new_slice.push_back(i); } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs index 4cb95994546..b24af65723a 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap, rc::Rc}; +use std::{borrow::Cow, collections::HashMap}; use crate::ssa_refactor::ir::instruction::SimplifyResult; @@ -9,7 +9,7 @@ use super::{ Instruction, InstructionId, InstructionResultType, Intrinsic, TerminatorInstruction, }, map::DenseMap, - types::{CompositeType, Type}, + types::Type, value::{Value, ValueId}, }; @@ -226,12 +226,9 @@ impl DataFlowGraph { } /// Create a new constant array value from the given elements - pub(crate) fn make_array( - &mut self, - array: im::Vector, - element_type: Rc, - ) -> ValueId { - self.make_value(Value::Array { array, element_type }) + pub(crate) fn make_array(&mut self, array: im::Vector, typ: Type) -> ValueId { + assert!(matches!(typ, Type::Array(..) | Type::Slice(_))); + self.make_value(Value::Array { array, typ }) } /// Gets or creates a ValueId for the given FunctionId. @@ -369,13 +366,10 @@ impl DataFlowGraph { /// Returns the Value::Array associated with this ValueId if it refers to an array constant. /// Otherwise, this returns None. - pub(crate) fn get_array_constant( - &self, - value: ValueId, - ) -> Option<(im::Vector, Rc)> { + pub(crate) fn get_array_constant(&self, value: ValueId) -> Option<(im::Vector, Type)> { match &self.values[self.resolve(value)] { // Vectors are shared, so cloning them is cheap - Value::Array { array, element_type } => Some((array.clone(), element_type.clone())), + Value::Array { array, typ } => Some((array.clone(), typ.clone())), _ => None, } } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/function_inserter.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/function_inserter.rs index 22a1399ae79..38dcfbbb168 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/function_inserter.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/function_inserter.rs @@ -33,11 +33,11 @@ impl<'f> FunctionInserter<'f> { match self.values.get(&value) { Some(value) => *value, None => match &self.function.dfg[value] { - super::value::Value::Array { array, element_type } => { + super::value::Value::Array { array, typ } => { let array = array.clone(); - let element_type = element_type.clone(); + let typ = typ.clone(); let new_array = array.iter().map(|id| self.resolve(*id)).collect(); - let new_id = self.function.dfg.make_array(new_array, element_type); + let new_id = self.function.dfg.make_array(new_array, typ); self.values.insert(value, new_id); new_id } diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs index cec7408ebcd..b7a3ea02ae9 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs @@ -528,9 +528,11 @@ fn constant_to_radix( while limbs.len() < limb_count_with_padding as usize { limbs.push(FieldElement::zero()); } - let result_constants = + let result_constants: im::Vector = limbs.into_iter().map(|limb| dfg.make_constant(limb, Type::unsigned(bit_size))).collect(); - dfg.make_array(result_constants, Rc::new(vec![Type::unsigned(bit_size)])) + + let typ = Type::Array(Rc::new(vec![Type::unsigned(bit_size)]), result_constants.len()); + dfg.make_array(result_constants, typ) } /// The possible return values for Instruction::return_types diff --git a/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs b/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs index 03475f5f514..cea526058b4 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ir/value.rs @@ -1,5 +1,3 @@ -use std::rc::Rc; - use acvm::FieldElement; use crate::ssa_refactor::ir::basic_block::BasicBlockId; @@ -8,7 +6,7 @@ use super::{ function::FunctionId, instruction::{InstructionId, Intrinsic}, map::Id, - types::{CompositeType, Type}, + types::Type, }; pub(crate) type ValueId = Id; @@ -38,7 +36,7 @@ pub(crate) enum Value { NumericConstant { constant: FieldElement, typ: Type }, /// Represents a constant array value - Array { array: im::Vector, element_type: Rc }, + Array { array: im::Vector, typ: Type }, /// This Value refers to a function in the IR. /// Functions always have the type Type::Function. @@ -64,9 +62,7 @@ impl Value { Value::Instruction { typ, .. } => typ.clone(), Value::Param { typ, .. } => typ.clone(), Value::NumericConstant { typ, .. } => typ.clone(), - Value::Array { element_type, array } => { - Type::Array(element_type.clone(), array.len() / element_type.len()) - } + Value::Array { typ, .. } => typ.clone(), Value::Function { .. } => Type::Function, Value::Intrinsic { .. } => Type::Function, Value::ForeignFunction { .. } => Type::Function, diff --git a/crates/noirc_evaluator/src/ssa_refactor/opt/flatten_cfg.rs b/crates/noirc_evaluator/src/ssa_refactor/opt/flatten_cfg.rs index ac62071d6ee..4ff857f942f 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/opt/flatten_cfg.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/opt/flatten_cfg.rs @@ -131,10 +131,7 @@ //! v11 = mul v4, Field 12 //! v12 = add v10, v11 //! store v12 at v5 (new store) -use std::{ - collections::{BTreeMap, HashMap, HashSet}, - rc::Rc, -}; +use std::collections::{BTreeMap, HashMap, HashSet}; use acvm::FieldElement; use iter_extended::vecmap; @@ -148,7 +145,7 @@ use crate::ssa_refactor::{ function::Function, function_inserter::FunctionInserter, instruction::{BinaryOp, Instruction, InstructionId, TerminatorInstruction}, - types::{CompositeType, Type}, + types::Type, value::ValueId, }, ssa_gen::Ssa, @@ -393,14 +390,9 @@ impl<'f> Context<'f> { Type::Numeric(_) => { self.merge_numeric_values(then_condition, else_condition, then_value, else_value) } - Type::Array(element_types, len) => self.merge_array_values( - element_types, - len, - then_condition, - else_condition, - then_value, - else_value, - ), + typ @ Type::Array(_, _) => { + self.merge_array_values(typ, then_condition, else_condition, then_value, else_value) + } // TODO(#1889) Type::Slice(_) => panic!("Cannot return slices from an if expression"), Type::Reference => panic!("Cannot return references from an if expression"), @@ -413,8 +405,7 @@ impl<'f> Context<'f> { /// by creating a new array containing the result of self.merge_values for each element. fn merge_array_values( &mut self, - element_types: Rc, - len: usize, + typ: Type, then_condition: ValueId, else_condition: ValueId, then_value: ValueId, @@ -422,6 +413,11 @@ impl<'f> Context<'f> { ) -> ValueId { let mut merged = im::Vector::new(); + let (element_types, len) = match &typ { + Type::Array(elements, len) => (elements, *len), + _ => panic!("Expected array type"), + }; + for i in 0..len { for (element_index, element_type) in element_types.iter().enumerate() { let index = ((i * element_types.len() + element_index) as u128).into(); @@ -446,7 +442,7 @@ impl<'f> Context<'f> { } } - self.inserter.function.dfg.make_array(merged, element_types) + self.inserter.function.dfg.make_array(merged, typ) } /// Merge two numeric values a and b from separate basic blocks to a single value. This @@ -1333,8 +1329,10 @@ mod test { let b3 = builder.insert_block(); let element_type = Rc::new(vec![Type::field()]); + let array_type = Type::Array(element_type.clone(), 1); + let zero = builder.field_constant(0_u128); - let zero_array = builder.array_constant(im::Vector::unit(zero), element_type.clone()); + let zero_array = builder.array_constant(im::Vector::unit(zero), array_type); let i_zero = builder.numeric_constant(0_u128, Type::unsigned(32)); let pedersen = builder.import_intrinsic_id(Intrinsic::BlackBox(acvm::acir::BlackBoxFunc::Pedersen)); diff --git a/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs b/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs index 430b52ce9f6..7aa2f9d176a 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs @@ -217,9 +217,9 @@ impl<'function> PerFunctionContext<'function> { Value::ForeignFunction(function) => { self.context.builder.import_foreign_function(function) } - Value::Array { array, element_type } => { + Value::Array { array, typ } => { let elements = array.iter().map(|value| self.translate_value(*value)).collect(); - self.context.builder.array_constant(elements, element_type.clone()) + self.context.builder.array_constant(elements, typ.clone()) } }; diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs index d3d9e56b3af..02350d9ed17 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, rc::Rc}; +use std::borrow::Cow; use acvm::FieldElement; use noirc_errors::Location; @@ -17,7 +17,6 @@ use super::{ dfg::InsertInstructionResult, function::RuntimeType, instruction::{InstructionId, Intrinsic}, - types::CompositeType, }, ssa_gen::Ssa, }; @@ -115,12 +114,8 @@ impl FunctionBuilder { } /// Insert an array constant into the current function with the given element values. - pub(crate) fn array_constant( - &mut self, - elements: im::Vector, - element_types: Rc, - ) -> ValueId { - self.current_function.dfg.make_array(elements, element_types) + pub(crate) fn array_constant(&mut self, elements: im::Vector, typ: Type) -> ValueId { + self.current_function.dfg.make_array(elements, typ) } /// Returns the type of the given value. diff --git a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs index 13e67f26cc5..2b6db4e7586 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/ssa_gen/mod.rs @@ -2,8 +2,6 @@ mod context; mod program; mod value; -use std::rc::Rc; - pub(crate) use program::Ssa; use context::SharedContext; @@ -16,12 +14,7 @@ use self::{ value::{Tree, Values}, }; -use super::ir::{ - function::RuntimeType, - instruction::BinaryOp, - types::{CompositeType, Type}, - value::ValueId, -}; +use super::ir::{function::RuntimeType, instruction::BinaryOp, types::Type, value::ValueId}; /// Generates SSA for the given monomorphized program. /// @@ -115,8 +108,8 @@ impl<'a> FunctionContext<'a> { match literal { ast::Literal::Array(array) => { let elements = vecmap(&array.contents, |element| self.codegen_expression(element)); - let element_types = Self::convert_type(&array.element_type).flatten(); - self.codegen_array(elements, element_types) + let typ = Self::convert_non_tuple_type(&array.typ); + self.codegen_array(elements, typ) } ast::Literal::Integer(value, typ) => { let typ = Self::convert_non_tuple_type(typ); @@ -129,7 +122,8 @@ impl<'a> FunctionContext<'a> { let elements = vecmap(string.as_bytes(), |byte| { self.builder.numeric_constant(*byte as u128, Type::field()).into() }); - self.codegen_array(elements, vec![Type::char()]) + let typ = Self::convert_non_tuple_type(&ast::Type::String(elements.len() as u64)); + self.codegen_array(elements, typ) } } } @@ -143,7 +137,7 @@ impl<'a> FunctionContext<'a> { /// stored the same as the array [1, 2, 3, 4]. /// /// The value returned from this function is always that of the allocate instruction. - fn codegen_array(&mut self, elements: Vec, element_types: CompositeType) -> Values { + fn codegen_array(&mut self, elements: Vec, typ: Type) -> Values { let mut array = im::Vector::new(); for element in elements { @@ -153,7 +147,7 @@ impl<'a> FunctionContext<'a> { }); } - self.builder.array_constant(array, Rc::new(element_types)).into() + self.builder.array_constant(array, typ).into() } fn codegen_block(&mut self, block: &[Expression]) -> Values { diff --git a/crates/noirc_frontend/src/monomorphization/ast.rs b/crates/noirc_frontend/src/monomorphization/ast.rs index 7cac2ed8e4f..488d05c6509 100644 --- a/crates/noirc_frontend/src/monomorphization/ast.rs +++ b/crates/noirc_frontend/src/monomorphization/ast.rs @@ -119,7 +119,7 @@ pub struct Cast { #[derive(Debug, Clone)] pub struct ArrayLiteral { pub contents: Vec, - pub element_type: Type, + pub typ: Type, } #[derive(Debug, Clone)] diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 8140065a2ac..bb0228091da 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -269,7 +269,7 @@ impl<'interner> Monomorphizer<'interner> { HirExpression::Literal(HirLiteral::Array(array)) => match array { HirArrayLiteral::Standard(array) => self.standard_array(expr, array), HirArrayLiteral::Repeated { repeated_element, length } => { - self.repeated_array(repeated_element, length) + self.repeated_array(expr, repeated_element, length) } }, HirExpression::Literal(HirLiteral::Unit) => ast::Expression::Block(vec![]), @@ -354,25 +354,26 @@ impl<'interner> Monomorphizer<'interner> { array: node_interner::ExprId, array_elements: Vec, ) -> ast::Expression { - let element_type = - Self::convert_type(&unwrap_array_element_type(&self.interner.id_type(array))); + let typ = Self::convert_type(&self.interner.id_type(array)); let contents = vecmap(array_elements, |id| self.expr(id)); - ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, element_type })) + ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ })) } fn repeated_array( &mut self, + array: node_interner::ExprId, repeated_element: node_interner::ExprId, length: HirType, ) -> ast::Expression { - let element_type = Self::convert_type(&self.interner.id_type(repeated_element)); + let typ = Self::convert_type(&self.interner.id_type(array)); + let contents = self.expr(repeated_element); let length = length .evaluate_to_u64() .expect("Length of array is unknown when evaluating numeric generic"); let contents = vec![contents; length as usize]; - ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, element_type })) + ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ })) } fn index(&mut self, id: node_interner::ExprId, index: HirIndexExpression) -> ast::Expression { @@ -764,17 +765,17 @@ impl<'interner> Monomorphizer<'interner> { } fn modulus_array_literal(&self, bytes: Vec, arr_elem_bits: u32) -> ast::Expression { + use ast::*; + let int_type = Type::Integer(crate::Signedness::Unsigned, arr_elem_bits); + let bytes_as_expr = vecmap(bytes, |byte| { - ast::Expression::Literal(ast::Literal::Integer( - (byte as u128).into(), - ast::Type::Integer(crate::Signedness::Unsigned, arr_elem_bits), - )) + Expression::Literal(Literal::Integer((byte as u128).into(), int_type.clone())) }); - let arr_literal = ast::ArrayLiteral { - contents: bytes_as_expr, - element_type: ast::Type::Integer(crate::Signedness::Unsigned, arr_elem_bits), - }; - ast::Expression::Literal(ast::Literal::Array(arr_literal)) + + let typ = Type::Array(bytes_as_expr.len() as u64, Box::new(int_type)); + + let arr_literal = ArrayLiteral { typ, contents: bytes_as_expr }; + Expression::Literal(Literal::Array(arr_literal)) } fn queue_function( @@ -915,7 +916,7 @@ impl<'interner> Monomorphizer<'interner> { let element = self.zeroed_value_of_type(element_type.as_ref()); ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents: vec![element; *length as usize], - element_type: element_type.as_ref().clone(), + typ: ast::Type::Array(*length, element_type.clone()), })) } ast::Type::String(length) => { @@ -930,7 +931,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::Slice(element_type) => { ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents: vec![], - element_type: *element_type.clone(), + typ: ast::Type::Slice(element_type.clone()), })) } ast::Type::MutableReference(element) => { @@ -1001,19 +1002,6 @@ fn unwrap_struct_type(typ: &HirType) -> Vec<(String, HirType)> { } } -fn unwrap_array_element_type(typ: &HirType) -> HirType { - match typ { - HirType::Array(_, elem) => *elem.clone(), - HirType::TypeVariable(binding, TypeVariableKind::Normal) => match &*binding.borrow() { - TypeBinding::Bound(binding) => unwrap_array_element_type(binding), - TypeBinding::Unbound(_) => unreachable!(), - }, - other => { - unreachable!("unwrap_array_element_type: expected an array or slice, found {:?}", other) - } - } -} - fn perform_instantiation_bindings(bindings: &TypeBindings) { for (var, binding) in bindings.values() { *var.borrow_mut() = TypeBinding::Bound(binding.clone()); From fe00354fef7c21e8a8c39b8469dd605fc018e797 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 27 Jul 2023 15:17:56 -0500 Subject: [PATCH 08/19] Fix tests --- crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs | 3 ++- .../src/ssa_refactor/opt/constant_folding.rs | 7 +++++-- crates/noirc_evaluator/src/ssa_refactor/opt/mem2reg.rs | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index b0ade9419fe..3bf18a2d86a 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -1057,7 +1057,8 @@ mod tests { let one = builder.field_constant(FieldElement::one()); let element_type = Rc::new(vec![Type::field()]); - let array = builder.array_constant(im::Vector::unit(one), element_type); + let array_type = Type::Array(element_type, 1); + let array = builder.array_constant(im::Vector::unit(one), array_type); builder.terminate_with_return(vec![array]); diff --git a/crates/noirc_evaluator/src/ssa_refactor/opt/constant_folding.rs b/crates/noirc_evaluator/src/ssa_refactor/opt/constant_folding.rs index 3c40e2a15c5..acf048595d7 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/opt/constant_folding.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/opt/constant_folding.rs @@ -92,6 +92,8 @@ impl Context { #[cfg(test)] mod test { + use std::rc::Rc; + use crate::ssa_refactor::{ ir::{ function::RuntimeType, @@ -176,8 +178,9 @@ mod test { let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); let v1 = builder.insert_binary(v0, BinaryOp::Add, one); - let arr = - builder.current_function.dfg.make_array(vec![v1].into(), vec![Type::field()].into()); + + let array_type = Type::Array(Rc::new(vec![Type::field()]), 1); + let arr = builder.current_function.dfg.make_array(vec![v1].into(), array_type); builder.terminate_with_return(vec![arr]); let ssa = builder.finish().fold_constants(); diff --git a/crates/noirc_evaluator/src/ssa_refactor/opt/mem2reg.rs b/crates/noirc_evaluator/src/ssa_refactor/opt/mem2reg.rs index 145ba25f5a5..15108abc490 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/opt/mem2reg.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/opt/mem2reg.rs @@ -212,10 +212,11 @@ mod tests { let two = builder.field_constant(FieldElement::one()); let element_type = Rc::new(vec![Type::field()]); - let array = builder.array_constant(vector![one, two], element_type.clone()); + let array_type = Type::Array(element_type, 2); + let array = builder.array_constant(vector![one, two], array_type.clone()); builder.insert_store(v0, array); - let v1 = builder.insert_load(v0, Type::Array(element_type, 2)); + let v1 = builder.insert_load(v0, array_type); let v2 = builder.insert_array_get(v1, one, Type::field()); builder.terminate_with_return(vec![v2]); From 704d9b8ee097f4722e2e6140eb80691fbf9c4f22 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 28 Jul 2023 07:27:01 +0000 Subject: [PATCH 09/19] fix: Initialize Value::Array of type Slice --- .../src/brillig/brillig_gen/brillig_block.rs | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 4de052aad9d..c7779533a8a 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -800,10 +800,29 @@ impl<'block> BrilligBlock<'block> { value_id, dfg, ); - let heap_array = self.function_context.extract_heap_array(new_variable); - self.brillig_context - .allocate_fixed_length_array(heap_array.pointer, heap_array.size); + // Initialize the variable + let pointer = match new_variable { + RegisterOrMemory::HeapArray(heap_array) => { + self.brillig_context + .allocate_fixed_length_array(heap_array.pointer, array.len()); + + heap_array.pointer + } + RegisterOrMemory::HeapVector(heap_vector) => { + self.brillig_context + .const_instruction(heap_vector.size, array.len().into()); + self.brillig_context + .allocate_array_instruction(heap_vector.pointer, heap_vector.size); + + heap_vector.pointer + } + _ => unreachable!( + "ICE: Cannot initialize array value created as {new_variable:?}" + ), + }; + + // Write the items // Allocate a register for the iterator let iterator_register = self.brillig_context.make_constant(0_usize.into()); @@ -811,11 +830,7 @@ impl<'block> BrilligBlock<'block> { 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( - heap_array.pointer, - iterator_register, - element_variable, - ); + self.store_variable_in_array(pointer, iterator_register, element_variable); // Increment the iterator self.brillig_context.usize_op_in_place(iterator_register, BinaryIntOp::Add, 1); } From 5c10ddb522ae44a0127fa248722668e69445e2ab Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 28 Jul 2023 07:34:43 +0000 Subject: [PATCH 10/19] test: improved brillig test after bug fix --- .../brillig_slices/src/main.nr | 98 ++++++++++--------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr index 7e4e8729199..34a9afcd515 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr @@ -2,71 +2,75 @@ use dep::std::slice; use dep::std; unconstrained fn main(x: Field, y: Field) { - // Mark it as mut so the compiler doesn't simplify the following operations - // But don't reuse the mut slice variable until this is fixed https://github.com/noir-lang/noir/issues/1931 - let slice: [Field] = [y, x]; + let mut slice: [Field] = [y, x]; assert(slice.len() == 2); - let mut pushed_back_slice = slice.push_back(7); - assert(pushed_back_slice.len() == 3); - assert(pushed_back_slice[0] == y); - assert(pushed_back_slice[1] == x); - assert(pushed_back_slice[2] == 7); + slice = slice.push_back(7); + assert(slice.len() == 3); + assert(slice[0] == y); + assert(slice[1] == x); + assert(slice[2] == 7); // Array set on slice target - pushed_back_slice[0] = x; - pushed_back_slice[1] = y; - pushed_back_slice[2] = 1; - - assert(pushed_back_slice[0] == x); - assert(pushed_back_slice[1] == y); - assert(pushed_back_slice[2] == 1); - - assert(slice.len() == 2); - - let pushed_front_slice = pushed_back_slice.push_front(2); - assert(pushed_front_slice.len() == 4); - assert(pushed_front_slice[0] == 2); - assert(pushed_front_slice[1] == x); - assert(pushed_front_slice[2] == y); - assert(pushed_front_slice[3] == 1); - - let (item, popped_front_slice) = pushed_front_slice.pop_front(); + slice[0] = x; + slice[1] = y; + slice[2] = 1; + + assert(slice[0] == x); + assert(slice[1] == y); + assert(slice[2] == 1); + + slice = push_front_to_slice(slice, 2); + assert(slice.len() == 4); + assert(slice[0] == 2); + assert(slice[1] == x); + assert(slice[2] == y); + assert(slice[3] == 1); + + let (item, popped_front_slice) = slice.pop_front(); + slice = popped_front_slice; assert(item == 2); - assert(popped_front_slice.len() == 3); - assert(popped_front_slice[0] == x); - assert(popped_front_slice[1] == y); - assert(popped_front_slice[2] == 1); + assert(slice.len() == 3); + assert(slice[0] == x); + assert(slice[1] == y); + assert(slice[2] == 1); - let (popped_back_slice, another_item) = popped_front_slice.pop_back(); + let (popped_back_slice, another_item) = slice.pop_back(); + slice = popped_back_slice; assert(another_item == 1); - assert(popped_back_slice.len() == 2); - assert(popped_back_slice[0] == x); - assert(popped_back_slice[1] == y); + assert(slice.len() == 2); + assert(slice[0] == x); + assert(slice[1] == y); - let inserted_slice = popped_back_slice.insert(1, 2); - assert(inserted_slice.len() == 3); - assert(inserted_slice[0] == x); - assert(inserted_slice[1] == 2); - assert(inserted_slice[2] == y); + slice = slice.insert(1, 2); + assert(slice.len() == 3); + assert(slice[0] == x); + assert(slice[1] == 2); + assert(slice[2] == y); - let (removed_slice, should_be_2) = inserted_slice.remove(1); + let (removed_slice, should_be_2) = slice.remove(1); + slice = removed_slice; assert(should_be_2 == 2); - assert(removed_slice.len() == 2); - assert(removed_slice[0] == x); - assert(removed_slice[1] == y); + assert(slice.len() == 2); + assert(slice[0] == x); + assert(slice[1] == y); - let (slice_with_only_x, should_be_y) = removed_slice.remove(1); + let (slice_with_only_x, should_be_y) = slice.remove(1); + slice = slice_with_only_x; assert(should_be_y == y); - assert(slice_with_only_x.len() == 1); - assert(removed_slice[0] == x); + assert(slice.len() == 1); + assert(slice[0] == x); - let (empty_slice, should_be_x) = slice_with_only_x.remove(0); + let (empty_slice, should_be_x) = slice.remove(0); assert(should_be_x == x); assert(empty_slice.len() == 0); } +// Tests slice passing to/from functions +unconstrained fn push_front_to_slice(slice: [T], item: T) -> [T] { + slice.push_front(item) +} \ No newline at end of file From 37aefbce870561237360c23771cfe48002469984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Fri, 28 Jul 2023 14:12:15 +0100 Subject: [PATCH 11/19] fix: Slice initialization (#2080) * fix: Initialize Value::Array of type Slice * test: improved brillig test after bug fix --- .../brillig_slices/src/main.nr | 98 ++++++++++--------- .../src/brillig/brillig_gen/brillig_block.rs | 31 ++++-- 2 files changed, 74 insertions(+), 55 deletions(-) diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr index 7e4e8729199..34a9afcd515 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr @@ -2,71 +2,75 @@ use dep::std::slice; use dep::std; unconstrained fn main(x: Field, y: Field) { - // Mark it as mut so the compiler doesn't simplify the following operations - // But don't reuse the mut slice variable until this is fixed https://github.com/noir-lang/noir/issues/1931 - let slice: [Field] = [y, x]; + let mut slice: [Field] = [y, x]; assert(slice.len() == 2); - let mut pushed_back_slice = slice.push_back(7); - assert(pushed_back_slice.len() == 3); - assert(pushed_back_slice[0] == y); - assert(pushed_back_slice[1] == x); - assert(pushed_back_slice[2] == 7); + slice = slice.push_back(7); + assert(slice.len() == 3); + assert(slice[0] == y); + assert(slice[1] == x); + assert(slice[2] == 7); // Array set on slice target - pushed_back_slice[0] = x; - pushed_back_slice[1] = y; - pushed_back_slice[2] = 1; - - assert(pushed_back_slice[0] == x); - assert(pushed_back_slice[1] == y); - assert(pushed_back_slice[2] == 1); - - assert(slice.len() == 2); - - let pushed_front_slice = pushed_back_slice.push_front(2); - assert(pushed_front_slice.len() == 4); - assert(pushed_front_slice[0] == 2); - assert(pushed_front_slice[1] == x); - assert(pushed_front_slice[2] == y); - assert(pushed_front_slice[3] == 1); - - let (item, popped_front_slice) = pushed_front_slice.pop_front(); + slice[0] = x; + slice[1] = y; + slice[2] = 1; + + assert(slice[0] == x); + assert(slice[1] == y); + assert(slice[2] == 1); + + slice = push_front_to_slice(slice, 2); + assert(slice.len() == 4); + assert(slice[0] == 2); + assert(slice[1] == x); + assert(slice[2] == y); + assert(slice[3] == 1); + + let (item, popped_front_slice) = slice.pop_front(); + slice = popped_front_slice; assert(item == 2); - assert(popped_front_slice.len() == 3); - assert(popped_front_slice[0] == x); - assert(popped_front_slice[1] == y); - assert(popped_front_slice[2] == 1); + assert(slice.len() == 3); + assert(slice[0] == x); + assert(slice[1] == y); + assert(slice[2] == 1); - let (popped_back_slice, another_item) = popped_front_slice.pop_back(); + let (popped_back_slice, another_item) = slice.pop_back(); + slice = popped_back_slice; assert(another_item == 1); - assert(popped_back_slice.len() == 2); - assert(popped_back_slice[0] == x); - assert(popped_back_slice[1] == y); + assert(slice.len() == 2); + assert(slice[0] == x); + assert(slice[1] == y); - let inserted_slice = popped_back_slice.insert(1, 2); - assert(inserted_slice.len() == 3); - assert(inserted_slice[0] == x); - assert(inserted_slice[1] == 2); - assert(inserted_slice[2] == y); + slice = slice.insert(1, 2); + assert(slice.len() == 3); + assert(slice[0] == x); + assert(slice[1] == 2); + assert(slice[2] == y); - let (removed_slice, should_be_2) = inserted_slice.remove(1); + let (removed_slice, should_be_2) = slice.remove(1); + slice = removed_slice; assert(should_be_2 == 2); - assert(removed_slice.len() == 2); - assert(removed_slice[0] == x); - assert(removed_slice[1] == y); + assert(slice.len() == 2); + assert(slice[0] == x); + assert(slice[1] == y); - let (slice_with_only_x, should_be_y) = removed_slice.remove(1); + let (slice_with_only_x, should_be_y) = slice.remove(1); + slice = slice_with_only_x; assert(should_be_y == y); - assert(slice_with_only_x.len() == 1); - assert(removed_slice[0] == x); + assert(slice.len() == 1); + assert(slice[0] == x); - let (empty_slice, should_be_x) = slice_with_only_x.remove(0); + let (empty_slice, should_be_x) = slice.remove(0); assert(should_be_x == x); assert(empty_slice.len() == 0); } +// Tests slice passing to/from functions +unconstrained fn push_front_to_slice(slice: [T], item: T) -> [T] { + slice.push_front(item) +} \ No newline at end of file diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 4de052aad9d..c7779533a8a 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -800,10 +800,29 @@ impl<'block> BrilligBlock<'block> { value_id, dfg, ); - let heap_array = self.function_context.extract_heap_array(new_variable); - self.brillig_context - .allocate_fixed_length_array(heap_array.pointer, heap_array.size); + // Initialize the variable + let pointer = match new_variable { + RegisterOrMemory::HeapArray(heap_array) => { + self.brillig_context + .allocate_fixed_length_array(heap_array.pointer, array.len()); + + heap_array.pointer + } + RegisterOrMemory::HeapVector(heap_vector) => { + self.brillig_context + .const_instruction(heap_vector.size, array.len().into()); + self.brillig_context + .allocate_array_instruction(heap_vector.pointer, heap_vector.size); + + heap_vector.pointer + } + _ => unreachable!( + "ICE: Cannot initialize array value created as {new_variable:?}" + ), + }; + + // Write the items // Allocate a register for the iterator let iterator_register = self.brillig_context.make_constant(0_usize.into()); @@ -811,11 +830,7 @@ impl<'block> BrilligBlock<'block> { 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( - heap_array.pointer, - iterator_register, - element_variable, - ); + self.store_variable_in_array(pointer, iterator_register, element_variable); // Increment the iterator self.brillig_context.usize_op_in_place(iterator_register, BinaryIntOp::Add, 1); } From 94cb29168d068b0e1aab32a26582b97d52cb6e6f Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 28 Jul 2023 13:44:40 +0000 Subject: [PATCH 12/19] feat: nested slices --- .../brillig_slices/src/main.nr | 40 +- .../src/brillig/brillig_gen/brillig_block.rs | 158 ++--- .../brillig/brillig_gen/brillig_slice_ops.rs | 576 +++++++++++------- 3 files changed, 467 insertions(+), 307 deletions(-) diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr index 34a9afcd515..4f4d90ab168 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr @@ -68,9 +68,47 @@ unconstrained fn main(x: Field, y: Field) { let (empty_slice, should_be_x) = slice.remove(0); assert(should_be_x == x); assert(empty_slice.len() == 0); + + test_nested(x,y); } // Tests slice passing to/from functions unconstrained fn push_front_to_slice(slice: [T], item: T) -> [T] { slice.push_front(item) -} \ No newline at end of file +} + +struct Foo { + x: Field, + y: Field, + arr: [Field] +} + +unconstrained fn create_foo(x: Field, y: Field) -> Foo { + let mut arr = [x]; + arr = arr.push_back(y); + Foo { arr: arr, x, y } +} + +unconstrained fn test_nested(x: Field, y: Field) { + let mut slice = [create_foo(x,y), create_foo(y, x)]; + assert(slice.len() == 2); + + assert(slice[0].y == y); + assert(slice[0].arr[0] == x); + assert(slice[1].x == y); + assert(slice[1].arr[1] == x); + + slice = slice.push_back(create_foo(7,8)); + assert(slice.len() == 3); + + assert(slice[0].x == x); + assert(slice[0].arr[1] == y); + + assert(slice[1].y == x); + assert(slice[1].arr[0] == y); + + assert(slice[2].x == 7); + assert(slice[2].y == 8); + assert(slice[2].arr[0] == 7); + assert(slice[2].arr[1] == 8); +} diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index c7779533a8a..589b3d7da08 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -1,6 +1,3 @@ -use crate::brillig::brillig_gen::brillig_slice_ops::{ - convert_array_or_vector_to_vector, slice_push_back_operation, -}; use crate::brillig::brillig_ir::{ BrilligBinaryOp, BrilligContext, BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE, }; @@ -20,18 +17,14 @@ use iter_extended::vecmap; use super::brillig_black_box::convert_black_box_call; use super::brillig_fn::FunctionContext; -use super::brillig_slice_ops::{ - slice_insert_operation, slice_pop_back_operation, slice_pop_front_operation, - slice_push_front_operation, slice_remove_operation, -}; /// Generate the compilation artifacts for compiling a function into brillig bytecode. pub(crate) struct BrilligBlock<'block> { - function_context: &'block mut FunctionContext, + pub(crate) function_context: &'block mut FunctionContext, /// The basic block that is being converted - block_id: BasicBlockId, + pub(crate) block_id: BasicBlockId, /// Context for creating brillig opcodes - brillig_context: &'block mut BrilligContext, + pub(crate) brillig_context: &'block mut BrilligContext, } impl<'block> BrilligBlock<'block> { @@ -309,8 +302,19 @@ impl<'block> BrilligBlock<'block> { dfg.instruction_results(instruction_id)[0], dfg, ); - let param = self.convert_ssa_value(arguments[0], dfg); - self.brillig_context.length_of_variable_instruction(param, result_register); + let param_id = arguments[0]; + let param_variable = self.convert_ssa_value(param_id, dfg); + + self.brillig_context + .length_of_variable_instruction(param_variable, result_register); + + let item_size = self.get_ssa_item_size(param_id, dfg); + + self.brillig_context.usize_op_in_place( + result_register, + BinaryIntOp::UnsignedDiv, + item_size, + ); } Value::Intrinsic( Intrinsic::SlicePushBack @@ -408,7 +412,11 @@ impl<'block> BrilligBlock<'block> { }; let index_register = self.convert_ssa_register_value(*index, dfg); - self.convert_ssa_array_get(array_pointer, index_register, destination_variable); + self.retrieve_variable_from_array( + array_pointer, + index_register, + destination_variable, + ); } Instruction::ArraySet { array, index, value } => { let source_variable = self.convert_ssa_value(*array, dfg); @@ -483,7 +491,7 @@ impl<'block> BrilligBlock<'block> { .post_call_prep_returns_load_registers(&returned_registers, &saved_registers); } - fn convert_ssa_array_get( + pub(crate) fn retrieve_variable_from_array( &mut self, array_pointer: RegisterIndex, index_register: RegisterIndex, @@ -496,7 +504,13 @@ impl<'block> BrilligBlock<'block> { RegisterOrMemory::HeapArray(HeapArray { pointer, .. }) => { self.brillig_context.array_get(array_pointer, index_register, pointer); } - RegisterOrMemory::HeapVector(_) => unimplemented!("ICE: Array get for vector"), + RegisterOrMemory::HeapVector(..) => { + // Vectors are stored as references inside arrays to be able to match SSA indexes + let reference = self.brillig_context.allocate_register(); + self.brillig_context.array_get(array_pointer, index_register, reference); + self.brillig_context.load_variable_instruction(destination_variable, reference); + self.brillig_context.deallocate_register(reference); + } } } @@ -551,7 +565,7 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.deallocate_register(source_size_as_register); } - fn store_variable_in_array( + pub(crate) fn store_variable_in_array( &mut self, destination_pointer: RegisterIndex, index_register: RegisterIndex, @@ -565,7 +579,12 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.array_set(destination_pointer, index_register, pointer); } RegisterOrMemory::HeapVector(_) => { - unimplemented!("ICE: cannot store a vector in array") + // Vectors are stored as references inside arrays to be able to match SSA indexes + let reference = self.brillig_context.allocate_register(); + self.brillig_context.allocate_variable_instruction(reference); + self.brillig_context.store_variable_instruction(reference, value_variable); + self.brillig_context.array_set(destination_pointer, index_register, reference); + self.brillig_context.deallocate_register(reference); } } } @@ -578,9 +597,10 @@ impl<'block> BrilligBlock<'block> { instruction_id: InstructionId, arguments: &[ValueId], ) { - let source_variable = self.convert_ssa_value(arguments[0], dfg); - let source_vector = - convert_array_or_vector_to_vector(self.brillig_context, source_variable); + let slice_id = arguments[0]; + let subitem_count = self.get_ssa_item_size(slice_id, dfg); + let source_variable = self.convert_ssa_value(slice_id, dfg); + let source_vector = self.convert_array_or_vector_to_vector(source_variable); match intrinsic { Value::Intrinsic(Intrinsic::SlicePushBack) => { @@ -590,13 +610,10 @@ impl<'block> BrilligBlock<'block> { dfg, ); let target_vector = self.function_context.extract_heap_vector(target_variable); - let item_value = self.convert_ssa_register_value(arguments[1], dfg); - slice_push_back_operation( - self.brillig_context, - target_vector, - source_vector, - item_value, - ); + let item_values = vecmap(&arguments[1..subitem_count + 1], |arg| { + self.convert_ssa_value(*arg, dfg) + }); + self.slice_push_back_operation(target_vector, source_vector, &item_values); } Value::Intrinsic(Intrinsic::SlicePushFront) => { let target_variable = self.function_context.create_variable( @@ -605,68 +622,54 @@ impl<'block> BrilligBlock<'block> { dfg, ); let target_vector = self.function_context.extract_heap_vector(target_variable); - let item_value = self.convert_ssa_register_value(arguments[1], dfg); - slice_push_front_operation( - self.brillig_context, - target_vector, - source_vector, - item_value, - ); + let item_values = vecmap(&arguments[1..subitem_count + 1], |arg| { + self.convert_ssa_value(*arg, dfg) + }); + self.slice_push_front_operation(target_vector, source_vector, &item_values); } Value::Intrinsic(Intrinsic::SlicePopBack) => { let results = dfg.instruction_results(instruction_id); let target_variable = self.function_context.create_variable(self.brillig_context, results[0], dfg); + let target_vector = self.function_context.extract_heap_vector(target_variable); - let pop_item = self.function_context.create_register_variable( - self.brillig_context, - results[1], - dfg, - ); + let pop_variables = vecmap(&results[1..subitem_count + 1], |result| { + self.function_context.create_variable(self.brillig_context, *result, dfg) + }); - slice_pop_back_operation( - self.brillig_context, - target_vector, - source_vector, - pop_item, - ); + self.slice_pop_back_operation(target_vector, source_vector, &pop_variables); } Value::Intrinsic(Intrinsic::SlicePopFront) => { let results = dfg.instruction_results(instruction_id); - let pop_item = self.function_context.create_register_variable( + let pop_variables = vecmap(&results[0..subitem_count], |result| { + self.function_context.create_variable(self.brillig_context, *result, dfg) + }); + + let target_variable = self.function_context.create_variable( self.brillig_context, - results[0], + results[subitem_count], dfg, ); - let target_variable = - self.function_context.create_variable(self.brillig_context, results[1], dfg); let target_vector = self.function_context.extract_heap_vector(target_variable); - slice_pop_front_operation( - self.brillig_context, - target_vector, - source_vector, - pop_item, - ); + self.slice_pop_front_operation(target_vector, source_vector, &pop_variables); } Value::Intrinsic(Intrinsic::SliceInsert) => { let results = dfg.instruction_results(instruction_id); let index = self.convert_ssa_register_value(arguments[1], dfg); - let item = self.convert_ssa_register_value(arguments[2], dfg); + + let items = vecmap(&arguments[2..subitem_count + 2], |arg| { + self.convert_ssa_value(*arg, dfg) + }); + let target_variable = self.function_context.create_variable(self.brillig_context, results[0], dfg); let target_vector = self.function_context.extract_heap_vector(target_variable); - slice_insert_operation( - self.brillig_context, - target_vector, - source_vector, - index, - item, - ); + self.slice_insert_operation(target_vector, source_vector, index, &items); } Value::Intrinsic(Intrinsic::SliceRemove) => { let results = dfg.instruction_results(instruction_id); @@ -676,19 +679,11 @@ impl<'block> BrilligBlock<'block> { self.function_context.create_variable(self.brillig_context, results[0], dfg); let target_vector = self.function_context.extract_heap_vector(target_variable); - let removed_item_register = self.function_context.create_register_variable( - self.brillig_context, - results[1], - dfg, - ); + let removed_items = vecmap(&results[1..subitem_count + 1], |result| { + self.function_context.create_variable(self.brillig_context, *result, dfg) + }); - slice_remove_operation( - self.brillig_context, - target_vector, - source_vector, - index, - removed_item_register, - ); + self.slice_remove_operation(target_vector, source_vector, index, &removed_items); } _ => unreachable!("ICE: Slice operation not supported"), } @@ -890,6 +885,19 @@ impl<'block> BrilligBlock<'block> { } } } + + fn get_ssa_item_size(&self, array_id: ValueId, dfg: &DataFlowGraph) -> usize { + let array_type = dfg[array_id].get_type(); + match array_type { + Type::Array(item_types, _) | Type::Slice(item_types) => { + // To match SSA indexes, all subitems are stored as one single value + item_types.len() + } + _ => { + unreachable!("ICE: Cannot get item size of {array_type:?}") + } + } + } } /// Returns the type of the operation considering the types of the operands diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 99af5c2b13b..622a7b9f8d0 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -1,231 +1,343 @@ use acvm::brillig_vm::brillig::{BinaryIntOp, HeapVector, RegisterIndex, RegisterOrMemory}; -use crate::brillig::brillig_ir::BrilligContext; - -pub(crate) fn slice_push_back_operation( - brillig_context: &mut BrilligContext, - target_vector: HeapVector, - source_vector: HeapVector, - item_to_insert: RegisterIndex, -) { - // First we need to allocate the target vector incrementing the size by 1 - brillig_context.usize_op(source_vector.size, target_vector.size, BinaryIntOp::Add, 1); - brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); - - // Now we copy the source vector into the target vector - brillig_context.copy_array_instruction( - source_vector.pointer, - target_vector.pointer, - source_vector.size, - ); - - brillig_context.array_set(target_vector.pointer, source_vector.size, item_to_insert); -} +use super::brillig_block::BrilligBlock; + +impl<'block> BrilligBlock<'block> { + pub(crate) fn slice_push_back_operation( + &mut self, + target_vector: HeapVector, + source_vector: HeapVector, + variables_to_insert: &[RegisterOrMemory], + ) { + // First we need to allocate the target vector incrementing the size by variables_to_insert.len() + self.brillig_context.usize_op( + source_vector.size, + target_vector.size, + BinaryIntOp::Add, + variables_to_insert.len(), + ); + self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); -pub(crate) fn slice_push_front_operation( - brillig_context: &mut BrilligContext, - target_vector: HeapVector, - source_vector: HeapVector, - item_to_insert: RegisterIndex, -) { - // First we need to allocate the target vector incrementing the size by 1 - brillig_context.usize_op(source_vector.size, target_vector.size, BinaryIntOp::Add, 1); - brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); - - // Now we offset the target pointer by one - let destination_copy_pointer = brillig_context.allocate_register(); - brillig_context.usize_op(target_vector.pointer, destination_copy_pointer, BinaryIntOp::Add, 1); - - // Now we copy the source vector into the target vector starting at index 1 - brillig_context.copy_array_instruction( - source_vector.pointer, - destination_copy_pointer, - source_vector.size, - ); - brillig_context.deallocate_register(destination_copy_pointer); - - // Then we write the item to insert at index 0 - let zero = brillig_context.make_constant(0_u128.into()); - brillig_context.array_set(target_vector.pointer, zero, item_to_insert); - brillig_context.deallocate_register(zero); -} + // Now we copy the source vector into the target vector + self.brillig_context.copy_array_instruction( + source_vector.pointer, + target_vector.pointer, + source_vector.size, + ); -pub(crate) fn slice_pop_front_operation( - brillig_context: &mut BrilligContext, - target_vector: HeapVector, - source_vector: HeapVector, - removed_item: RegisterIndex, -) { - // First we need to allocate the target vector decrementing the size by 1 - brillig_context.usize_op(source_vector.size, target_vector.size, BinaryIntOp::Sub, 1); - brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); - - // Now we offset the source pointer by one - let source_copy_pointer = brillig_context.allocate_register(); - brillig_context.usize_op(source_vector.pointer, source_copy_pointer, BinaryIntOp::Add, 1); - - // Now we copy the source vector starting at index 1 into the target vector - brillig_context.copy_array_instruction( - source_copy_pointer, - target_vector.pointer, - target_vector.size, - ); - brillig_context.deallocate_register(source_copy_pointer); - - let zero = brillig_context.make_constant(0_u128.into()); - brillig_context.array_get(source_vector.pointer, zero, removed_item); - brillig_context.deallocate_register(zero); -} + for (index, variable) in variables_to_insert.iter().enumerate() { + let target_index = self.brillig_context.make_constant(index.into()); + self.brillig_context.memory_op( + target_index, + source_vector.size, + target_index, + BinaryIntOp::Add, + ); + self.store_variable_in_array(target_vector.pointer, target_index, *variable); + self.brillig_context.deallocate_register(target_index); + } + } -pub(crate) fn slice_pop_back_operation( - brillig_context: &mut BrilligContext, - target_vector: HeapVector, - source_vector: HeapVector, - removed_item: RegisterIndex, -) { - // First we need to allocate the target vector decrementing the size by 1 - brillig_context.usize_op(source_vector.size, target_vector.size, BinaryIntOp::Sub, 1); - brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); - - // Now we copy all elements but the last into the target vector - brillig_context.copy_array_instruction( - source_vector.pointer, - target_vector.pointer, - target_vector.size, - ); - - brillig_context.array_get(source_vector.pointer, target_vector.size, removed_item); -} + pub(crate) fn slice_push_front_operation( + &mut self, + target_vector: HeapVector, + source_vector: HeapVector, + variables_to_insert: &[RegisterOrMemory], + ) { + // First we need to allocate the target vector incrementing the size by variables_to_insert.len() + self.brillig_context.usize_op( + source_vector.size, + target_vector.size, + BinaryIntOp::Add, + variables_to_insert.len(), + ); + self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + + // Now we offset the target pointer by variables_to_insert.len() + let destination_copy_pointer = self.brillig_context.allocate_register(); + self.brillig_context.usize_op( + target_vector.pointer, + destination_copy_pointer, + BinaryIntOp::Add, + variables_to_insert.len(), + ); -pub(crate) fn slice_insert_operation( - brillig_context: &mut BrilligContext, - target_vector: HeapVector, - source_vector: HeapVector, - index: RegisterIndex, - item: RegisterIndex, -) { - // First we need to allocate the target vector incrementing the size by 1 - brillig_context.usize_op(source_vector.size, target_vector.size, BinaryIntOp::Add, 1); - brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); - - // Copy the elements to the left of the index - brillig_context.copy_array_instruction(source_vector.pointer, target_vector.pointer, index); - - // Compute the source pointer just at the index - let source_pointer_at_index = brillig_context.allocate_register(); - brillig_context.memory_op( - source_vector.pointer, - index, - source_pointer_at_index, - BinaryIntOp::Add, - ); - - // Compute the target pointer after the index - let target_pointer_after_index = brillig_context.allocate_register(); - brillig_context.memory_op( - target_vector.pointer, - index, - target_pointer_after_index, - BinaryIntOp::Add, - ); - brillig_context.usize_op_in_place(target_pointer_after_index, BinaryIntOp::Add, 1); - - // Compute the number of elements to the right of the index - let item_count = brillig_context.allocate_register(); - brillig_context.memory_op(source_vector.size, index, item_count, BinaryIntOp::Sub); - - // Copy the elements to the right of the index - brillig_context.copy_array_instruction( - source_pointer_at_index, - target_pointer_after_index, - item_count, - ); - - brillig_context.deallocate_register(source_pointer_at_index); - brillig_context.deallocate_register(target_pointer_after_index); - brillig_context.deallocate_register(item_count); - - // Write the item to insert at the index - brillig_context.array_set(target_vector.pointer, index, item); -} + // Now we copy the source vector into the target vector starting at index variables_to_insert.len() + self.brillig_context.copy_array_instruction( + source_vector.pointer, + destination_copy_pointer, + source_vector.size, + ); -pub(crate) fn slice_remove_operation( - brillig_context: &mut BrilligContext, - target_vector: HeapVector, - source_vector: HeapVector, - index: RegisterIndex, - removed_item: RegisterIndex, -) { - // First we need to allocate the target vector decrementing the size by 1 - brillig_context.usize_op(source_vector.size, target_vector.size, BinaryIntOp::Sub, 1); - brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); - - // Copy the elements to the left of the index - brillig_context.copy_array_instruction(source_vector.pointer, target_vector.pointer, index); - - // Compute the source pointer after the index - let source_pointer_after_index = brillig_context.allocate_register(); - brillig_context.memory_op( - source_vector.pointer, - index, - source_pointer_after_index, - BinaryIntOp::Add, - ); - brillig_context.usize_op_in_place(source_pointer_after_index, BinaryIntOp::Add, 1); - - // Compute the target pointer at the index - let target_pointer_at_index = brillig_context.allocate_register(); - brillig_context.memory_op( - target_vector.pointer, - index, - target_pointer_at_index, - BinaryIntOp::Add, - ); - - // Compute the number of elements to the right of the index - let item_count = brillig_context.allocate_register(); - brillig_context.memory_op(source_vector.size, index, item_count, BinaryIntOp::Sub); - brillig_context.usize_op_in_place(item_count, BinaryIntOp::Sub, 1); - - // Copy the elements to the right of the index - brillig_context.copy_array_instruction( - source_pointer_after_index, - target_pointer_at_index, - item_count, - ); - - brillig_context.deallocate_register(source_pointer_after_index); - brillig_context.deallocate_register(target_pointer_at_index); - brillig_context.deallocate_register(item_count); - - // Get the item at the index - brillig_context.array_get(source_vector.pointer, index, removed_item); -} + // Then we write the items to insert at the start + for (index, variable) in variables_to_insert.iter().enumerate() { + let target_index = self.brillig_context.make_constant(index.into()); + self.store_variable_in_array(target_vector.pointer, target_index, *variable); + self.brillig_context.deallocate_register(target_index); + } + + self.brillig_context.deallocate_register(destination_copy_pointer); + } + + pub(crate) fn slice_pop_front_operation( + &mut self, + target_vector: HeapVector, + source_vector: HeapVector, + removed_items: &[RegisterOrMemory], + ) { + // First we need to allocate the target vector decrementing the size by removed_items.len() + self.brillig_context.usize_op( + source_vector.size, + target_vector.size, + BinaryIntOp::Sub, + removed_items.len(), + ); + self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + + // Now we offset the source pointer by removed_items.len() + let source_copy_pointer = self.brillig_context.allocate_register(); + self.brillig_context.usize_op( + source_vector.pointer, + source_copy_pointer, + BinaryIntOp::Add, + removed_items.len(), + ); + + // Now we copy the source vector starting at index removed_items.len() into the target vector + self.brillig_context.copy_array_instruction( + source_copy_pointer, + target_vector.pointer, + target_vector.size, + ); + + for (index, variable) in removed_items.iter().enumerate() { + let target_index = self.brillig_context.make_constant(index.into()); + self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); + self.brillig_context.deallocate_register(target_index); + } -pub(crate) fn convert_array_or_vector_to_vector( - brillig_context: &mut BrilligContext, - source_variable: RegisterOrMemory, -) -> HeapVector { - match source_variable { - RegisterOrMemory::HeapVector(source_vector) => source_vector, - RegisterOrMemory::HeapArray(source_array) => brillig_context.array_to_vector(&source_array), - _ => unreachable!("ICE: unsupported slice push back source {:?}", source_variable), + self.brillig_context.deallocate_register(source_copy_pointer); + } + + pub(crate) fn slice_pop_back_operation( + &mut self, + target_vector: HeapVector, + source_vector: HeapVector, + removed_items: &[RegisterOrMemory], + ) { + // First we need to allocate the target vector decrementing the size by removed_items.len() + self.brillig_context.usize_op( + source_vector.size, + target_vector.size, + BinaryIntOp::Sub, + removed_items.len(), + ); + self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + + // Now we copy all elements except the last items into the target vector + self.brillig_context.copy_array_instruction( + source_vector.pointer, + target_vector.pointer, + target_vector.size, + ); + + for (index, variable) in removed_items.iter().enumerate() { + let target_index = self.brillig_context.make_constant(index.into()); + self.brillig_context.memory_op( + target_index, + target_vector.size, + target_index, + BinaryIntOp::Add, + ); + self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); + } + } + + pub(crate) fn slice_insert_operation( + &mut self, + target_vector: HeapVector, + source_vector: HeapVector, + index: RegisterIndex, + items: &[RegisterOrMemory], + ) { + // First we need to allocate the target vector incrementing the size by items.len() + self.brillig_context.usize_op( + source_vector.size, + target_vector.size, + BinaryIntOp::Add, + items.len(), + ); + self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + + // Copy the elements to the left of the index + self.brillig_context.copy_array_instruction( + source_vector.pointer, + target_vector.pointer, + index, + ); + + // Compute the source pointer just at the index + let source_pointer_at_index = self.brillig_context.allocate_register(); + self.brillig_context.memory_op( + source_vector.pointer, + index, + source_pointer_at_index, + BinaryIntOp::Add, + ); + + // Compute the target pointer after the inserted elements + let target_pointer_after_index = self.brillig_context.allocate_register(); + self.brillig_context.memory_op( + target_vector.pointer, + index, + target_pointer_after_index, + BinaryIntOp::Add, + ); + self.brillig_context.usize_op_in_place( + target_pointer_after_index, + BinaryIntOp::Add, + items.len(), + ); + + // Compute the number of elements to the right of the index + let item_count = self.brillig_context.allocate_register(); + self.brillig_context.memory_op(source_vector.size, index, item_count, BinaryIntOp::Sub); + + // Copy the elements to the right of the index + self.brillig_context.copy_array_instruction( + source_pointer_at_index, + target_pointer_after_index, + item_count, + ); + + // Write the items to insert starting at the index + for (subitem_index, variable) in items.iter().enumerate() { + let target_index = self.brillig_context.make_constant(subitem_index.into()); + self.brillig_context.memory_op(target_index, index, target_index, BinaryIntOp::Add); + self.store_variable_in_array(target_vector.pointer, target_index, *variable); + self.brillig_context.deallocate_register(target_index); + } + + self.brillig_context.deallocate_register(source_pointer_at_index); + self.brillig_context.deallocate_register(target_pointer_after_index); + self.brillig_context.deallocate_register(item_count); + } + + pub(crate) fn slice_remove_operation( + &mut self, + target_vector: HeapVector, + source_vector: HeapVector, + index: RegisterIndex, + removed_items: &[RegisterOrMemory], + ) { + // First we need to allocate the target vector decrementing the size by removed_items.len() + self.brillig_context.usize_op( + source_vector.size, + target_vector.size, + BinaryIntOp::Sub, + removed_items.len(), + ); + self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + + // Copy the elements to the left of the index + self.brillig_context.copy_array_instruction( + source_vector.pointer, + target_vector.pointer, + index, + ); + + // Compute the source pointer after the removed items + let source_pointer_after_index = self.brillig_context.allocate_register(); + self.brillig_context.memory_op( + source_vector.pointer, + index, + source_pointer_after_index, + BinaryIntOp::Add, + ); + self.brillig_context.usize_op_in_place( + source_pointer_after_index, + BinaryIntOp::Add, + removed_items.len(), + ); + + // Compute the target pointer at the index + let target_pointer_at_index = self.brillig_context.allocate_register(); + self.brillig_context.memory_op( + target_vector.pointer, + index, + target_pointer_at_index, + BinaryIntOp::Add, + ); + + // Compute the number of elements to the right of the index + let item_count = self.brillig_context.allocate_register(); + self.brillig_context.memory_op(source_vector.size, index, item_count, BinaryIntOp::Sub); + self.brillig_context.usize_op_in_place(item_count, BinaryIntOp::Sub, removed_items.len()); + + // Copy the elements to the right of the index + self.brillig_context.copy_array_instruction( + source_pointer_after_index, + target_pointer_at_index, + item_count, + ); + + // Get the removed items + for (subitem_index, variable) in removed_items.iter().enumerate() { + let target_index = self.brillig_context.make_constant(subitem_index.into()); + self.brillig_context.memory_op(target_index, index, target_index, BinaryIntOp::Add); + self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); + self.brillig_context.deallocate_register(target_index); + } + + self.brillig_context.deallocate_register(source_pointer_after_index); + self.brillig_context.deallocate_register(target_pointer_at_index); + self.brillig_context.deallocate_register(item_count); + } + + pub(crate) fn convert_array_or_vector_to_vector( + &mut self, + source_variable: RegisterOrMemory, + ) -> HeapVector { + match source_variable { + RegisterOrMemory::HeapVector(source_vector) => source_vector, + RegisterOrMemory::HeapArray(source_array) => { + self.brillig_context.array_to_vector(&source_array) + } + _ => unreachable!("ICE: unsupported slice push back source {:?}", source_variable), + } } } #[cfg(test)] mod tests { + use std::collections::HashMap; use std::vec; use acvm::acir::brillig::{HeapVector, Value}; - use acvm::brillig_vm::brillig::RegisterIndex; + use acvm::brillig_vm::brillig::{RegisterIndex, RegisterOrMemory}; - use crate::brillig::brillig_gen::brillig_slice_ops::{ - slice_insert_operation, slice_pop_back_operation, slice_pop_front_operation, - slice_push_back_operation, slice_push_front_operation, slice_remove_operation, - }; + use crate::brillig::brillig_gen::brillig_block::BrilligBlock; + use crate::brillig::brillig_gen::brillig_fn::FunctionContext; use crate::brillig::brillig_ir::artifact::BrilligParameter; use crate::brillig::brillig_ir::tests::{create_and_run_vm, create_context}; + use crate::brillig::brillig_ir::BrilligContext; + use crate::ssa_refactor::ir::map::Id; + + fn create_test_environment() -> (FunctionContext, BrilligContext) { + let function_context = FunctionContext { + function_id: Id::test_new(0), + ssa_value_to_brillig_variable: HashMap::new(), + }; + let brillig_context = create_context(); + (function_context, brillig_context) + } + + fn create_brillig_block<'a>( + function_context: &'a mut FunctionContext, + brillig_context: &'a mut BrilligContext, + ) -> BrilligBlock<'a> { + BrilligBlock { function_context, block_id: Id::test_new(0), brillig_context } + } #[test] fn test_slice_push_operation() { @@ -244,7 +356,7 @@ mod tests { BrilligParameter::Simple, ]; - let mut context = create_context(); + let (mut function_context, mut context) = create_test_environment(); // Allocate the parameters let array_pointer = context.allocate_register(); @@ -257,19 +369,19 @@ mod tests { let copied_array_pointer = context.allocate_register(); let copied_array_size = context.allocate_register(); + let mut block = create_brillig_block(&mut function_context, &mut context); + if push_back { - slice_push_back_operation( - &mut context, + block.slice_push_back_operation( HeapVector { pointer: copied_array_pointer, size: copied_array_size }, HeapVector { pointer: array_pointer, size: array_size }, - item_to_insert, + &[RegisterOrMemory::RegisterIndex(item_to_insert)], ); } else { - slice_push_front_operation( - &mut context, + block.slice_push_front_operation( HeapVector { pointer: copied_array_pointer, size: copied_array_size }, HeapVector { pointer: array_pointer, size: array_size }, - item_to_insert, + &[RegisterOrMemory::RegisterIndex(item_to_insert)], ); } @@ -337,7 +449,7 @@ mod tests { BrilligParameter::Simple, ]; - let mut context = create_context(); + let (mut function_context, mut context) = create_test_environment(); // Allocate the parameters let array_pointer = context.allocate_register(); @@ -351,19 +463,19 @@ mod tests { let copied_array_size = context.allocate_register(); + let mut block = create_brillig_block(&mut function_context, &mut context); + if pop_back { - slice_pop_back_operation( - &mut context, + block.slice_pop_back_operation( HeapVector { pointer: copied_array_pointer, size: copied_array_size }, HeapVector { pointer: array_pointer, size: array_size }, - removed_item, + &[RegisterOrMemory::RegisterIndex(removed_item)], ); } else { - slice_pop_front_operation( - &mut context, + block.slice_pop_front_operation( HeapVector { pointer: copied_array_pointer, size: copied_array_size }, HeapVector { pointer: array_pointer, size: array_size }, - removed_item, + &[RegisterOrMemory::RegisterIndex(removed_item)], ); } @@ -434,7 +546,7 @@ mod tests { BrilligParameter::Simple, ]; - let mut context = create_context(); + let (mut function_context, mut context) = create_test_environment(); // Allocate the parameters let array_pointer = context.allocate_register(); @@ -449,12 +561,13 @@ mod tests { let copied_array_size = context.allocate_register(); - slice_insert_operation( - &mut context, + let mut block = create_brillig_block(&mut function_context, &mut context); + + block.slice_insert_operation( HeapVector { pointer: copied_array_pointer, size: copied_array_size }, HeapVector { pointer: array_pointer, size: array_size }, index_to_insert, - item_to_insert, + &[RegisterOrMemory::RegisterIndex(item_to_insert)], ); context.return_instruction(&[copied_array_pointer, copied_array_size]); @@ -556,7 +669,7 @@ mod tests { BrilligParameter::Simple, ]; - let mut context = create_context(); + let (mut function_context, mut context) = create_test_environment(); // Allocate the parameters let array_pointer = context.allocate_register(); @@ -571,12 +684,13 @@ mod tests { let copied_array_size = context.allocate_register(); - slice_remove_operation( - &mut context, + let mut block = create_brillig_block(&mut function_context, &mut context); + + block.slice_remove_operation( HeapVector { pointer: copied_array_pointer, size: copied_array_size }, HeapVector { pointer: array_pointer, size: array_size }, index_to_insert, - removed_item, + &[RegisterOrMemory::RegisterIndex(removed_item)], ); context.return_instruction(&[copied_array_pointer, copied_array_size, removed_item]); From 4b49b5606b4567d696fe1e36a6294f54edd2bc70 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 28 Jul 2023 14:44:20 +0000 Subject: [PATCH 13/19] fix: insert and remove indexes --- .../brillig_nested_slices/Nargo.toml | 6 ++ .../brillig_nested_slices/Prover.toml | 2 + .../brillig_nested_slices/src/main.nr | 59 ++++++++++++++++++ .../brillig_nested_slices/target/main.json | 1 + .../brillig_nested_slices/target/witness.tr | Bin 0 -> 51 bytes .../brillig_slices/src/main.nr | 38 ----------- .../src/brillig/brillig_gen/brillig_block.rs | 51 ++++++++++++--- 7 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Nargo.toml create mode 100644 crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Prover.toml create mode 100644 crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/src/main.nr create mode 100644 crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/main.json create mode 100644 crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/witness.tr diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Nargo.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Nargo.toml new file mode 100644 index 00000000000..3bf54c7d667 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_slices" +authors = [""] +compiler_version = "0.6.0" + +[dependencies] diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Prover.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Prover.toml new file mode 100644 index 00000000000..c52564de922 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/Prover.toml @@ -0,0 +1,2 @@ +a = "5" +b = "10" diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/src/main.nr new file mode 100644 index 00000000000..44b499d7b1c --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/src/main.nr @@ -0,0 +1,59 @@ +use dep::std::slice; +use dep::std; + +// Tests nested slice passing to/from functions +unconstrained fn push_back_to_slice(slice: [T], item: T) -> [T] { + slice.push_back(item) +} + +struct NestedSliceStruct { + id: Field, + arr: [Field] +} + +unconstrained fn create_foo(id: Field, value: Field) -> NestedSliceStruct { + let mut arr = [id]; + arr = arr.push_back(value); + NestedSliceStruct { id, arr } +} + +unconstrained fn main(a: Field, b: Field) { + let mut slice = [create_foo(a, b), create_foo(b, a)]; + assert(slice.len() == 2); + + assert(slice[0].id == a); + assert(slice[0].arr[0] == a); + assert(slice[1].id == b); + assert(slice[1].arr[1] == a); + + slice = push_back_to_slice(slice, create_foo(0, 42)); + assert(slice.len() == 3); + + assert(slice[0].id == a); + assert(slice[0].arr[0] == a); + assert(slice[1].id == b); + assert(slice[1].arr[1] == a); + + assert(slice[2].id == 0); + assert(slice[2].arr[0] == 0); + assert(slice[2].arr[1] == 42); + + let mut remove_result = slice.remove(0); + slice = remove_result.0; + let mut removed_item = remove_result.1; + assert(removed_item.arr[0] == a); + + remove_result = slice.remove(1); + slice = remove_result.0; + removed_item = remove_result.1; + assert(removed_item.arr[0] == 0); + + let last_item = slice[0]; + + assert(last_item.id == b); + slice = slice.insert(1, removed_item); + + assert(slice.len() == 2); + assert(slice[0].id == b); + assert(slice[1].id == 0); +} diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/main.json b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/main.json new file mode 100644 index 00000000000..977dbeb44f3 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/main.json @@ -0,0 +1 @@ +{"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[1],"y":[2]},"return_type":null,"return_witnesses":[]},"bytecode":"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","proving_key":null,"verification_key":null} \ No newline at end of file diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/witness.tr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_nested_slices/target/witness.tr new file mode 100644 index 0000000000000000000000000000000000000000..3530c6f59c11241b06d274764b06781543549d49 GIT binary patch literal 51 zcmb2|=3oE;rvGbuHgYmBa2(zuzH`U#uK)H67szjEbXazPFaEW)h0v~W{@*>D+!g?p F0s!8X6UYDn literal 0 HcmV?d00001 diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr index 4f4d90ab168..2d871bc4b2f 100644 --- a/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/brillig_slices/src/main.nr @@ -68,47 +68,9 @@ unconstrained fn main(x: Field, y: Field) { let (empty_slice, should_be_x) = slice.remove(0); assert(should_be_x == x); assert(empty_slice.len() == 0); - - test_nested(x,y); } // Tests slice passing to/from functions unconstrained fn push_front_to_slice(slice: [T], item: T) -> [T] { slice.push_front(item) } - -struct Foo { - x: Field, - y: Field, - arr: [Field] -} - -unconstrained fn create_foo(x: Field, y: Field) -> Foo { - let mut arr = [x]; - arr = arr.push_back(y); - Foo { arr: arr, x, y } -} - -unconstrained fn test_nested(x: Field, y: Field) { - let mut slice = [create_foo(x,y), create_foo(y, x)]; - assert(slice.len() == 2); - - assert(slice[0].y == y); - assert(slice[0].arr[0] == x); - assert(slice[1].x == y); - assert(slice[1].arr[1] == x); - - slice = slice.push_back(create_foo(7,8)); - assert(slice.len() == 3); - - assert(slice[0].x == x); - assert(slice[0].arr[1] == y); - - assert(slice[1].y == x); - assert(slice[1].arr[0] == y); - - assert(slice[2].x == 7); - assert(slice[2].y == 8); - assert(slice[2].arr[0] == 7); - assert(slice[2].arr[1] == 8); -} diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 589b3d7da08..45d6d7d7c80 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -659,31 +659,64 @@ impl<'block> BrilligBlock<'block> { } Value::Intrinsic(Intrinsic::SliceInsert) => { let results = dfg.instruction_results(instruction_id); - let index = self.convert_ssa_register_value(arguments[1], dfg); + let target_id = results[0]; + let target_variable = + self.function_context.create_variable(self.brillig_context, target_id, dfg); + + let target_vector = self.function_context.extract_heap_vector(target_variable); + + let user_index = self.convert_ssa_register_value(arguments[1], dfg); + + let converted_index = self + .brillig_context + .make_constant(self.get_ssa_item_size(target_id, dfg).into()); + + self.brillig_context.memory_op( + converted_index, + user_index, + converted_index, + BinaryIntOp::Mul, + ); let items = vecmap(&arguments[2..subitem_count + 2], |arg| { self.convert_ssa_value(*arg, dfg) }); - let target_variable = - self.function_context.create_variable(self.brillig_context, results[0], dfg); - - let target_vector = self.function_context.extract_heap_vector(target_variable); - self.slice_insert_operation(target_vector, source_vector, index, &items); + self.slice_insert_operation(target_vector, source_vector, converted_index, &items); + self.brillig_context.deallocate_register(converted_index); } Value::Intrinsic(Intrinsic::SliceRemove) => { let results = dfg.instruction_results(instruction_id); - let index = self.convert_ssa_register_value(arguments[1], dfg); + let target_id = results[0]; let target_variable = - self.function_context.create_variable(self.brillig_context, results[0], dfg); + self.function_context.create_variable(self.brillig_context, target_id, dfg); let target_vector = self.function_context.extract_heap_vector(target_variable); + let user_index = self.convert_ssa_register_value(arguments[1], dfg); + + let converted_index = self + .brillig_context + .make_constant(self.get_ssa_item_size(target_id, dfg).into()); + self.brillig_context.memory_op( + converted_index, + user_index, + converted_index, + BinaryIntOp::Mul, + ); + let removed_items = vecmap(&results[1..subitem_count + 1], |result| { self.function_context.create_variable(self.brillig_context, *result, dfg) }); - self.slice_remove_operation(target_vector, source_vector, index, &removed_items); + self.slice_remove_operation( + target_vector, + source_vector, + converted_index, + &removed_items, + ); + + self.brillig_context.deallocate_register(converted_index); } _ => unreachable!("ICE: Slice operation not supported"), } From 742a55dd27043099d222cdeab84973abcd02bafe Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 28 Jul 2023 15:47:53 +0000 Subject: [PATCH 14/19] fix: add missing deallocation --- .../noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs | 5 +++++ .../src/brillig/brillig_gen/brillig_slice_ops.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 45d6d7d7c80..a185f2c697c 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -665,6 +665,7 @@ impl<'block> BrilligBlock<'block> { let target_vector = self.function_context.extract_heap_vector(target_variable); + // TODO: Remove after https://github.com/noir-lang/noir/issues/2083 is fixed let user_index = self.convert_ssa_register_value(arguments[1], dfg); let converted_index = self @@ -693,6 +694,7 @@ impl<'block> BrilligBlock<'block> { self.function_context.create_variable(self.brillig_context, target_id, dfg); let target_vector = self.function_context.extract_heap_vector(target_variable); + // TODO: Remove after https://github.com/noir-lang/noir/issues/2083 is fixed let user_index = self.convert_ssa_register_value(arguments[1], dfg); let converted_index = self @@ -919,6 +921,9 @@ impl<'block> BrilligBlock<'block> { } } + /// Gets the number of subitems an array item has. + /// This allows operations like returning the user-defined length of an array where every item has multiple fields. + /// Such as an array/slice of structs. fn get_ssa_item_size(&self, array_id: ValueId, dfg: &DataFlowGraph) -> usize { let array_type = dfg[array_id].get_type(); match array_type { diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 622a7b9f8d0..d1fc5eea2ba 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -150,6 +150,7 @@ impl<'block> BrilligBlock<'block> { BinaryIntOp::Add, ); self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); + self.brillig_context.deallocate_register(target_index); } } From be7674c7acbd0364e43136537f584eab4cf63661 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 7 Aug 2023 09:41:43 +0000 Subject: [PATCH 15/19] test: added more cases to nested slice test --- .../test_data/brillig_nested_slices/src/main.nr | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/nargo_cli/tests/test_data/brillig_nested_slices/src/main.nr b/crates/nargo_cli/tests/test_data/brillig_nested_slices/src/main.nr index 44b499d7b1c..f239d94fdc1 100644 --- a/crates/nargo_cli/tests/test_data/brillig_nested_slices/src/main.nr +++ b/crates/nargo_cli/tests/test_data/brillig_nested_slices/src/main.nr @@ -38,6 +38,21 @@ unconstrained fn main(a: Field, b: Field) { assert(slice[2].arr[0] == 0); assert(slice[2].arr[1] == 42); + slice = slice.push_front(create_foo(1, 43)); + slice = slice.push_back(create_foo(2, 44)); + + assert(slice.len() == 5); + + let pop_front_result = slice.pop_front(); + slice = pop_front_result.1; + assert(pop_front_result.0.id == 1); + + let pop_back_result = slice.pop_back(); + slice = pop_back_result.0; + assert(pop_back_result.1.id == 2); + + assert(slice.len() == 3); + let mut remove_result = slice.remove(0); slice = remove_result.0; let mut removed_item = remove_result.1; From 00b54384f3055bbe74b68834ebfb73db0fcc6303 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 7 Aug 2023 09:54:25 +0000 Subject: [PATCH 16/19] refactor: simplify array length instructions --- .../src/brillig/brillig_gen/brillig_block.rs | 43 +++++++++++++------ .../noirc_evaluator/src/brillig/brillig_ir.rs | 18 -------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 4d17a726fa7..cf0105ffa5d 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -304,18 +304,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let param_id = arguments[0]; - let param_variable = self.convert_ssa_value(param_id, dfg); - - self.brillig_context - .length_of_variable_instruction(param_variable, result_register); - - let item_size = self.get_ssa_item_size(param_id, dfg); - - self.brillig_context.usize_op_in_place( - result_register, - BinaryIntOp::UnsignedDiv, - item_size, - ); + self.convert_ssa_array_len(param_id, result_register, dfg); } Value::Intrinsic( Intrinsic::SlicePushBack @@ -936,6 +925,36 @@ impl<'block> BrilligBlock<'block> { } } } + + /// Gets the "user-facing" length of an array. + /// An array of structs with two fields would be stored as an 2 * array.len() heap array/heap vector. + /// So we divide the length by the number of subitems in an item to get the user-facing length. + fn convert_ssa_array_len( + &mut self, + array_id: ValueId, + result_register: RegisterIndex, + dfg: &DataFlowGraph, + ) { + let array_variable = self.convert_ssa_value(array_id, dfg); + let item_size = self.get_ssa_item_size(array_id, dfg); + + match array_variable { + RegisterOrMemory::HeapArray(HeapArray { size, .. }) => { + self.brillig_context.const_instruction(result_register, (size / item_size).into()); + } + RegisterOrMemory::HeapVector(HeapVector { size, .. }) => { + self.brillig_context.usize_op( + size, + result_register, + BinaryIntOp::UnsignedDiv, + item_size, + ); + } + _ => { + unreachable!("ICE: Cannot get length of {array_variable:?}") + } + } + } } /// Returns the type of the operation considering the types of the operands diff --git a/crates/noirc_evaluator/src/brillig/brillig_ir.rs b/crates/noirc_evaluator/src/brillig/brillig_ir.rs index 4471d507579..047e8b7edf8 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_ir.rs @@ -548,24 +548,6 @@ impl BrilligContext { self.push_opcode(BrilligOpcode::Store { destination_pointer, source }); } - pub(crate) fn length_of_variable_instruction( - &mut self, - variable: RegisterOrMemory, - result: RegisterIndex, - ) { - match variable { - RegisterOrMemory::RegisterIndex(_) => { - self.const_instruction(result, 1_u128.into()); - } - RegisterOrMemory::HeapArray(HeapArray { size, .. }) => { - self.const_instruction(result, size.into()); - } - RegisterOrMemory::HeapVector(HeapVector { size, .. }) => { - self.mov_instruction(result, size); - } - } - } - /// Stores a variable by saving its registers to memory pub(crate) fn store_variable_instruction( &mut self, From 0cbe9ce77ee921569ed30a2977a3f0ef4519a3c8 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 7 Aug 2023 10:14:10 +0000 Subject: [PATCH 17/19] test: fix stale import --- .../src/brillig/brillig_gen/brillig_slice_ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index d1fc5eea2ba..facc4766722 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -322,7 +322,7 @@ mod tests { use crate::brillig::brillig_ir::artifact::BrilligParameter; use crate::brillig::brillig_ir::tests::{create_and_run_vm, create_context}; use crate::brillig::brillig_ir::BrilligContext; - use crate::ssa_refactor::ir::map::Id; + use crate::ssa::ir::map::Id; fn create_test_environment() -> (FunctionContext, BrilligContext) { let function_context = FunctionContext { From 2bdda12f4acd44d62e5b7c56daad702fddd4afb4 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 7 Aug 2023 15:07:37 +0000 Subject: [PATCH 18/19] refactor: reuse element_size and regen json --- .../target/brillig_nested_slices.json | 1 + .../brillig_nested_slices/target/main.json | 1 - .../src/brillig/brillig_gen/brillig_block.rs | 53 +++++++------------ 3 files changed, 19 insertions(+), 36 deletions(-) create mode 100644 crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/brillig_nested_slices.json delete mode 100644 crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/main.json diff --git a/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/brillig_nested_slices.json b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/brillig_nested_slices.json new file mode 100644 index 00000000000..c39fa017efa --- /dev/null +++ b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/brillig_nested_slices.json @@ -0,0 +1 @@ +{"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"a","type":{"kind":"field"},"visibility":"private"},{"name":"b","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"a":[1],"b":[2]},"return_type":null,"return_witnesses":[]},"bytecode":"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","proving_key":null,"verification_key":null} \ No newline at end of file diff --git a/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/main.json b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/main.json deleted file mode 100644 index 977dbeb44f3..00000000000 --- a/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/main.json +++ /dev/null @@ -1 +0,0 @@ -{"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[1],"y":[2]},"return_type":null,"return_witnesses":[]},"bytecode":"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","proving_key":null,"verification_key":null} \ No newline at end of file diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index cf0105ffa5d..abad61407db 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -588,7 +588,7 @@ impl<'block> BrilligBlock<'block> { arguments: &[ValueId], ) { let slice_id = arguments[0]; - let subitem_count = self.get_ssa_item_size(slice_id, dfg); + let element_size = dfg.type_of_value(slice_id).element_size(); let source_variable = self.convert_ssa_value(slice_id, dfg); let source_vector = self.convert_array_or_vector_to_vector(source_variable); @@ -600,7 +600,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let target_vector = self.brillig_context.extract_heap_vector(target_variable); - let item_values = vecmap(&arguments[1..subitem_count + 1], |arg| { + let item_values = vecmap(&arguments[1..element_size + 1], |arg| { self.convert_ssa_value(*arg, dfg) }); self.slice_push_back_operation(target_vector, source_vector, &item_values); @@ -612,7 +612,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let target_vector = self.brillig_context.extract_heap_vector(target_variable); - let item_values = vecmap(&arguments[1..subitem_count + 1], |arg| { + let item_values = vecmap(&arguments[1..element_size + 1], |arg| { self.convert_ssa_value(*arg, dfg) }); self.slice_push_front_operation(target_vector, source_vector, &item_values); @@ -625,7 +625,7 @@ impl<'block> BrilligBlock<'block> { let target_vector = self.brillig_context.extract_heap_vector(target_variable); - let pop_variables = vecmap(&results[1..subitem_count + 1], |result| { + let pop_variables = vecmap(&results[1..element_size + 1], |result| { self.function_context.create_variable(self.brillig_context, *result, dfg) }); @@ -634,13 +634,13 @@ impl<'block> BrilligBlock<'block> { Value::Intrinsic(Intrinsic::SlicePopFront) => { let results = dfg.instruction_results(instruction_id); - let pop_variables = vecmap(&results[0..subitem_count], |result| { + let pop_variables = vecmap(&results[0..element_size], |result| { self.function_context.create_variable(self.brillig_context, *result, dfg) }); let target_variable = self.function_context.create_variable( self.brillig_context, - results[subitem_count], + results[element_size], dfg, ); let target_vector = self.brillig_context.extract_heap_vector(target_variable); @@ -655,12 +655,11 @@ impl<'block> BrilligBlock<'block> { let target_vector = self.brillig_context.extract_heap_vector(target_variable); - // TODO: Remove after https://github.com/noir-lang/noir/issues/2083 is fixed + // Remove if indexing in insert is changed to flattened indexing + // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 let user_index = self.convert_ssa_register_value(arguments[1], dfg); - let converted_index = self - .brillig_context - .make_constant(self.get_ssa_item_size(target_id, dfg).into()); + let converted_index = self.brillig_context.make_constant(element_size.into()); self.brillig_context.memory_op( converted_index, @@ -669,7 +668,7 @@ impl<'block> BrilligBlock<'block> { BinaryIntOp::Mul, ); - let items = vecmap(&arguments[2..subitem_count + 2], |arg| { + let items = vecmap(&arguments[2..element_size + 2], |arg| { self.convert_ssa_value(*arg, dfg) }); @@ -684,12 +683,11 @@ impl<'block> BrilligBlock<'block> { self.function_context.create_variable(self.brillig_context, target_id, dfg); let target_vector = self.brillig_context.extract_heap_vector(target_variable); - // TODO: Remove after https://github.com/noir-lang/noir/issues/2083 is fixed + // Remove if indexing in insert is changed to flattened indexing + // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 let user_index = self.convert_ssa_register_value(arguments[1], dfg); - let converted_index = self - .brillig_context - .make_constant(self.get_ssa_item_size(target_id, dfg).into()); + let converted_index = self.brillig_context.make_constant(element_size.into()); self.brillig_context.memory_op( converted_index, user_index, @@ -697,7 +695,7 @@ impl<'block> BrilligBlock<'block> { BinaryIntOp::Mul, ); - let removed_items = vecmap(&results[1..subitem_count + 1], |result| { + let removed_items = vecmap(&results[1..element_size + 1], |result| { self.function_context.create_variable(self.brillig_context, *result, dfg) }); @@ -910,22 +908,6 @@ impl<'block> BrilligBlock<'block> { } } - /// Gets the number of subitems an array item has. - /// This allows operations like returning the user-defined length of an array where every item has multiple fields. - /// Such as an array/slice of structs. - fn get_ssa_item_size(&self, array_id: ValueId, dfg: &DataFlowGraph) -> usize { - let array_type = dfg[array_id].get_type(); - match array_type { - Type::Array(item_types, _) | Type::Slice(item_types) => { - // To match SSA indexes, all subitems are stored as one single value - item_types.len() - } - _ => { - unreachable!("ICE: Cannot get item size of {array_type:?}") - } - } - } - /// Gets the "user-facing" length of an array. /// An array of structs with two fields would be stored as an 2 * array.len() heap array/heap vector. /// So we divide the length by the number of subitems in an item to get the user-facing length. @@ -936,18 +918,19 @@ impl<'block> BrilligBlock<'block> { dfg: &DataFlowGraph, ) { let array_variable = self.convert_ssa_value(array_id, dfg); - let item_size = self.get_ssa_item_size(array_id, dfg); + let element_size = dfg.type_of_value(array_id).element_size(); match array_variable { RegisterOrMemory::HeapArray(HeapArray { size, .. }) => { - self.brillig_context.const_instruction(result_register, (size / item_size).into()); + self.brillig_context + .const_instruction(result_register, (size / element_size).into()); } RegisterOrMemory::HeapVector(HeapVector { size, .. }) => { self.brillig_context.usize_op( size, result_register, BinaryIntOp::UnsignedDiv, - item_size, + element_size, ); } _ => { From d1c9f270d84c49bc1c067720a3606dadb13e84b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Mon, 7 Aug 2023 17:09:25 +0200 Subject: [PATCH 19/19] Update crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs --- crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index abad61407db..6af911e718f 100644 --- a/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -683,7 +683,7 @@ impl<'block> BrilligBlock<'block> { self.function_context.create_variable(self.brillig_context, target_id, dfg); let target_vector = self.brillig_context.extract_heap_vector(target_variable); - // Remove if indexing in insert is changed to flattened indexing + // Remove if indexing in remove is changed to flattened indexing // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 let user_index = self.convert_ssa_register_value(arguments[1], dfg);