Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(brillig): runtime memory allocation #1732

Merged
merged 6 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions crates/noirc_evaluator/src/brillig/brillig_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ pub(crate) fn convert_ssa_function(func: &Function) -> BrilligArtifact {

brillig_context.artifact()
}

/// Creates an entry point artifact, that will be linked with the brillig functions being called
pub(crate) fn create_entry_point_function(num_arguments: usize) -> BrilligArtifact {
let mut brillig_context = BrilligContext::default();
brillig_context.entry_point_instruction(num_arguments);
brillig_context.artifact()
}
12 changes: 6 additions & 6 deletions crates/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::brillig::brillig_ir::{
BrilligBinaryOp, BrilligContext, BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE,
BrilligBinaryOp, BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
};
use crate::ssa_refactor::ir::types::CompositeType;
use crate::ssa_refactor::ir::{
Expand Down Expand Up @@ -113,7 +113,7 @@ impl<'block> BrilligBlock<'block> {
let pointer_register = self
.function_context
.get_or_create_register(self.brillig_context, *param_id);
self.brillig_context.allocate_array(pointer_register, *size as u32);
self.brillig_context.allocate_fixed_length_array(pointer_register, *size);
}
_ => {
todo!("ICE: Param type not supported")
Expand Down Expand Up @@ -228,7 +228,7 @@ impl<'block> BrilligBlock<'block> {

// First issue a array copy to the destination
let array_size = compute_size_of_type(&dfg.type_of_value(*array));
self.brillig_context.allocate_array(destination, array_size as u32);
self.brillig_context.allocate_fixed_length_array(destination, array_size);
let source_array_register: RegisterIndex = self.convert_ssa_value(*array, dfg);
let size_register = self.brillig_context.make_constant(array_size.into());
self.brillig_context.copy_array_instruction(
Expand Down Expand Up @@ -281,7 +281,7 @@ impl<'block> BrilligBlock<'block> {
iterator_register,
BrilligBinaryOp::Integer {
op: BinaryIntOp::Add,
bit_size: BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE,
bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
},
);
}
Expand Down Expand Up @@ -369,9 +369,9 @@ impl<'block> BrilligBlock<'block> {
}
Value::Array { .. } => {
let address_register = self.brillig_context.create_register();
self.brillig_context.allocate_array(
self.brillig_context.allocate_fixed_length_array(
address_register,
compute_size_of_type(&dfg.type_of_value(value_id)) as u32,
compute_size_of_type(&dfg.type_of_value(value_id)),
);
self.store_in_memory(address_register, value_id, dfg);
address_register
Expand Down
79 changes: 65 additions & 14 deletions crates/noirc_evaluator/src/brillig/brillig_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@
//! ssa types and types in this module.
//! A similar paradigm can be seen with the `acir_ir` module.
pub(crate) mod artifact;
pub(crate) mod memory;

use self::{
artifact::{BrilligArtifact, UnresolvedJumpLocation},
memory::BrilligMemory,
};
use self::artifact::{BrilligArtifact, UnresolvedJumpLocation};
use acvm::{
acir::brillig_vm::{
BinaryFieldOp, BinaryIntOp, Opcode as BrilligOpcode, RegisterIndex, RegisterValueOrArray,
Expand All @@ -30,6 +26,27 @@ use acvm::{
/// would mean that unconstrained functions will differ from
/// constrained functions in terms of syntax compatibility.
pub(crate) const BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE: u32 = 127;
pub(crate) const BRILLIG_MEMORY_ADDRESSING_BIT_SIZE: u32 = 64;

// Registers reserved in runtime for special purposes.
pub(crate) enum ReservedRegisters {
/// This register stores the stack pointer. Allocations must be done after this pointer.
StackPointer = 0,
/// Number of reserved registers
Len = 1,
}

impl ReservedRegisters {
/// Returns the length of the reserved registers
pub(crate) fn len() -> usize {
ReservedRegisters::Len as usize
}

/// Returns the stack pointer register. This will get used to allocate memory in runtime.
pub(crate) fn stack_pointer() -> RegisterIndex {
RegisterIndex::from(ReservedRegisters::StackPointer as usize)
}
}

/// Brillig context object that is used while constructing the
/// Brillig bytecode.
Expand All @@ -38,8 +55,6 @@ pub(crate) struct BrilligContext {
obj: BrilligArtifact,
/// A usize indicating the latest un-used register.
latest_register: usize,
/// Tracks memory allocations
memory: BrilligMemory,
/// Context label, must be unique with respect to the function
/// being linked.
context_label: String,
Expand All @@ -48,6 +63,17 @@ pub(crate) struct BrilligContext {
}

impl BrilligContext {
/// Adds the instructions needed to handle entry point parameters
/// And sets the starting value of the reserved registers
pub(crate) fn entry_point_instruction(&mut self, num_arguments: usize) {
// Translate the inputs by the reserved registers offset
for i in (0..num_arguments).into_iter().rev() {
self.mov_instruction(self.user_register_index(i), RegisterIndex::from(i));
}
// Set the initial value of the stack pointer register
self.const_instruction(ReservedRegisters::stack_pointer(), Value::from(0_usize));
}

/// Adds a brillig instruction to the brillig byte code
pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) {
self.obj.byte_code.push(opcode);
Expand All @@ -60,12 +86,32 @@ impl BrilligContext {

/// Allocates an array of size `size` and stores the pointer to the array
/// in `pointer_register`
pub(crate) fn allocate_array(&mut self, pointer_register: RegisterIndex, size: u32) {
let allocation = self.memory.allocate(size as usize);
pub(crate) fn allocate_fixed_length_array(
&mut self,
pointer_register: RegisterIndex,
size: usize,
) {
let size_register = self.make_constant(size.into());
self.allocate_array_instruction(pointer_register, size_register);
}

self.push_opcode(BrilligOpcode::Const {
/// Allocates an array of size contained in size_register and stores the
/// pointer to the array in `pointer_register`
pub(crate) fn allocate_array_instruction(
&mut self,
pointer_register: RegisterIndex,
size_register: RegisterIndex,
) {
self.push_opcode(BrilligOpcode::Mov {
destination: pointer_register,
value: Value::from(allocation),
source: ReservedRegisters::stack_pointer(),
});
self.push_opcode(BrilligOpcode::BinaryIntOp {
destination: ReservedRegisters::stack_pointer(),
op: BinaryIntOp::Add,
bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
lhs: ReservedRegisters::stack_pointer(),
rhs: size_register,
});
}

Expand Down Expand Up @@ -130,7 +176,7 @@ impl BrilligContext {
index_less_than_array_len,
BrilligBinaryOp::Integer {
op: BinaryIntOp::LessThan,
bit_size: BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE,
bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
},
);

Expand All @@ -152,7 +198,7 @@ impl BrilligContext {
index,
BrilligBinaryOp::Integer {
op: BinaryIntOp::Add,
bit_size: BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE,
bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
},
);

Expand Down Expand Up @@ -221,9 +267,14 @@ impl BrilligContext {
self.obj.add_unresolved_jump(jmp_instruction, destination);
}

/// Returns a user defined (non-reserved) register index.
fn user_register_index(&self, index: usize) -> RegisterIndex {
RegisterIndex::from(index + ReservedRegisters::len())
}

/// Creates a new register.
pub(crate) fn create_register(&mut self) -> RegisterIndex {
let register = RegisterIndex::from(self.latest_register);
let register = self.user_register_index(self.latest_register);
self.latest_register += 1;
register
}
Expand Down
15 changes: 0 additions & 15 deletions crates/noirc_evaluator/src/brillig/brillig_ir/memory.rs

This file was deleted.

4 changes: 2 additions & 2 deletions crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::collections::HashMap;

use crate::brillig::{brillig_ir::artifact::BrilligArtifact, Brillig};
use crate::brillig::{brillig_gen::create_entry_point_function, Brillig};

use self::acir_ir::{
acir_variable::{AcirContext, AcirType, AcirVar},
Expand Down Expand Up @@ -183,7 +183,7 @@ impl Context {
let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg));

// Generate the brillig code of the function
let code = BrilligArtifact::default().link(&brillig[*id]);
let code = create_entry_point_function(arguments.len()).link(&brillig[*id]);

let outputs: Vec<AcirType> = vecmap(result_ids, |result_id| dfg.type_of_value(*result_id).into());

Expand Down