Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'noir-lang:master' into feat-implement-integer-printing
Browse files Browse the repository at this point in the history
grasshopper47 authored Nov 27, 2023
2 parents 265af8b + 70ee787 commit 8bb6da3
Showing 32 changed files with 471 additions and 134 deletions.
25 changes: 5 additions & 20 deletions .github/workflows/docs-pr.yml
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ jobs:
if: needs.add_label.outputs.has_label == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v2
@@ -71,24 +71,8 @@ jobs:
run: |
npm i wasm-opt -g
- name: Install dependencies
run: yarn

- name: Build acvm_js
run: yarn workspace @noir-lang/acvm_js build

- name: Build noirc_abi
run: yarn workspace @noir-lang/noirc_abi build

- name: Build noir_js_types
run: yarn workspace @noir-lang/types build

- name: Build barretenberg wrapper
run: yarn workspace @noir-lang/backend_barretenberg build

- name: Run noir_js
run: |
yarn workspace @noir-lang/noir_js build
- name: Install Yarn dependencies
uses: ./.github/actions/setup

- name: Remove pre-releases
working-directory: docs
@@ -97,8 +81,9 @@ jobs:
run: yarn setStable

- name: Build docs
working-directory: docs
run:
yarn workspace docs build
yarn workspaces foreach -Rt run build

- name: Deploy to Netlify
uses: nwtgck/[email protected]
97 changes: 97 additions & 0 deletions .github/workflows/test-noir_codegen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: noir_codegen

on:
pull_request:
merge_group:
push:
branches:
- master

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }}
cancel-in-progress: true

jobs:
build-nargo:
runs-on: ubuntu-22.04
strategy:
matrix:
target: [x86_64-unknown-linux-gnu]

steps:
- name: Checkout Noir repo
uses: actions/checkout@v4

- name: Setup toolchain
uses: dtolnay/[email protected]

- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
cache-on-failure: true
save-if: ${{ github.event_name != 'merge_group' }}

- name: Build Nargo
run: cargo build --package nargo_cli --release

