Skip to content

Commit

Permalink
chore(ssa refactor): Brillig main (#1561)
Browse files Browse the repository at this point in the history
* remove mac runner

* chore: generate brillig opcode for simple identity unconstrained function (#1536)

* feat(brillig): added arithmetic operations on brillig (#1565)

Co-authored-by: kevaundray <[email protected]>

* make ranges be polymorphic integers

* chore(brillig): Clean up handling of Binary operations (#1571)

* chore(ssa refactor): Rename Brillig example (#1563)

* chore(brillig): added tests for all field binary operations (#1586)

* chore(brillig): added tests for brillig integer operations (#1590)

* feat: process blocks and jumps when compiling brillig (#1591)

* process jumps between blocks

* fix jumps

* add doc comments

* cargo fmt

* code refactor

* update code comment

---------

Co-authored-by: kevaundray <[email protected]>

* feat: process blocks and jumps when compiling brillig (#1591)

* process jumps between blocks

* fix jumps

* add doc comments

* cargo fmt

* code refactor

* update code comment

---------

Co-authored-by: kevaundray <[email protected]>

* feat(brillig): parsing oracles/foreign calls (#1596)

* feat(brillig): start of oracles/foreign calls

* fix: broken tests

* Update execute.rs

* self.data -> self.vars

* chore(brillig): Add handling of the not instruction (#1609)

* make behavior consistent

* remove closure

* change index_type

* Update crates/noirc_frontend/src/hir/type_check/expr.rs

* feat(brillig): loops (#1610)

* make ranges be polymorphic integers

* feat: brillig loop support

* fix: fixed brillig returns and stop

* fix: do not apply constants folding to brillig fns

* chore: update acvm pointer, cleanup

* style: newline on cargo toml

* make behavior consistent

* remove closure

* change index_type

* Update crates/noirc_frontend/src/hir/type_check/expr.rs

* better debug information for unsupported instruction

* remove edge case for optimizations

* clippy fix

* patch infinite loop

---------

Co-authored-by: kevaundray <[email protected]>
Co-authored-by: jfecher <[email protected]>

* chore: resolve immutable array merge differences (#1617)

* chore(ssa refactor): Switch to immutable arrays (#1578)

* Represent SSA arrays with im::Vector

* Get tests passing

* Implement assign with immutable arrays

* Add constant folding pass

* Update comments

* Clippy

* Update comment

* Update type of array

* Update crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs

Co-authored-by: Tom French <[email protected]>

* Undo formatting changes in instruction.rs

* Massive acir_gen update

* Refactor acir array operations into a shared function

* Appease clippy

* Update to_radix and to_bits in acir_gen to return arrays

* Disable assert

* Fix convert_type for arrays

* Include AcirType in AcirValue::Var variant

* Fix black box functions

* Appease clippy

* Fix simple_radix

* Add doc comments

---------

Co-authored-by: Tom French <[email protected]>

* feat: Make for-loop range be a polymorphic integer instead of just Field in unconstrained functions (#1583)

* make ranges be polymorphic integers

* make behavior consistent

* remove closure

* change index_type

* Update crates/noirc_frontend/src/hir/type_check/expr.rs

---------

Co-authored-by: jfecher <[email protected]>

* chore(ssa refactor): fix brillig post master merge

* chore(ssa refactor): accidental merge undelete

---------

Co-authored-by: jfecher <[email protected]>
Co-authored-by: Tom French <[email protected]>
Co-authored-by: kevaundray <[email protected]>

* chore(ssa refactor): Add more documentation for truncation  (#1607)

* add more documentation

* small change

* Update crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs

* Update .github/workflows/test.yml

* Update .github/workflows/test.yml

---------

Co-authored-by: guipublic <[email protected]>
Co-authored-by: Álvaro Rodríguez <[email protected]>
Co-authored-by: ludamad <[email protected]>
Co-authored-by: jfecher <[email protected]>
Co-authored-by: joss-aztec <[email protected]>
Co-authored-by: Tom French <[email protected]>
  • Loading branch information
7 people authored Jun 9, 2023
1 parent 77fba56 commit 2cb87dc
Show file tree
Hide file tree
Showing 40 changed files with 912 additions and 87 deletions.
20 changes: 10 additions & 10 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.14.1"
acvm = "=0.14.2"
arena = { path = "crates/arena" }
fm = { path = "crates/fm" }
iter-extended = { path = "crates/iter-extended" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = "1"
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Tests a very simple program.
//
// The features being tested is basic conditonal on brillig
fn main(x: Field) {
assert(4 == conditional(x as bool));
}

unconstrained fn conditional(x : bool) -> Field {
if x {
4
}else {
5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Tests arithmetic operations on fields
fn main() {
let x = 4;
let y = 2;
assert((x + y) == add(x, y));
assert((x - y) == sub(x, y));
assert((x * y) == mul(x, y));
assert((x / y) == div(x, y));
}

unconstrained fn add(x : Field, y : Field) -> Field {
x + y
}

unconstrained fn sub(x : Field, y : Field) -> Field {
x - y
}

unconstrained fn mul(x : Field, y : Field) -> Field {
x * y
}

unconstrained fn div(x : Field, y : Field) -> Field {
x / y
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = "3"

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Tests a very simple program.
//
// The features being tested is the identity function in Brillig
fn main(x : Field) {
assert(x == identity(x));
}

unconstrained fn identity(x : Field) -> Field {
x
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Tests arithmetic operations on integers
fn main() {
let x: u32 = 6;
let y: u32 = 2;

assert((x + y) == add(x, y));

assert((x - y) == sub(x, y));

assert((x * y) == mul(x, y));

assert((x / y) == div(x, y));

// TODO SSA => ACIR has some issues with i32 ops
assert(check_signed_div(6, 2, 3));

assert(eq(1, 2) == false);
assert(eq(1, 1));

assert(lt(x, y) == false);
assert(lt(y, x));

assert((x & y) == and(x, y));
assert((x | y) == or(x, y));

// TODO SSA => ACIR has some issues with xor ops

assert(check_xor(x, y, 4));
assert((x >> y) == shr(x, y));
assert((x << y) == shl(x, y));
}

unconstrained fn add(x : u32, y : u32) -> u32 {
x + y
}

unconstrained fn sub(x : u32, y : u32) -> u32 {
x - y
}

unconstrained fn mul(x : u32, y : u32) -> u32 {
x * y
}

unconstrained fn div(x : u32, y : u32) -> u32 {
x / y
}

unconstrained fn check_signed_div(x: i32, y: i32, result: i32) -> bool {
(x / y) == result
}

unconstrained fn eq(x : u32, y : u32) -> bool {
x == y
}

unconstrained fn lt(x : u32, y : u32) -> bool {
x < y
}

unconstrained fn and(x : u32, y : u32) -> u32 {
x & y
}

unconstrained fn or(x : u32, y : u32) -> u32 {
x | y
}

unconstrained fn check_xor(x : u32, y : u32, result: u32) -> bool {
(x ^ y) == result
}

unconstrained fn shr(x : u32, y : u32) -> u32 {
x >> y
}

unconstrained fn shl(x : u32, y : u32) -> u32 {
x << y
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sum = "6"
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Tests a very simple program.
//
// The features being tested is basic looping on brillig
fn main(sum: u32){
assert(loop(4) == sum);
}

unconstrained fn loop(x: u32) -> u32 {
let mut sum = 0;
for i in 0..x {
sum = sum + i;
}
sum
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = "1"
y = "0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Tests a very simple Brillig function.
//
// The features being tested is not instruction on brillig
fn main(x: Field, y : Field) {
assert(false == not_operator(x as bool));
assert(true == not_operator(y as bool));
}

unconstrained fn not_operator(x : bool) -> bool {
!x
}
85 changes: 79 additions & 6 deletions crates/noirc_evaluator/src/brillig/artifact.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,98 @@
use crate::ssa_refactor::ir::basic_block::BasicBlockId;
use acvm::acir::brillig_vm::Opcode as BrilligOpcode;
use std::collections::HashMap;

/// Pointer to a unresolved Jump instruction in
/// the bytecode.
pub(crate) type JumpLabel = usize;

/// Pointer to a position in the bytecode where a
/// particular basic block starts.
pub(crate) type BlockLabel = usize;

#[derive(Default, Debug, Clone)]
/// Artifacts resulting from the compilation of a function into brillig byte code
/// Currently it is just the brillig bytecode of the function
/// Artifacts resulting from the compilation of a function into brillig byte code.
/// Currently it is just the brillig bytecode of the function.
pub(crate) struct BrilligArtifact {
pub(crate) byte_code: Vec<BrilligOpcode>,
/// The set of jumps that need to have their locations
/// resolved.
unresolved_jumps: Vec<(JumpLabel, BasicBlockId)>,
/// A map of the basic blocks to their positions
/// in the bytecode.
blocks: HashMap<BasicBlockId, BlockLabel>,
}

impl BrilligArtifact {
// Link some compiled brillig bytecode with its referenced artifacts
/// Link some compiled brillig bytecode with its referenced artifacts.
pub(crate) fn link(&mut self, obj: &BrilligArtifact) -> Vec<BrilligOpcode> {
self.link_with(obj);
self.resolve_jumps();
self.byte_code.clone()
}

// Link with a brillig artifact
/// Link with a brillig artifact
fn link_with(&mut self, obj: &BrilligArtifact) {
if obj.byte_code.is_empty() {
panic!("ICE: unresolved symbol");
let offset = self.code_len();
for (jump_label, block_id) in &obj.unresolved_jumps {
self.unresolved_jumps.push((jump_label + offset, *block_id));
}

for (block_id, block_label) in &obj.blocks {
self.blocks.insert(*block_id, block_label + offset);
}

self.byte_code.extend_from_slice(&obj.byte_code);
}

/// Adds a unresolved jump to be fixed at the end of bytecode processing.
pub(crate) fn add_unresolved_jump(&mut self, destination: BasicBlockId) {
self.unresolved_jumps.push((self.code_len(), destination));
}

/// Adds a label in the bytecode to specify where this block's
/// opcodes will start.
pub(crate) fn add_block_label(&mut self, block: BasicBlockId) {
self.blocks.insert(block, self.code_len());
}

/// Number of the opcodes currently in the bytecode
pub(crate) fn code_len(&self) -> usize {
self.byte_code.len()
}

/// Resolves all of the unresolved jumps in the program.
///
/// Note: This should only be called once all blocks are processed.
fn resolve_jumps(&mut self) {
for (jump_label, block) in &self.unresolved_jumps {
let jump_instruction = self.byte_code[*jump_label].clone();

let actual_block_location = self.blocks[block];

match jump_instruction {
BrilligOpcode::Jump { location } => {
assert_eq!(location, 0, "location is not zero, which means that the jump label does not need resolving");

self.byte_code[*jump_label] =
BrilligOpcode::Jump { location: actual_block_location };
}
BrilligOpcode::JumpIfNot { condition, location } => {
assert_eq!(location, 0, "location is not zero, which means that the jump label does not need resolving");

self.byte_code[*jump_label] =
BrilligOpcode::JumpIfNot { condition, location: actual_block_location };
}
BrilligOpcode::JumpIf { condition, location } => {
assert_eq!(location, 0,"location is not zero, which means that the jump label does not need resolving");

self.byte_code[*jump_label] =
BrilligOpcode::JumpIf { condition, location: actual_block_location };
}
_ => unreachable!(
"all jump labels should point to a jump instruction in the bytecode"
),
}
}
}
}
Loading

0 comments on commit 2cb87dc

Please sign in to comment.