Skip to content

Commit

Permalink
fix: entrypoint register allocation
Browse files Browse the repository at this point in the history
  • Loading branch information
sirasistant authored and fcarreiro committed Sep 6, 2024
1 parent 9de462a commit bf18e64
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ impl<F: AcirField + DebugToString> BrilligContext<F, Stack> {
arguments: &[BrilligParameter],
return_parameters: &[BrilligParameter],
) {
// We need to allocate the variable for every argument first so any register allocation doesn't mangle the expected order.
let mut argument_variables = self.allocate_function_arguments(arguments);

let calldata_size = Self::flattened_tuple_size(arguments);
let return_data_size = Self::flattened_tuple_size(return_parameters);

Expand All @@ -64,90 +67,91 @@ impl<F: AcirField + DebugToString> BrilligContext<F, Stack> {
// Copy calldata
self.copy_and_cast_calldata(arguments);

// Allocate the variables for every argument:
let mut current_calldata_pointer = Self::calldata_start_offset();

let mut argument_variables: Vec<_> = arguments
.iter()
.map(|argument| match argument {
BrilligParameter::SingleAddr(bit_size) => {
let single_address = self.allocate_register();
let var = BrilligVariable::SingleAddr(SingleAddrVariable {
address: single_address,
bit_size: *bit_size,
});
self.mov_instruction(single_address, MemoryAddress(current_calldata_pointer));
current_calldata_pointer += 1;
var
}
BrilligParameter::Array(_, _) => {
let pointer_to_the_array_in_calldata =
self.make_usize_constant_instruction(current_calldata_pointer.into());
let rc_register = self.make_usize_constant_instruction(1_usize.into());
let flattened_size = Self::flattened_size(argument);
let var = BrilligVariable::BrilligArray(BrilligArray {
pointer: pointer_to_the_array_in_calldata.address,
size: flattened_size,
rc: rc_register.address,
});

current_calldata_pointer += flattened_size;
var
}
BrilligParameter::Slice(_, _) => {
let pointer_to_the_array_in_calldata =
self.make_usize_constant_instruction(current_calldata_pointer.into());

let flattened_size = Self::flattened_size(argument);
let size_register = self.make_usize_constant_instruction(flattened_size.into());
let rc_register = self.make_usize_constant_instruction(1_usize.into());

let var = BrilligVariable::BrilligVector(BrilligVector {
pointer: pointer_to_the_array_in_calldata.address,
size: size_register.address,
rc: rc_register.address,
});

current_calldata_pointer += flattened_size;
var
}
})
.collect();

// Deflatten arrays
// Initialize the variables with the calldata
for (argument_variable, argument) in argument_variables.iter_mut().zip(arguments) {
match (argument_variable, argument) {
(BrilligVariable::SingleAddr(single_address), BrilligParameter::SingleAddr(_)) => {
self.mov_instruction(
single_address.address,
MemoryAddress(current_calldata_pointer),
);
current_calldata_pointer += 1;
}
(
BrilligVariable::BrilligArray(array),
BrilligParameter::Array(item_type, item_count),
) => {
let flattened_size = array.size;
self.usize_const_instruction(array.pointer, current_calldata_pointer.into());
self.usize_const_instruction(array.rc, 1_usize.into());

// Deflatten the array
let deflattened_address =
self.deflatten_array(item_type, array.size, array.pointer);
self.mov_instruction(array.pointer, deflattened_address);
array.size = item_type.len() * item_count;
self.deallocate_register(deflattened_address);

current_calldata_pointer += flattened_size;
}
(
BrilligVariable::BrilligVector(vector),
BrilligParameter::Slice(item_type, item_count),
) => {
let flattened_size = Self::flattened_size(argument);
self.usize_const_instruction(vector.pointer, current_calldata_pointer.into());
self.usize_const_instruction(vector.rc, 1_usize.into());
self.usize_const_instruction(vector.size, flattened_size.into());

// Deflatten the vector
let deflattened_address =
self.deflatten_array(item_type, flattened_size, vector.pointer);
self.mov_instruction(vector.pointer, deflattened_address);
self.usize_const_instruction(
vector.size,
(item_type.len() * item_count).into(),
);

self.deallocate_register(deflattened_address);

current_calldata_pointer += flattened_size;
}
_ => {}
_ => unreachable!("ICE: cannot match variables against arguments"),
}
}
}

fn allocate_function_arguments(
&mut self,
arguments: &[BrilligParameter],
) -> Vec<BrilligVariable> {
arguments
.iter()
.map(|argument| match argument {
BrilligParameter::SingleAddr(bit_size) => {
BrilligVariable::SingleAddr(SingleAddrVariable {
address: self.allocate_register(),
bit_size: *bit_size,
})
}
BrilligParameter::Array(_, _) => {
let flattened_size = Self::flattened_size(argument);
BrilligVariable::BrilligArray(BrilligArray {
pointer: self.allocate_register(),
size: flattened_size,
rc: self.allocate_register(),
})
}
BrilligParameter::Slice(_, _) => BrilligVariable::BrilligVector(BrilligVector {
pointer: self.allocate_register(),
size: self.allocate_register(),
rc: self.allocate_register(),
}),
})
.collect()
}

fn copy_and_cast_calldata(&mut self, arguments: &[BrilligParameter]) {
let calldata_size = Self::flattened_tuple_size(arguments);
self.calldata_copy_instruction(
Expand Down
36 changes: 30 additions & 6 deletions noir/noir-repo/tooling/debugger/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ mod tests {
})
);

// Execute the first Brillig opcode (calldata copy)
// Const
let result = context.step_into_opcode();
assert!(matches!(result, DebugCommandResult::Ok));
assert_eq!(
Expand All @@ -1058,7 +1058,7 @@ mod tests {
})
);

// execute the second Brillig opcode (const)
// Const
let result = context.step_into_opcode();
assert!(matches!(result, DebugCommandResult::Ok));
assert_eq!(
Expand All @@ -1070,26 +1070,50 @@ mod tests {
})
);

// try to execute the third Brillig opcode (and resolve the foreign call)
// Calldatacopy
let result = context.step_into_opcode();
assert!(matches!(result, DebugCommandResult::Ok));
assert_eq!(
context.get_current_debug_location(),
Some(DebugLocation {
circuit_id: 0,
opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 },
opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 },
brillig_function_id: Some(BrilligFunctionId(0)),
})
);

// retry the third Brillig opcode (foreign call should be finished)
// Const
let result = context.step_into_opcode();
assert!(matches!(result, DebugCommandResult::Ok));
assert_eq!(
context.get_current_debug_location(),
Some(DebugLocation {
circuit_id: 0,
opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 },
opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 },
brillig_function_id: Some(BrilligFunctionId(0)),
})
);

// try to execute the Brillig opcode (and resolve the foreign call)
let result = context.step_into_opcode();
assert!(matches!(result, DebugCommandResult::Ok));
assert_eq!(
context.get_current_debug_location(),
Some(DebugLocation {
circuit_id: 0,
opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 },
brillig_function_id: Some(BrilligFunctionId(0)),
})
);

// retry the Brillig opcode (foreign call should be finished)
let result = context.step_into_opcode();
assert!(matches!(result, DebugCommandResult::Ok));
assert_eq!(
context.get_current_debug_location(),
Some(DebugLocation {
circuit_id: 0,
opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 5 },
brillig_function_id: Some(BrilligFunctionId(0)),
})
);
Expand Down

0 comments on commit bf18e64

Please sign in to comment.