- name: Package artifacts
run: |
mkdir dist
cp ./target/release/nargo ./dist/nargo
7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: nargo
path: ./dist/*
retention-days: 3

test:
needs: [build-nargo]
name: Test noir_codegen
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Yarn dependencies
uses: ./.github/actions/setup

- name: Setup toolchain
uses: dtolnay/[email protected]
with:
targets: wasm32-unknown-unknown

- uses: Swatinem/rust-cache@v2
with:
key: wasm32-unknown-unknown-noir-js
cache-on-failure: true
save-if: ${{ github.event_name != 'merge_group' }}

- name: Install jq
run: sudo apt-get install jq

- name: Install wasm-bindgen-cli
uses: taiki-e/install-action@v2
with:
tool: [email protected]

- name: Install wasm-opt
run: |
npm i wasm-opt -g
- name: Build acvm_js
run: yarn workspace @noir-lang/acvm_js build

- name: Build noirc_abi
run: yarn workspace @noir-lang/noirc_abi build

- name: Build noir_js_types
run: yarn workspace @noir-lang/types build

- name: Build noir_js
run: yarn workspace @noir-lang/noir_js build

- name: Run noir_codegen tests
run: yarn workspace @noir-lang/noir_codegen test
54 changes: 28 additions & 26 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
@@ -282,32 +282,34 @@ impl FunctionBuilder {
) -> ValueId {
let base = self.field_constant(FieldElement::from(2_u128));
let typ = self.current_function.dfg.type_of_value(lhs);
let (max_bit, pow) = if let Some(rhs_constant) =
self.current_function.dfg.get_numeric_constant(rhs)
{
// Happy case is that we know precisely by how many bits the the integer will
// increase: lhs_bit_size + rhs
let (rhs_bit_size_pow_2, overflows) =
2_u32.overflowing_pow(rhs_constant.to_u128() as u32);
if overflows {
let zero = self.numeric_constant(FieldElement::zero(), typ);
return InsertInstructionResult::SimplifiedTo(zero).first();
}
let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2 as u128), typ);
(bit_size + (rhs_constant.to_u128() as u32), pow)
} else {
// we use a predicate to nullify the result in case of overflow
let bit_size_var =
self.numeric_constant(FieldElement::from(bit_size as u128), typ.clone());
let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var);
let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1));
let predicate = self.insert_binary(overflow, BinaryOp::Eq, one);
let predicate = self.insert_cast(predicate, typ.clone());

let pow = self.pow(base, rhs);
let pow = self.insert_cast(pow, typ);
(FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow))
};
let (max_bit, pow) =
if let Some(rhs_constant) = self.current_function.dfg.get_numeric_constant(rhs) {
// Happy case is that we know precisely by how many bits the the integer will
// increase: lhs_bit_size + rhs
let (rhs_bit_size_pow_2, overflows) =
2_u128.overflowing_pow(rhs_constant.to_u128() as u32);
if overflows {
assert!(bit_size < 128, "ICE - shift left with big integers are not supported");
if bit_size < 128 {
let zero = self.numeric_constant(FieldElement::zero(), typ);
return InsertInstructionResult::SimplifiedTo(zero).first();
}
}
let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2), typ);
(bit_size + (rhs_constant.to_u128() as u32), pow)
} else {
// we use a predicate to nullify the result in case of overflow
let bit_size_var =
self.numeric_constant(FieldElement::from(bit_size as u128), typ.clone());
let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var);
let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1));
let predicate = self.insert_binary(overflow, BinaryOp::Eq, one);
let predicate = self.insert_cast(predicate, typ.clone());

let pow = self.pow(base, rhs);
let pow = self.insert_cast(pow, typ);
(FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow))
};

let instruction = Instruction::Binary(Binary { lhs, rhs: pow, operator: BinaryOp::Mul });
if max_bit <= bit_size {
19 changes: 8 additions & 11 deletions compiler/noirc_evaluator/src/ssa/opt/mem2reg/block.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::BTreeMap};
use std::borrow::Cow;

use crate::ssa::ir::{
function::Function,
@@ -19,27 +19,27 @@ pub(super) struct Block {
/// Maps a ValueId to the Expression it represents.
/// Multiple ValueIds can map to the same Expression, e.g.
/// dereferences to the same allocation.
pub(super) expressions: BTreeMap<ValueId, Expression>,
pub(super) expressions: im::OrdMap<ValueId, Expression>,

/// Each expression is tracked as to how many aliases it
/// may have. If there is only 1, we can attempt to optimize
/// out any known loads to that alias. Note that "alias" here
/// includes the original reference as well.
pub(super) aliases: BTreeMap<Expression, AliasSet>,
pub(super) aliases: im::OrdMap<Expression, AliasSet>,

/// Each allocate instruction result (and some reference block parameters)
/// will map to a Reference value which tracks whether the last value stored
/// to the reference is known.
pub(super) references: BTreeMap<ValueId, ReferenceValue>,
pub(super) references: im::OrdMap<ValueId, ReferenceValue>,

/// The last instance of a `Store` instruction to each address in this block
pub(super) last_stores: BTreeMap<ValueId, InstructionId>,
pub(super) last_stores: im::OrdMap<ValueId, InstructionId>,
}

/// An `Expression` here is used to represent a canonical key
/// into the aliases map since otherwise two dereferences of the
/// same address will be given different ValueIds.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub(super) enum Expression {
Dereference(Box<Expression>),
ArrayElement(Box<Expression>),
@@ -111,10 +111,7 @@ impl Block {
}

fn invalidate_all_references(&mut self) {
for reference_value in self.references.values_mut() {
*reference_value = ReferenceValue::Unknown;
}

self.references.clear();
self.last_stores.clear();
}

@@ -137,7 +134,7 @@ impl Block {
}

// Keep only the references present in both maps.
let mut intersection = BTreeMap::new();
let mut intersection = im::OrdMap::new();
for (value_id, reference) in &other.references {
if let Some(existing) = self.references.get(value_id) {
intersection.insert(*value_id, existing.unify(*reference));
3 changes: 1 addition & 2 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
@@ -646,7 +646,6 @@ fn resolve_globals(
let globals = vecmap(globals, |global| {
let module_id = ModuleId { local_id: global.module_id, krate: crate_id };
let path_resolver = StandardPathResolver::new(module_id);
let storage_slot = context.next_storage_slot(module_id);

let mut resolver = Resolver::new(
&mut context.def_interner,
@@ -662,7 +661,7 @@ fn resolve_globals(

context.def_interner.update_global(global.stmt_id, hir_stmt);

context.def_interner.push_global(global.stmt_id, name, global.module_id, storage_slot);
context.def_interner.push_global(global.stmt_id, name, global.module_id);

(global.file_id, global.stmt_id)
});
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
@@ -528,11 +528,11 @@ impl<'a> ModCollector<'a> {
};
errors.push((error.into(), location.file));

let error2 = DefCollectorErrorKind::ModuleOriginallyDefined {
let error = DefCollectorErrorKind::ModuleOriginallyDefined {
mod_name: mod_name.clone(),
span: old_location.span,
};
errors.push((error2.into(), old_location.file));
errors.push((error.into(), old_location.file));
return errors;
}

19 changes: 0 additions & 19 deletions compiler/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -29,10 +29,6 @@ pub struct Context {
/// A map of each file that already has been visited from a prior `mod foo;` declaration.
/// This is used to issue an error if a second `mod foo;` is declared to the same file.
pub visited_files: BTreeMap<fm::FileId, Location>,

/// Maps a given (contract) module id to the next available storage slot
/// for that contract.
pub storage_slots: BTreeMap<def_map::ModuleId, StorageSlot>,
}

#[derive(Debug, Copy, Clone)]
@@ -42,8 +38,6 @@ pub enum FunctionNameMatch<'a> {
Contains(&'a str),
}

pub type StorageSlot = u32;

impl Context {
pub fn new(file_manager: FileManager, crate_graph: CrateGraph) -> Context {
Context {
@@ -52,7 +46,6 @@ impl Context {
visited_files: BTreeMap::new(),
crate_graph,
file_manager,
storage_slots: BTreeMap::new(),
}
}

@@ -200,16 +193,4 @@ impl Context {
fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData {
module_id.module(&self.def_maps)
}

/// Returns the next available storage slot in the given module.
/// Returns None if the given module is not a contract module.
fn next_storage_slot(&mut self, module_id: def_map::ModuleId) -> Option<StorageSlot> {
let module = self.module(module_id);

module.is_contract.then(|| {
let next_slot = self.storage_slots.entry(module_id).or_insert(0);
*next_slot += 1;
*next_slot
})
}
}
15 changes: 2 additions & 13 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ use crate::ast::Ident;
use crate::graph::CrateId;
use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias};
use crate::hir::def_map::{LocalModuleId, ModuleId};
use crate::hir::StorageSlot;
use crate::hir_def::stmt::HirLetStatement;
use crate::hir_def::traits::TraitImpl;
use crate::hir_def::traits::{Trait, TraitConstraint};
@@ -399,10 +398,6 @@ impl DefinitionKind {
pub struct GlobalInfo {
pub ident: Ident,
pub local_id: LocalModuleId,

/// Global definitions have an associated storage slot if they are defined within
/// a contract. If they're defined elsewhere, this value is None.
pub storage_slot: Option<StorageSlot>,
}

impl Default for NodeInterner {
@@ -578,14 +573,8 @@ impl NodeInterner {
self.id_to_type.insert(definition_id.into(), typ);
}

pub fn push_global(
&mut self,
stmt_id: StmtId,
ident: Ident,
local_id: LocalModuleId,
storage_slot: Option<StorageSlot>,
) {
self.globals.insert(stmt_id, GlobalInfo { ident, local_id, storage_slot });
pub fn push_global(&mut self, stmt_id: StmtId, ident: Ident, local_id: LocalModuleId) {
self.globals.insert(stmt_id, GlobalInfo { ident, local_id });
}

/// Intern an empty global stmt. Used for collecting globals
2 changes: 1 addition & 1 deletion compiler/noirc_printable_type/src/lib.rs
Original file line number Diff line number Diff line change
@@ -205,7 +205,7 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option<String> {
}

(PrintableValue::String(s), PrintableType::String { .. }) => {
output.push_str(&format!(r#""{s}""#));
output.push_str(s);
}

(PrintableValue::Struct(map), PrintableType::Struct { name, fields, .. }) => {
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
"@docusaurus/preset-classic": "^2.4.0",
"@easyops-cn/docusaurus-search-local": "^0.35.0",
"@mdx-js/react": "^1.6.22",
"@noir-lang/noir_js": "workspace:*",
"axios": "^1.4.0",
"clsx": "^1.2.1",
"docusaurus-plugin-typedoc": "1.0.0-next.18",
Loading

0 comments on commit 8bb6da3

Please sign in to comment.