diff --git a/crates/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml new file mode 100644 index 00000000000..3a558b737d8 --- /dev/null +++ b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_nested_slices" +type = "bin" +authors = [""] +compiler_version = "0.6.0" + +[dependencies] diff --git a/crates/nargo_cli/tests/execution_success/brillig_nested_slices/Prover.toml b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/Prover.toml new file mode 100644 index 00000000000..c52564de922 --- /dev/null +++ b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/Prover.toml @@ -0,0 +1,2 @@ +a = "5" +b = "10" diff --git a/crates/nargo_cli/tests/execution_success/brillig_nested_slices/src/main.nr b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/src/main.nr new file mode 100644 index 00000000000..f239d94fdc1 --- /dev/null +++ b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/src/main.nr @@ -0,0 +1,74 @@ +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); + + 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; + 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/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/witness.tr b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/witness.tr new file mode 100644 index 00000000000..3530c6f59c1 Binary files /dev/null and b/crates/nargo_cli/tests/execution_success/brillig_nested_slices/target/witness.tr differ diff --git a/crates/nargo_cli/tests/execution_success/brillig_slices/src/main.nr b/crates/nargo_cli/tests/execution_success/brillig_slices/src/main.nr index 34a9afcd515..2d871bc4b2f 100644 --- a/crates/nargo_cli/tests/execution_success/brillig_slices/src/main.nr +++ b/crates/nargo_cli/tests/execution_success/brillig_slices/src/main.nr @@ -73,4 +73,4 @@ unconstrained fn main(x: Field, y: Field) { // 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 5e66519e4ad..6af911e718f 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, }; @@ -21,18 +18,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> { @@ -310,8 +303,8 @@ 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]; + self.convert_ssa_array_len(param_id, result_register, dfg); } Value::Intrinsic( Intrinsic::SlicePushBack @@ -409,7 +402,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); @@ -484,7 +481,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, @@ -497,7 +494,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); + } } } @@ -552,7 +555,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, @@ -566,7 +569,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); } } } @@ -579,9 +587,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 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); match intrinsic { Value::Intrinsic(Intrinsic::SlicePushBack) => { @@ -591,13 +600,10 @@ impl<'block> BrilligBlock<'block> { dfg, ); let target_vector = self.brillig_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..element_size + 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( @@ -606,90 +612,101 @@ impl<'block> BrilligBlock<'block> { dfg, ); let target_vector = self.brillig_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..element_size + 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.brillig_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..element_size + 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..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[0], + results[element_size], dfg, ); - let target_variable = - self.function_context.create_variable(self.brillig_context, results[1], dfg); let target_vector = self.brillig_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 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.brillig_context.extract_heap_vector(target_variable); - slice_insert_operation( - self.brillig_context, - target_vector, - source_vector, - index, - item, + + // 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(element_size.into()); + + self.brillig_context.memory_op( + converted_index, + user_index, + converted_index, + BinaryIntOp::Mul, ); + + let items = vecmap(&arguments[2..element_size + 2], |arg| { + self.convert_ssa_value(*arg, dfg) + }); + + 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.brillig_context.extract_heap_vector(target_variable); - let removed_item_register = self.function_context.create_register_variable( - self.brillig_context, - results[1], - dfg, + // 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); + + let converted_index = self.brillig_context.make_constant(element_size.into()); + self.brillig_context.memory_op( + converted_index, + user_index, + converted_index, + BinaryIntOp::Mul, ); - slice_remove_operation( - self.brillig_context, + let removed_items = vecmap(&results[1..element_size + 1], |result| { + self.function_context.create_variable(self.brillig_context, *result, dfg) + }); + + self.slice_remove_operation( target_vector, source_vector, - index, - removed_item_register, + converted_index, + &removed_items, ); + + self.brillig_context.deallocate_register(converted_index); } _ => unreachable!("ICE: Slice operation not supported"), } @@ -890,6 +907,37 @@ 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 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 / element_size).into()); + } + RegisterOrMemory::HeapVector(HeapVector { size, .. }) => { + self.brillig_context.usize_op( + size, + result_register, + BinaryIntOp::UnsignedDiv, + element_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_gen/brillig_slice_ops.rs b/crates/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 99af5c2b13b..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 @@ -1,231 +1,344 @@ 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); + self.brillig_context.deallocate_register(target_index); + } + } + + 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::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 +357,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 +370,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 +450,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 +464,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 +547,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 +562,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 +670,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 +685,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]); 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,