diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 15d72c2ae74..b560fafd337 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1303,6 +1303,29 @@ impl<'a> Context<'a> { } } + /// Returns the acir value at the provided databus offset + fn get_from_call_data( + &mut self, + offset: &mut AcirVar, + call_data_block: BlockId, + typ: &Type, + ) -> Result { + match typ { + Type::Numeric(_) => self.array_get_value(&Type::field(), call_data_block, offset), + Type::Array(arc, len) => { + let mut result = Vector::new(); + for _i in 0..*len { + for sub_type in arc.iter() { + let element = self.get_from_call_data(offset, call_data_block, sub_type)?; + result.push_back(element); + } + } + Ok(AcirValue::Array(result)) + } + _ => unimplemented!("Unsupported type in databus"), + } + } + /// Generates a read opcode for the array /// `index_side_effect == false` means that we ensured `var_index` will have a type matching the value in the array fn array_get( @@ -1316,27 +1339,19 @@ impl<'a> Context<'a> { let block_id = self.ensure_array_is_initialized(array, dfg)?; let results = dfg.instruction_results(instruction); let res_typ = dfg.type_of_value(results[0]); - // Get operations to call-data parameters are replaced by a get to the call-data-bus array - if let Some(call_data) = - self.data_bus.call_data.iter().find(|cd| cd.index_map.contains_key(&array)) - { - let type_size = res_typ.flattened_size(); - let type_size = self.acir_context.add_constant(FieldElement::from(type_size as i128)); - let offset = self.acir_context.mul_var(var_index, type_size)?; + let call_data = + self.data_bus.call_data.iter().find(|cd| cd.index_map.contains_key(&array)).cloned(); + if let Some(call_data) = call_data { + let call_data_block = self.ensure_array_is_initialized(call_data.array_id, dfg)?; let bus_index = self .acir_context .add_constant(FieldElement::from(call_data.index_map[&array] as i128)); - let new_index = self.acir_context.add_var(offset, bus_index)?; - return self.array_get( - instruction, - call_data.array_id, - new_index, - dfg, - index_side_effect, - ); + let mut current_index = self.acir_context.add_var(bus_index, var_index)?; + let result = self.get_from_call_data(&mut current_index, call_data_block, &res_typ)?; + self.define_result(dfg, instruction, result.clone()); + return Ok(result); } - // Compiler sanity check assert!( !res_typ.contains_slice_element(), diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index 61dfa096fce..de9ae8a24d7 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -122,15 +122,21 @@ impl FunctionBuilder { } Type::Array(typ, len) => { databus.map.insert(value, databus.index); - for i in 0..len { - for (subitem_index, subitem_typ) in typ.iter().enumerate() { - let index = i * typ.len() + subitem_index; - // load each element of the array - let index = self + + let mut index = 0; + for _i in 0..len { + for subitem_typ in typ.iter() { + // load each element of the array, and add it to the databus + let index_var = self .current_function .dfg .make_constant(FieldElement::from(index as i128), Type::length_type()); - let element = self.insert_array_get(value, index, subitem_typ.clone()); + let element = self.insert_array_get(value, index_var, subitem_typ.clone()); + index += match subitem_typ { + Type::Array(_, _) | Type::Slice(_) => subitem_typ.element_size(), + Type::Numeric(_) => 1, + _ => unreachable!("Unsupported type for databus"), + }; self.add_to_data_bus(element, databus); } } diff --git a/test_programs/execution_success/databus_composite_calldata/Prover.toml b/test_programs/execution_success/databus_composite_calldata/Prover.toml index ff173cc70cd..ab154c13372 100644 --- a/test_programs/execution_success/databus_composite_calldata/Prover.toml +++ b/test_programs/execution_success/databus_composite_calldata/Prover.toml @@ -1,9 +1,11 @@ zero = "0" one = "1" +values = [[["12", "33"], ["37", "11"]],[["14", "37"], ["30", "10"]],[["10", "30"], ["30", "10"]]] + [[foos]] -x = "27" -y = "40" +x = 1 +y = [1,2,3,4,5,6,7,8,9,0] [[foos]] -x = "28" -y = "42" +x = 2 +y = [1,2,3,5,6,8,7,8,9,0] \ No newline at end of file diff --git a/test_programs/execution_success/databus_composite_calldata/src/main.nr b/test_programs/execution_success/databus_composite_calldata/src/main.nr index c4da253cbce..e8b88e84d0d 100644 --- a/test_programs/execution_success/databus_composite_calldata/src/main.nr +++ b/test_programs/execution_success/databus_composite_calldata/src/main.nr @@ -1,11 +1,16 @@ struct Foo { x: u32, - y: u32, + y: [u32; 10], } -fn main(foos: call_data(0) [Foo; 2], zero: u32, one: u32) -> return_data u32 { +fn main( + foos: call_data(0) [Foo; 2], + values: call_data(0) [[[u32; 2]; 2]; 3], + zero: u32, + one: u32 +) -> pub u32 { assert_eq(foos[zero].x + 1, foos[one].x); - assert_eq(foos[zero].y + 2, foos[one].y); - foos[zero].x + foos[one].y + assert_eq(foos[zero].y[3] + 2, foos[one].y[4]); + assert_eq(values[zero][one][zero], values[one][zero][one]); + foos[zero].x + foos[one].y[0] } -