Skip to content

Commit

Permalink
chore: pull lazy memory initialization from sync (#11607)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Jan 30, 2025
1 parent 57131d6 commit 5da7521
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,17 @@ impl<F: AcirField> GeneratedAcir<F> {
bit_size: u32,
) -> Result<Vec<Witness>, RuntimeError> {
let radix_big = BigUint::from(radix);
let radix_range = BigUint::from(2u128)..=BigUint::from(256u128);
assert!(
radix_range.contains(&radix_big),
"ICE: Radix must be in the range 2..=256, but found: {:?}",
radix
);
assert_eq!(
BigUint::from(2u128).pow(bit_size),
radix_big,
"ICE: Radix must be a power of 2"
);

let limb_witnesses = self.brillig_to_radix(input_expr, radix, limb_count);

let mut composed_limbs = Expression::default();
Expand Down
106 changes: 62 additions & 44 deletions noir/noir-repo/compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,8 +1069,7 @@ impl<'a> Context<'a> {
// Ensure that array id is fully resolved.
let array = dfg.resolve(array);

let array_id = dfg.resolve(array);
let array_typ = dfg.type_of_value(array_id);
let array_typ = dfg.type_of_value(array);
// Compiler sanity checks
assert!(!array_typ.is_nested_slice(), "ICE: Nested slice type has reached ACIR generation");
let (Type::Array(_, _) | Type::Slice(_)) = &array_typ else {
Expand Down Expand Up @@ -1125,15 +1124,7 @@ impl<'a> Context<'a> {
index: ValueId,
store_value: Option<ValueId>,
) -> Result<bool, RuntimeError> {
let array_id = dfg.resolve(array);
let array_typ = dfg.type_of_value(array_id);
// Compiler sanity checks
assert!(!array_typ.is_nested_slice(), "ICE: Nested slice type has reached ACIR generation");
let (Type::Array(_, _) | Type::Slice(_)) = &array_typ else {
unreachable!("ICE: expected array or slice type");
};

match self.convert_value(array_id, dfg) {
match self.convert_value(array, dfg) {
AcirValue::Var(acir_var, _) => {
Err(RuntimeError::InternalError(InternalError::Unexpected {
expected: "an array value".to_string(),
Expand Down Expand Up @@ -1343,7 +1334,7 @@ impl<'a> Context<'a> {
typ: &Type,
) -> Result<AcirValue, RuntimeError> {
match typ {
Type::Numeric(_) => self.array_get_value(&Type::field(), call_data_block, offset),
Type::Numeric(_) => self.array_get_value(typ, call_data_block, offset),
Type::Array(arc, len) => {
let mut result = im::Vector::new();
for _i in 0..*len {
Expand Down Expand Up @@ -2231,45 +2222,41 @@ impl<'a> Context<'a> {
Intrinsic::AsSlice => {
let slice_contents = arguments[0];
let slice_typ = dfg.type_of_value(slice_contents);
let block_id = self.ensure_array_is_initialized(slice_contents, dfg)?;
assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation");

let result_block_id = self.block_id(&result_ids[1]);
let acir_value = self.convert_value(slice_contents, dfg);
let (slice_length, result) = match acir_value {
AcirValue::Var(_, _) => {
unreachable!("ICE: cannot call `as_slice` on non-array type")
}
array @ AcirValue::Array(_) => {
let array_len = if !slice_typ.contains_slice_element() {
slice_typ.flattened_size() as usize
} else {
self.flattened_slice_size(slice_contents, dfg)
};
(array_len, array)
}
AcirValue::DynamicArray(source_array) => {
let result_block_id = self.block_id(&result_ids[1]);
self.copy_dynamic_array(
source_array.block_id,
result_block_id,
source_array.len,
)?;

let array_len = if !slice_typ.contains_slice_element() {
slice_typ.flattened_size() as usize
} else {
self.flattened_slice_size(slice_contents, dfg)
};
let slice_length = self.acir_context.add_constant(array_len);
self.copy_dynamic_array(block_id, result_block_id, array_len)?;
let array = AcirValue::DynamicArray(AcirDynamicArray {
block_id: result_block_id,
len: source_array.len,
value_types: source_array.value_types,
element_type_sizes: source_array.element_type_sizes,
});

let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) {
Some(self.init_element_type_sizes_array(
&slice_typ,
slice_contents,
Some(&acir_value),
dfg,
)?)
} else {
None
(source_array.len, array)
}
};

let value_types = self.convert_value(slice_contents, dfg).flat_numeric_types();
assert!(
array_len == value_types.len(),
"AsSlice: unexpected length difference: {:?} != {:?}",
array_len,
value_types.len()
);

let result = AcirValue::DynamicArray(AcirDynamicArray {
block_id: result_block_id,
len: value_types.len(),
value_types,
element_type_sizes,
});
let slice_length = self.acir_context.add_constant(slice_length);
Ok(vec![AcirValue::Var(slice_length, AcirType::field()), result])
}
Intrinsic::SlicePushBack => {
Expand Down Expand Up @@ -3706,4 +3693,35 @@ mod test {
}
}
}

#[test]
fn does_not_generate_memory_blocks_without_dynamic_accesses() {
let src = "
acir(inline) fn main f0 {
b0(v0: [Field; 2]):
v2, v3 = call as_slice(v0) -> (u32, [Field])
call f1(u32 2, v3)
v7 = array_get v0, index u32 0 -> Field
constrain v7 == Field 0
return
}
brillig(inline) fn foo f1 {
b0(v0: u32, v1: [Field]):
return
}
";
let ssa = Ssa::from_str(src).unwrap();
let brillig = ssa.to_brillig(false);

let (acir_functions, _brillig_functions, _, _) = ssa
.into_acir(&brillig, ExpressionWidth::default())
.expect("Should compile manually written SSA into ACIR");

assert_eq!(acir_functions.len(), 1);

// Check that no memory opcodes were emitted.
let main = &acir_functions[0];
assert!(!main.opcodes().iter().any(|opcode| matches!(opcode, Opcode::MemoryOp { .. })));
}
}

0 comments on commit 5da7521

Please sign in to comment.