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): foreign calls with dynamic-size objects #1705

Merged
merged 58 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
6210550
disable mac tests
kevaundray Jun 9, 2023
66e7297
feat: added support for modulo ops on brillig (#1621)
sirasistant Jun 9, 2023
6bd5a8d
feat(brillig): foreign call/oracle compilation (#1600)
ludamad Jun 9, 2023
03d5040
feat: add support for assert in brillig (#1603)
guipublic Jun 9, 2023
055b892
Merge remote-tracking branch 'origin/master' into kw/brillig-main
kevaundray Jun 10, 2023
c5da92c
chore(ssa refactor): Separate Brillig only logic from Brillig-SSA gen…
kevaundray Jun 12, 2023
e66fb0c
chore(ssa_refactor): Improve foreign call compilation (#1644)
vezenovm Jun 13, 2023
f7f2647
feat: Brillig array inputs and outputs (#1630)
vezenovm Jun 13, 2023
ac5fb9d
*WIP* call brillig function from brillig
guipublic Jun 13, 2023
2893855
chore(brillig): master into brillig main (#1663)
sirasistant Jun 13, 2023
27b87d2
discriminate labels per function
guipublic Jun 14, 2023
ee1dd79
initial changes to get noir building using adam/foreign-call-vectors …
vezenovm Jun 14, 2023
3c88e25
include fix for array output from foreign calls
vezenovm Jun 14, 2023
e3d0ecc
Merge branch 'kw/brillig-main' into gd/brillig5
guipublic Jun 14, 2023
000e516
fixed commit to reference remote patch
vezenovm Jun 14, 2023
9a616d5
small cleanup
guipublic Jun 14, 2023
080e18d
do not save the special registers
guipublic Jun 14, 2023
dcc81c4
cargo clippy
vezenovm Jun 14, 2023
730f757
Merge
ludamad Jun 14, 2023
a5e61d0
towards dynamic arrays
ludamad Jun 14, 2023
31f2256
chore: bump acvm for better acvm vectors
ludamad Jun 15, 2023
20a50d4
Towards brillig vectors
ludamad Jun 15, 2023
54e33b1
push fix for test_brillig_ir_foreign_call_return_vector
vezenovm Jun 15, 2023
389836d
fix pseudo-noir in test
vezenovm Jun 15, 2023
fc11ef4
add Trap opcode to make Brillig IR test more accurate
vezenovm Jun 15, 2023
04a017e
move code from Adams and Guillaume's branch for BrilligIR
kevaundray Jun 17, 2023
30cf672
add used registers method
kevaundray Jun 17, 2023
00a2e9b
add method to handle calling normal functions and thread the function…
kevaundray Jun 17, 2023
75fd28e
add unresolved_call method into artifact struct
kevaundray Jun 17, 2023
fd1e5cb
remove Vec::clone
kevaundray Jun 17, 2023
bf0c136
small clean-up:
kevaundray Jun 17, 2023
da0d5f9
modify API for linking
kevaundray Jun 17, 2023
0ba8bed
pass parameter length and return type length to BrilligContext
kevaundray Jun 17, 2023
2f50676
move entry_point_instruction to artifact for now
kevaundray Jun 17, 2023
9471ad3
refactor API -- still has a lot of scaffolding
kevaundray Jun 17, 2023
1b39454
remove pretty_print_opcode
kevaundray Jun 17, 2023
f54c900
chore: high level brillig printorrr
ludamad Jun 17, 2023
272edb2
chore: move acvm
ludamad Jun 18, 2023
a055708
feat: implement call semantics (#1746)
sirasistant Jun 19, 2023
0269e7f
fix: correct_usize_op
sirasistant Jun 19, 2023
72aa6e0
fix: fix moving registers to registers
sirasistant Jun 19, 2023
39a2ada
fix: fixed array handling across calls
sirasistant Jun 19, 2023
4f2d669
docs: improved error msgs
sirasistant Jun 19, 2023
90c506e
Update
ludamad Jun 19, 2023
6cf0f03
debug(brillig): pretty print tool for debugging
ludamad Jun 19, 2023
b2f4565
Merge master into adam/foreign-call-vectors-redux
ludamad Jun 20, 2023
49ff693
Merge remote-tracking branch 'origin' into adam/foreign-call-vectors-…
ludamad Jun 20, 2023
0d4c33b
Merge brillig call branch
ludamad Jun 20, 2023
7e4916e
post-merge fixes
ludamad Jun 20, 2023
0aeb52d
Post-merge brillig ir printer fixes
ludamad Jun 20, 2023
09ec828
fix: post-merge build
ludamad Jun 20, 2023
766048e
chore: fixing diff. TODO not building
ludamad Jun 20, 2023
4ba5ba5
Re-merge master
ludamad Jun 20, 2023
f3f7529
Working build
ludamad Jun 20, 2023
8254942
Merge remote-tracking branch 'origin/master' into adam/foreign-call-v…
ludamad Jun 20, 2023
a74f1cb
Foreign call test
ludamad Jun 20, 2023
dd482b7
chore: fix deps
ludamad Jun 20, 2023
3c6deb7
Merge remote-tracking branch 'origin/master' into adam/foreign-call-v…
kevaundray Jun 22, 2023
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
21 changes: 10 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ edition = "2021"
rust-version = "1.66"

[workspace.dependencies]
acvm = "0.15.0"
acvm = "0.15.1"
arena = { path = "crates/arena" }
fm = { path = "crates/fm" }
iter-extended = { path = "crates/iter-extended" }
Expand Down
9 changes: 2 additions & 7 deletions crates/nargo/src/ops/execute.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use acvm::acir::brillig_vm::ForeignCallResult;
use acvm::acir::circuit::Opcode;
use acvm::pwg::{solve, Blocks, PartialWitnessGeneratorStatus, UnresolvedBrilligCall};
use acvm::PartialWitnessGenerator;
Expand Down Expand Up @@ -34,9 +33,7 @@ pub fn execute_circuit(
if foreign_call_wait_info.function == "oracle_print_impl" {
let values = &foreign_call_wait_info.inputs[0];
println!("{:?}", values[0].to_field().to_hex());
brillig.foreign_call_results.push(ForeignCallResult {
values: vec![vec![foreign_call_wait_info.inputs[0][0]]],
});
brillig.foreign_call_results.push(foreign_call_wait_info.inputs[0][0].into());
} else if foreign_call_wait_info.function == "oracle_print_array_impl" {
let mut outputs_hex = Vec::new();
for value in foreign_call_wait_info.inputs.clone() {
Expand All @@ -46,9 +43,7 @@ pub fn execute_circuit(
let comma_separated_elements = outputs_hex.join(", ");
let output_witnesses_string = "[".to_owned() + &comma_separated_elements + "]";
println!("{output_witnesses_string}");
brillig.foreign_call_results.push(ForeignCallResult {
values: vec![vec![foreign_call_wait_info.inputs[0][0]]],
});
brillig.foreign_call_results.push(foreign_call_wait_info.inputs[0][0].into());
}

let mut next_opcodes_for_solving = vec![Opcode::Brillig(brillig)];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ unconstrained fn oracle_print_array_wrapper(arr: [Field; 2]) {
oracle_print_array(arr);
}


Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::ssa_refactor::ir::{
types::{NumericType, Type},
value::{Value, ValueId},
};
use acvm::acir::brillig_vm::{BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterValueOrArray};
use acvm::acir::brillig_vm::{BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterOrMemory};
use acvm::FieldElement;
use iter_extended::vecmap;

Expand Down Expand Up @@ -430,12 +430,12 @@ impl<'block> BrilligBlock<'block> {
&mut self,
value_id: ValueId,
dfg: &DataFlowGraph,
) -> RegisterValueOrArray {
) -> RegisterOrMemory {
let register_index = self.convert_ssa_value(value_id, dfg);
let typ = dfg[value_id].get_type();
match typ {
Type::Numeric(_) => RegisterValueOrArray::RegisterIndex(register_index),
Type::Array(_, size) => RegisterValueOrArray::HeapArray(register_index, size),
Type::Numeric(_) => RegisterOrMemory::RegisterIndex(register_index),
Type::Array(_, size) => RegisterOrMemory::HeapArray(register_index, size),
_ => {
unreachable!("type not supported for conversion into brillig register")
}
Expand Down
94 changes: 88 additions & 6 deletions crates/noirc_evaluator/src/brillig/brillig_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use self::{
};
use acvm::{
acir::brillig_vm::{
BinaryFieldOp, BinaryIntOp, Opcode as BrilligOpcode, RegisterIndex, RegisterValueOrArray,
Value,
BinaryFieldOp, BinaryIntOp, Opcode as BrilligOpcode, RegisterIndex, RegisterOrMemory, Value,
},
FieldElement,
};
Expand Down Expand Up @@ -339,7 +338,6 @@ impl BrilligContext {
/// the VM.
pub(crate) fn return_instruction(&mut self, return_registers: &[RegisterIndex]) {
debug_show::return_instruction(return_registers);

let mut sources = Vec::with_capacity(return_registers.len());
let mut destinations = Vec::with_capacity(return_registers.len());

Expand Down Expand Up @@ -442,11 +440,10 @@ impl BrilligContext {
pub(crate) fn foreign_call_instruction(
&mut self,
func_name: String,
inputs: &[RegisterValueOrArray],
outputs: &[RegisterValueOrArray],
inputs: &[RegisterOrMemory],
outputs: &[RegisterOrMemory],
) {
debug_show::foreign_call_instruction(func_name.clone(), inputs, outputs);
// TODO(https://github.com/noir-lang/acvm/issues/366): Enable multiple inputs and outputs to a foreign call
let opcode = BrilligOpcode::ForeignCall {
function: func_name,
destinations: outputs.to_vec(),
Expand Down Expand Up @@ -592,7 +589,9 @@ impl BrilligContext {
}

/// Adds a unresolved external `Call` instruction to the bytecode.
/// This calls into another function compiled into this brillig artifact.
pub(crate) fn add_external_call_instruction<T: ToString>(&mut self, func_label: T) {
debug_show::add_external_call_instruction(func_label.to_string());
self.obj.add_unresolved_external_call(
BrilligOpcode::Call { location: 0 },
func_label.to_string(),
Expand Down Expand Up @@ -702,3 +701,86 @@ pub(crate) enum BrilligBinaryOp {
// Brillig.
Modulo { is_signed_integer: bool, bit_size: u32 },
}

#[cfg(test)]
mod tests {
use std::vec;

use acvm::acir::brillig_vm::{
BinaryIntOp, ForeignCallOutput, ForeignCallResult, RegisterIndex, RegisterOrMemory,
Registers, VMStatus, Value, VM,
};

use crate::brillig::brillig_ir::{BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE};

use super::{BrilligBinaryOp, BrilligOpcode, ReservedRegisters};

/// Test a Brillig foreign call returning a vector
#[test]
fn test_brillig_ir_foreign_call_return_vector() {
// pseudo-noir:
//
// #[oracle(make_number_sequence)]
// unconstrained fn make_number_sequence(size: u32) -> Vec<u32> {
// }
//
// unconstrained fn main() -> Vec<u32> {
// let the_sequence = make_number_sequence(12);
// assert(the_sequence.len() == 12);
// }
let mut context = BrilligContext::new(vec![], vec![]);
let r_stack = ReservedRegisters::stack_pointer();
// Start stack pointer at 0
context.const_instruction(r_stack, Value::from(0_usize));
let r_input_size = RegisterIndex::from(ReservedRegisters::len());
let r_array_ptr = RegisterIndex::from(ReservedRegisters::len() + 1);
let r_output_size = RegisterIndex::from(ReservedRegisters::len() + 2);
let r_equality = RegisterIndex::from(ReservedRegisters::len() + 3);
context.const_instruction(r_input_size, Value::from(12_usize));
// copy our stack frame to r_array_ptr
context.mov_instruction(r_array_ptr, r_stack);
context.foreign_call_instruction(
"make_number_sequence".into(),
&[RegisterOrMemory::RegisterIndex(r_input_size)],
&[RegisterOrMemory::HeapVector(r_stack, r_output_size)],
);
// push stack frame by r_returned_size
context.binary_instruction(
r_stack,
r_output_size,
r_stack,
BrilligBinaryOp::Integer {
op: BinaryIntOp::Add,
bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
},
);
// check r_input_size == r_output_size
context.binary_instruction(
r_input_size,
r_output_size,
r_equality,
BrilligBinaryOp::Integer {
op: BinaryIntOp::Equals,
bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
},
);
// We push a JumpIf and Trap opcode directly as the constrain instruction
// uses unresolved jumps which requires a block to be constructed in SSA and
// we don't need this for Brillig IR tests
context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 8 });
context.push_opcode(BrilligOpcode::Trap);

context.stop_instruction();

let bytecode = context.artifact().byte_code;
let number_sequence: Vec<Value> = (0_usize..12_usize).map(Value::from).collect();
let mut vm = VM::new(
Registers { inner: vec![] },
vec![],
bytecode,
vec![ForeignCallResult { values: vec![ForeignCallOutput::Array(number_sequence)] }],
);
let status = vm.process_opcodes();
assert_eq!(status, VMStatus::Finished);
}
}
32 changes: 19 additions & 13 deletions crates/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
///! This module contains functions for producing a higher level view disassembler of Brillig.
use super::BrilligBinaryOp;
use crate::brillig::brillig_ir::{ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE};
use acvm::acir::brillig_vm::{
BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterValueOrArray, Value,
};
use acvm::acir::brillig_vm::{BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterOrMemory, Value};

/// Controls whether debug traces are enabled
const ENABLE_DEBUG_TRACE: bool = true;
Expand Down Expand Up @@ -98,13 +96,16 @@ impl DebugToString for Value {
}
}

impl DebugToString for RegisterValueOrArray {
impl DebugToString for RegisterOrMemory {
fn debug_to_string(&self) -> String {
match self {
RegisterValueOrArray::RegisterIndex(index) => index.debug_to_string(),
RegisterValueOrArray::HeapArray(index, size) => {
RegisterOrMemory::RegisterIndex(index) => index.debug_to_string(),
RegisterOrMemory::HeapArray(index, size) => {
format!("{}[0..{}]", index.debug_to_string(), size)
}
RegisterOrMemory::HeapVector(index, size_register) => {
format!("{}[0..*{}]", index.debug_to_string(), size_register.debug_to_string())
}
}
}
}
Expand All @@ -116,14 +117,14 @@ impl<T: DebugToString> DebugToString for [T] {
}

macro_rules! debug_println {
( $first:expr ) => {
( $literal:expr ) => {
if ENABLE_DEBUG_TRACE {
println!("{}", $first);
println!("{}", $literal);
}
};
( $first:expr, $( $x:expr ),* ) => {
( $format_message:expr, $( $x:expr ),* ) => {
if ENABLE_DEBUG_TRACE {
println!($first, $( $x.debug_to_string(), )*)
println!($format_message, $( $x.debug_to_string(), )*)
}
};
}
Expand Down Expand Up @@ -167,14 +168,14 @@ pub(crate) fn const_instruction(result: RegisterIndex, constant: Value) {

/// Processes a not instruction. Append with "_" as this is a high-level instruction.
pub(crate) fn not_instruction(condition: RegisterIndex, result: RegisterIndex) {
debug_println!(" _NOT {} = !{}", result, condition);
debug_println!(" NOT {} = !{}", result, condition);
}

/// Processes a foreign call instruction.
pub(crate) fn foreign_call_instruction(
func_name: String,
inputs: &[RegisterValueOrArray],
outputs: &[RegisterValueOrArray],
inputs: &[RegisterOrMemory],
outputs: &[RegisterOrMemory],
) {
debug_println!(" FOREIGN_CALL {} ({}) => {}", func_name, inputs, outputs);
}
Expand Down Expand Up @@ -252,3 +253,8 @@ pub(crate) fn cast_instruction(
) {
debug_println!(" CAST {} FROM {} TO {} BITS", destination, source, target_bit_size);
}

/// Debug function for cast_instruction
pub(crate) fn add_external_call_instruction(func_label: String) {
debug_println!(" CALL {}", func_label);
}