diff --git a/crates/nargo_cli/tests/test_data/array_dynamic/Prover.toml b/crates/nargo_cli/tests/test_data/array_dynamic/Prover.toml index 1e652e28d1c..ff6f02ccdac 100644 --- a/crates/nargo_cli/tests/test_data/array_dynamic/Prover.toml +++ b/crates/nargo_cli/tests/test_data/array_dynamic/Prover.toml @@ -1,5 +1,6 @@ x = [104, 101, 108, 108, 111] z = "59" t = "10" +index = [0,1,2,3,4] diff --git a/crates/nargo_cli/tests/test_data/array_dynamic/src/main.nr b/crates/nargo_cli/tests/test_data/array_dynamic/src/main.nr index 23041188724..a4073fd55cb 100644 --- a/crates/nargo_cli/tests/test_data/array_dynamic/src/main.nr +++ b/crates/nargo_cli/tests/test_data/array_dynamic/src/main.nr @@ -1,8 +1,16 @@ -fn main(x: [u32; 5], mut z: u32, t: u32) { +fn main(x: [u32; 5], mut z: u32, t: u32, index: [Field;5]) { let idx = (z - 5*t - 5) as Field; //dynamic array test dyn_array(x, idx, idx - 3); + + // regression for issue 1283 + let mut s = 0; + let x3 = [246,159,32,176,8]; + for i in 0..5 { + s += x3[index[i]]; + } + assert(s!=0); } fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { diff --git a/crates/noirc_evaluator/src/ssa/acir_gen.rs b/crates/noirc_evaluator/src/ssa/acir_gen.rs index b964672e285..22b5390e2fa 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen.rs @@ -46,7 +46,7 @@ impl Acir { //TODO we should rather follow the jumps current_block = block.left.map(|block_id| &ctx[block_id]); } - self.memory.acir_gen(evaluator); + self.memory.acir_gen(evaluator, ctx); Ok(()) } diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/acir_mem.rs b/crates/noirc_evaluator/src/ssa/acir_gen/acir_mem.rs index 0c55f61ca20..ac3395d9411 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/acir_mem.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/acir_mem.rs @@ -8,7 +8,10 @@ use crate::{ }; use acvm::{ acir::{ - circuit::{directives::Directive, opcodes::Opcode as AcirOpcode}, + circuit::{ + directives::Directive, + opcodes::{BlockId as AcirBlockId, MemOp, MemoryBlock, Opcode as AcirOpcode}, + }, native_types::{Expression, Witness}, }, FieldElement, @@ -22,15 +25,6 @@ use super::{ operations::{self}, }; -/// Represent a memory operation on the ArrayHeap, at the specified index -/// Operation is one for a store and 0 for a load -#[derive(Clone, Debug)] -pub(crate) struct MemOp { - operation: Expression, - value: Expression, - index: Expression, -} - type MemAddress = u32; enum ArrayType { @@ -137,7 +131,7 @@ impl ArrayHeap { outputs } - pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator) { + pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator, array_id: ArrayId, array_len: u32) { let (len, read_write) = match self.typ { ArrayType::Init(_, _) | ArrayType::WriteOnly => (0, true), ArrayType::ReadOnly(last) => (last.unwrap_or(self.trace.len()), false), @@ -147,6 +141,11 @@ impl ArrayHeap { if len == 0 { return; } + evaluator.opcodes.push(AcirOpcode::Block(MemoryBlock { + id: AcirBlockId(array_id.as_u32()), + len: array_len, + trace: self.trace.clone(), + })); let len_bits = AcirMem::bits(len); // permutations let mut in_counter = Vec::new(); @@ -318,9 +317,10 @@ impl AcirMem { let item = MemOp { operation: op, value, index }; self.array_heap_mut(*array_id).push(item); } - pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator) { + pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator, ctx: &SsaContext) { for mem in &self.virtual_memory { - mem.1.acir_gen(evaluator); + let array = &ctx.mem[*mem.0]; + mem.1.acir_gen(evaluator, array.id, array.len); } } } diff --git a/crates/noirc_evaluator/src/ssa/mem.rs b/crates/noirc_evaluator/src/ssa/mem.rs index e4a82a7e59c..09fdc33b704 100644 --- a/crates/noirc_evaluator/src/ssa/mem.rs +++ b/crates/noirc_evaluator/src/ssa/mem.rs @@ -23,6 +23,10 @@ impl ArrayId { pub(crate) fn dummy() -> ArrayId { ArrayId(std::u32::MAX) } + + pub(crate) fn as_u32(&self) -> u32 { + self.0 + } } /// MemArray represents a contiguous array of elements of the same type.