1use acir::{
15 AcirField,
16 brillig::{BitSize, IntegerBitSize, MemoryAddress},
17};
18
19use crate::assert_usize;
20
21pub const MEMORY_ADDRESSING_BIT_SIZE: IntegerBitSize = IntegerBitSize::U32;
25
26pub const MAX_MEMORY_SIZE: usize = i32::MAX as usize;
35
36pub const STACK_POINTER_ADDRESS: MemoryAddress = MemoryAddress::Direct(0);
40
41pub const FREE_MEMORY_POINTER_ADDRESS: MemoryAddress = MemoryAddress::Direct(1);
48
49pub mod offsets {
53 pub const ARRAY_META_COUNT: u32 = 1;
55 pub const ARRAY_ITEMS: u32 = 1;
56
57 pub const VECTOR_META_COUNT: u32 = 3;
59 pub const VECTOR_SIZE: u32 = 1;
60 pub const VECTOR_CAPACITY: u32 = 2;
61 pub const VECTOR_ITEMS: u32 = 3;
62}
63
64pub(crate) struct ArrayAddress(MemoryAddress);
69
70impl ArrayAddress {
71 pub(crate) fn items_start(&self) -> MemoryAddress {
73 self.0.offset(offsets::ARRAY_ITEMS)
74 }
75}
76
77impl From<MemoryAddress> for ArrayAddress {
78 fn from(value: MemoryAddress) -> Self {
79 Self(value)
80 }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
89pub enum MemoryValue<F> {
90 Field(F),
91 U1(bool),
92 U8(u8),
93 U16(u16),
94 U32(u32),
95 U64(u64),
96 U128(u128),
97}
98
99#[derive(Debug, thiserror::Error)]
101pub enum MemoryTypeError {
102 #[error(
104 "Bit size for value {value_bit_size} does not match the expected bit size {expected_bit_size}"
105 )]
106 MismatchedBitSize { value_bit_size: u32, expected_bit_size: u32 },
107 #[error("Value is not an integer")]
110 NotAnInteger,
111}
112
113impl<F: std::fmt::Display> MemoryValue<F> {
114 pub fn new_field(value: F) -> Self {
116 MemoryValue::Field(value)
117 }
118
119 pub fn new_integer(value: u128, bit_size: IntegerBitSize) -> Self {
121 match bit_size {
122 IntegerBitSize::U1 => MemoryValue::U1(match value {
123 0 => false,
124 1 => true,
125 _ => panic!("{value} is out of 1 bit range"),
126 }),
127 IntegerBitSize::U8 => {
128 MemoryValue::U8(value.try_into().expect("{value} is out of 8 bits range"))
129 }
130 IntegerBitSize::U16 => {
131 MemoryValue::U16(value.try_into().expect("{value} is out of 16 bits range"))
132 }
133 IntegerBitSize::U32 => {
134 MemoryValue::U32(value.try_into().expect("{value} is out of 32 bits range"))
135 }
136 IntegerBitSize::U64 => {
137 MemoryValue::U64(value.try_into().expect("{value} is out of 64 bits range"))
138 }
139 IntegerBitSize::U128 => MemoryValue::U128(value),
140 }
141 }
142
143 pub fn bit_size(&self) -> BitSize {
144 match self {
145 MemoryValue::Field(_) => BitSize::Field,
146 MemoryValue::U1(_) => BitSize::Integer(IntegerBitSize::U1),
147 MemoryValue::U8(_) => BitSize::Integer(IntegerBitSize::U8),
148 MemoryValue::U16(_) => BitSize::Integer(IntegerBitSize::U16),
149 MemoryValue::U32(_) => BitSize::Integer(IntegerBitSize::U32),
150 MemoryValue::U64(_) => BitSize::Integer(IntegerBitSize::U64),
151 MemoryValue::U128(_) => BitSize::Integer(IntegerBitSize::U128),
152 }
153 }
154
155 pub fn to_u32(&self) -> u32 {
159 match self {
160 MemoryValue::U32(value) => *value,
161 other => panic!("value is not typed as Brillig usize: {other}"),
162 }
163 }
164}
165
166impl<F: AcirField> MemoryValue<F> {
167 pub fn new_from_field(value: F, bit_size: BitSize) -> Self {
171 if let BitSize::Integer(bit_size) = bit_size {
172 MemoryValue::new_integer(value.to_u128(), bit_size)
173 } else {
174 MemoryValue::new_field(value)
175 }
176 }
177
178 pub fn new_checked(value: F, bit_size: BitSize) -> Option<Self> {
181 if let BitSize::Integer(bit_size) = bit_size
182 && value.num_bits() > bit_size.into()
183 {
184 return None;
185 }
186
187 Some(MemoryValue::new_from_field(value, bit_size))
188 }
189
190 pub fn to_field(&self) -> F {
192 match self {
193 MemoryValue::Field(value) => *value,
194 MemoryValue::U1(value) => F::from(*value),
195 MemoryValue::U8(value) => F::from(u128::from(*value)),
196 MemoryValue::U16(value) => F::from(u128::from(*value)),
197 MemoryValue::U32(value) => F::from(u128::from(*value)),
198 MemoryValue::U64(value) => F::from(u128::from(*value)),
199 MemoryValue::U128(value) => F::from(*value),
200 }
201 }
202
203 pub fn to_u128(&self) -> Result<u128, MemoryTypeError> {
205 match self {
206 MemoryValue::Field(..) => Err(MemoryTypeError::NotAnInteger),
207 MemoryValue::U1(value) => Ok(u128::from(*value)),
208 MemoryValue::U8(value) => Ok(u128::from(*value)),
209 MemoryValue::U16(value) => Ok(u128::from(*value)),
210 MemoryValue::U32(value) => Ok(u128::from(*value)),
211 MemoryValue::U64(value) => Ok(u128::from(*value)),
212 MemoryValue::U128(value) => Ok(*value),
213 }
214 }
215
216 pub fn expect_field(self) -> Result<F, MemoryTypeError> {
218 if let MemoryValue::Field(field) = self {
219 Ok(field)
220 } else {
221 Err(MemoryTypeError::MismatchedBitSize {
222 value_bit_size: self.bit_size().to_u32::<F>(),
223 expected_bit_size: F::max_num_bits(),
224 })
225 }
226 }
227 pub(crate) fn expect_u1(self) -> Result<bool, MemoryTypeError> {
228 if let MemoryValue::U1(value) = self {
229 Ok(value)
230 } else {
231 Err(MemoryTypeError::MismatchedBitSize {
232 value_bit_size: self.bit_size().to_u32::<F>(),
233 expected_bit_size: 1,
234 })
235 }
236 }
237
238 pub(crate) fn expect_u8(self) -> Result<u8, MemoryTypeError> {
239 if let MemoryValue::U8(value) = self {
240 Ok(value)
241 } else {
242 Err(MemoryTypeError::MismatchedBitSize {
243 value_bit_size: self.bit_size().to_u32::<F>(),
244 expected_bit_size: 8,
245 })
246 }
247 }
248
249 pub(crate) fn expect_u16(self) -> Result<u16, MemoryTypeError> {
250 if let MemoryValue::U16(value) = self {
251 Ok(value)
252 } else {
253 Err(MemoryTypeError::MismatchedBitSize {
254 value_bit_size: self.bit_size().to_u32::<F>(),
255 expected_bit_size: 16,
256 })
257 }
258 }
259
260 pub(crate) fn expect_u32(self) -> Result<u32, MemoryTypeError> {
261 if let MemoryValue::U32(value) = self {
262 Ok(value)
263 } else {
264 Err(MemoryTypeError::MismatchedBitSize {
265 value_bit_size: self.bit_size().to_u32::<F>(),
266 expected_bit_size: 32,
267 })
268 }
269 }
270
271 pub(crate) fn expect_u64(self) -> Result<u64, MemoryTypeError> {
272 if let MemoryValue::U64(value) = self {
273 Ok(value)
274 } else {
275 Err(MemoryTypeError::MismatchedBitSize {
276 value_bit_size: self.bit_size().to_u32::<F>(),
277 expected_bit_size: 64,
278 })
279 }
280 }
281
282 pub(crate) fn expect_u128(self) -> Result<u128, MemoryTypeError> {
283 if let MemoryValue::U128(value) = self {
284 Ok(value)
285 } else {
286 Err(MemoryTypeError::MismatchedBitSize {
287 value_bit_size: self.bit_size().to_u32::<F>(),
288 expected_bit_size: 128,
289 })
290 }
291 }
292}
293
294impl<F: std::fmt::Display> std::fmt::Display for MemoryValue<F> {
295 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
296 match self {
297 MemoryValue::Field(value) => write!(f, "{value}: field"),
298 MemoryValue::U1(value) => write!(f, "{value}: u1"),
299 MemoryValue::U8(value) => write!(f, "{value}: u8"),
300 MemoryValue::U16(value) => write!(f, "{value}: u16"),
301 MemoryValue::U32(value) => write!(f, "{value}: u32"),
302 MemoryValue::U64(value) => write!(f, "{value}: u64"),
303 MemoryValue::U128(value) => write!(f, "{value}: u128"),
304 }
305 }
306}
307
308impl<F: AcirField> Default for MemoryValue<F> {
309 fn default() -> Self {
310 MemoryValue::new_field(F::zero())
311 }
312}
313
314impl<F: AcirField> From<bool> for MemoryValue<F> {
315 fn from(value: bool) -> Self {
316 MemoryValue::U1(value)
317 }
318}
319
320impl<F: AcirField> From<u8> for MemoryValue<F> {
321 fn from(value: u8) -> Self {
322 MemoryValue::U8(value)
323 }
324}
325
326impl<F: AcirField> From<u32> for MemoryValue<F> {
327 fn from(value: u32) -> Self {
328 MemoryValue::U32(value)
329 }
330}
331
332impl<F: AcirField> From<u64> for MemoryValue<F> {
333 fn from(value: u64) -> Self {
334 MemoryValue::U64(value)
335 }
336}
337
338impl<F: AcirField> From<u128> for MemoryValue<F> {
339 fn from(value: u128) -> Self {
340 MemoryValue::U128(value)
341 }
342}
343
344impl<F: AcirField> TryFrom<MemoryValue<F>> for bool {
345 type Error = MemoryTypeError;
346
347 fn try_from(memory_value: MemoryValue<F>) -> Result<Self, Self::Error> {
348 memory_value.expect_u1()
349 }
350}
351
352impl<F: AcirField> TryFrom<MemoryValue<F>> for u8 {
353 type Error = MemoryTypeError;
354
355 fn try_from(memory_value: MemoryValue<F>) -> Result<Self, Self::Error> {
356 memory_value.expect_u8()
357 }
358}
359
360impl<F: AcirField> TryFrom<MemoryValue<F>> for u32 {
361 type Error = MemoryTypeError;
362
363 fn try_from(memory_value: MemoryValue<F>) -> Result<Self, Self::Error> {
364 memory_value.expect_u32()
365 }
366}
367
368impl<F: AcirField> TryFrom<MemoryValue<F>> for u64 {
369 type Error = MemoryTypeError;
370
371 fn try_from(memory_value: MemoryValue<F>) -> Result<Self, Self::Error> {
372 memory_value.expect_u64()
373 }
374}
375
376impl<F: AcirField> TryFrom<MemoryValue<F>> for u128 {
377 type Error = MemoryTypeError;
378
379 fn try_from(memory_value: MemoryValue<F>) -> Result<Self, Self::Error> {
380 memory_value.expect_u128()
381 }
382}
383#[derive(Debug, Clone, PartialEq, Eq)]
397pub struct Memory<F> {
398 inner: Vec<MemoryValue<F>>,
400 stack_pointer: u32,
409}
410
411impl<F> Default for Memory<F> {
412 fn default() -> Self {
413 Self { inner: Vec::new(), stack_pointer: STACK_POINTER_ADDRESS.to_u32() }
414 }
415}
416
417impl<F: AcirField> Memory<F> {
418 fn resolve(&self, address: MemoryAddress) -> u32 {
424 match address {
425 MemoryAddress::Direct(address) => address,
426 MemoryAddress::Relative(offset) => {
427 self.stack_pointer.checked_add(offset).expect("stack pointer offset overflow")
428 }
429 }
430 }
431
432 pub fn read(&self, address: MemoryAddress) -> MemoryValue<F> {
436 let resolved_addr = assert_usize(self.resolve(address));
437 self.inner.get(resolved_addr).copied().unwrap_or_default()
438 }
439
440 pub fn read_ref(&self, ptr: MemoryAddress) -> MemoryAddress {
443 let resolved = assert_usize(self.resolve(ptr));
444 if resolved >= self.inner.len() {
445 panic!(
446 "read_ref: address {ptr:?} (resolved to {resolved}) is out of bounds (memory size: {})",
447 self.inner.len()
448 );
449 }
450 let value = self.inner[resolved];
451 let MemoryValue::U32(addr) = value else {
452 panic!(
453 "read_ref: expected a U32 pointer at address {ptr:?}, but found {value} ({})",
454 value.bit_size()
455 );
456 };
457 MemoryAddress::direct(addr)
458 }
459
460 pub fn write_ref(&mut self, ptr: MemoryAddress, address: MemoryAddress) {
462 self.write(ptr, MemoryValue::from(address.to_u32()));
463 }
464
465 pub fn read_slice(&self, address: MemoryAddress, len: usize) -> &[MemoryValue<F>] {
469 if len == 0 {
473 return &[];
474 }
475 let resolved_addr = assert_usize(self.resolve(address));
476 let end = resolved_addr.checked_add(len).expect("read_slice: address + len overflows");
477 assert!(
478 end <= self.inner.len(),
479 "read_slice: out of bounds — reading {len} elements from address {resolved_addr} \
480 exceeds memory size {}. Callers should validate sizes before calling read_slice.",
481 self.inner.len()
482 );
483 &self.inner[resolved_addr..end]
484 }
485
486 pub fn write(&mut self, address: MemoryAddress, value: MemoryValue<F>) {
488 let resolved_addr = assert_usize(self.resolve(address));
489 self.resize_to_fit(resolved_addr.saturating_add(1));
491 self.inner[resolved_addr] = value;
492 if address == STACK_POINTER_ADDRESS
493 && let MemoryValue::U32(sp) = value
494 {
495 self.stack_pointer = sp;
496 }
497 }
498
499 fn resize_to_fit(&mut self, size: usize) {
505 assert!(
506 size <= MAX_MEMORY_SIZE,
507 "Memory address space exceeded: requested {size} slots, maximum is {MAX_MEMORY_SIZE} (i32::MAX)"
508 );
509 let new_size = std::cmp::max(self.inner.len(), size);
511 self.inner.resize(new_size, MemoryValue::default());
513 }
514
515 pub fn write_slice(&mut self, address: MemoryAddress, values: &[MemoryValue<F>]) {
517 let resolved_addr = assert_usize(self.resolve(address));
518 let end_addr = resolved_addr + values.len();
519 self.resize_to_fit(end_addr);
520 self.inner[resolved_addr..end_addr].copy_from_slice(values);
521 if address == STACK_POINTER_ADDRESS
522 && let Some(MemoryValue::U32(sp)) = values.first()
523 {
524 self.stack_pointer = *sp;
525 }
526 }
527
528 pub(crate) fn len(&self) -> usize {
530 self.inner.len()
531 }
532
533 pub fn values(&self) -> &[MemoryValue<F>] {
535 &self.inner
536 }
537}
538
539#[cfg(test)]
540mod tests {
541 use super::*;
542 use acir::FieldElement;
543 use test_case::test_case;
544
545 #[test]
546 fn direct_write_and_read() {
547 let mut memory = Memory::<FieldElement>::default();
548 let addr = MemoryAddress::direct(5);
549
550 memory.write(addr, MemoryValue::U32(42));
551 assert_eq!(memory.read(addr).to_u128().unwrap(), 42);
552 }
553
554 #[test]
555 fn relative_write_and_read() {
556 let mut memory = Memory::<FieldElement>::default();
557 memory.write(MemoryAddress::direct(0), MemoryValue::U32(10));
559
560 let addr = MemoryAddress::Relative(5);
561 memory.write(addr, MemoryValue::U32(42));
562 assert_eq!(memory.read(addr).to_u128().unwrap(), 42);
563
564 let resolved_addr = memory.resolve(addr);
565 assert_eq!(resolved_addr, 15);
568 assert_eq!(memory.values()[assert_usize(resolved_addr)].to_u128().unwrap(), 42);
569 }
570
571 #[test]
572 fn memory_growth() {
573 let mut memory = Memory::<FieldElement>::default();
574 let addr = MemoryAddress::direct(10);
575
576 memory.write(addr, MemoryValue::U32(123));
577
578 let mut expected = vec![MemoryValue::default(); 10];
579 expected.push(MemoryValue::U32(123));
580
581 assert_eq!(memory.values(), &expected);
582 }
583
584 #[test]
585 fn resize_to_fit_grows_memory() {
586 let mut memory = Memory::<FieldElement>::default();
587 memory.resize_to_fit(15);
588
589 assert_eq!(memory.values().len(), 15);
590 assert!(memory.values().iter().all(|v| *v == MemoryValue::default()));
591 }
592
593 #[test]
594 fn write_and_read_slice() {
595 let mut memory = Memory::<FieldElement>::default();
596 let values: Vec<_> = (1..=5).map(MemoryValue::U32).collect();
598
599 memory.write_slice(MemoryAddress::direct(2), &values);
601 assert_eq!(
602 memory
603 .read_slice(MemoryAddress::direct(2), 3)
604 .iter()
605 .map(|v| v.to_u128().unwrap())
606 .collect::<Vec<_>>(),
607 vec![1, 2, 3]
608 );
609 assert_eq!(
610 memory
611 .read_slice(MemoryAddress::direct(5), 2)
612 .iter()
613 .map(|v| v.to_u128().unwrap())
614 .collect::<Vec<_>>(),
615 vec![4, 5]
616 );
617 let zero_field = FieldElement::zero();
618 assert_eq!(
619 memory
620 .read_slice(MemoryAddress::direct(0), 2)
621 .iter()
622 .map(|v| v.to_field())
623 .collect::<Vec<_>>(),
624 vec![zero_field, zero_field]
625 );
626 assert_eq!(
627 memory
628 .read_slice(MemoryAddress::direct(2), 5)
629 .iter()
630 .map(|v| v.to_u128().unwrap())
631 .collect::<Vec<_>>(),
632 vec![1, 2, 3, 4, 5]
633 );
634 }
635
636 #[test]
637 fn read_ref_returns_expected_address_and_reads_slice() {
638 let mut memory = Memory::<FieldElement>::default();
639
640 let heap_start = MemoryAddress::direct(10);
642 let values: Vec<_> = (1..=3).map(MemoryValue::U32).collect();
644 memory.write_slice(heap_start, &values);
645
646 let array_pointer = MemoryAddress::direct(1);
647 memory.write(array_pointer, MemoryValue::U32(10));
649
650 let array_start = memory.read_ref(array_pointer);
652 assert_eq!(array_start, MemoryAddress::direct(10));
653
654 let got_slice = memory.read_slice(array_start, 3);
656 assert_eq!(got_slice, values);
657 }
658
659 #[test]
660 fn zero_length_slice() {
661 let memory = Memory::<FieldElement>::default();
662 assert_eq!(memory.read_slice(MemoryAddress::direct(20), 0), &[]);
663 }
664
665 #[test]
666 fn read_from_non_existent_memory() {
667 let memory = Memory::<FieldElement>::default();
668 let result = memory.read(MemoryAddress::direct(20));
669 assert!(result.to_field().is_zero());
671 }
672
673 #[test]
674 #[should_panic(expected = "read_slice: out of bounds")]
675 fn read_vector_from_non_existent_memory() {
676 let memory = Memory::<FieldElement>::default();
677 let _ = memory.read_slice(MemoryAddress::direct(20), 10);
678 }
679
680 #[test]
681 #[should_panic(expected = "Memory address space exceeded")]
682 fn resize_to_fit_panics_when_exceeding_max_memory_size() {
683 let mut memory = Memory::<FieldElement>::default();
684 memory.resize_to_fit(MAX_MEMORY_SIZE + 1);
686 }
687
688 #[test_case(IntegerBitSize::U1, 2)]
689 #[test_case(IntegerBitSize::U8, 256)]
690 #[test_case(IntegerBitSize::U16, u128::from(u16::MAX) + 1)]
691 #[test_case(IntegerBitSize::U32, u128::from(u32::MAX) + 1)]
692 #[test_case(IntegerBitSize::U64, u128::from(u64::MAX) + 1)]
693 #[should_panic(expected = "range")]
694 fn memory_value_new_integer_out_of_range(bit_size: IntegerBitSize, value: u128) {
695 let _ = MemoryValue::<FieldElement>::new_integer(value, bit_size);
696 }
697
698 #[test]
699 #[should_panic = "stack pointer offset overflow"]
700 fn memory_resolve_overflow() {
701 let mut memory = Memory::<FieldElement>::default();
702 memory.write(STACK_POINTER_ADDRESS, MemoryValue::from(u32::MAX - 10));
703 let addr = MemoryAddress::relative(20);
704 let _wrap = memory.resolve(addr);
705 }
706}