Skip to content

Commit

Permalink
chore: split off fuzzer, abi changes and noirc_artifacts from sync (#…
Browse files Browse the repository at this point in the history
…7208)

This PR splits off a lot of the peripheral changes from the sync PR,
namely the fuzzer, pushing ABI gen into `noirc_driver`, splitting
`noirc_artifacts` out.
  • Loading branch information
TomAFrench authored Jun 27, 2024
1 parent 141e137 commit 255d752
Show file tree
Hide file tree
Showing 64 changed files with 1,252 additions and 347 deletions.
61 changes: 50 additions & 11 deletions noir/noir-repo/Cargo.lock

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

6 changes: 6 additions & 0 deletions noir/noir-repo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ members = [
# Crates related to tooling built on top of the Noir compiler
"tooling/lsp",
"tooling/debugger",
"tooling/fuzzer",
"tooling/nargo",
"tooling/nargo_fmt",
"tooling/nargo_cli",
"tooling/nargo_toml",
"tooling/noirc_artifacts",
"tooling/noirc_abi",
"tooling/noirc_abi_wasm",
"tooling/acvm_cli",
Expand Down Expand Up @@ -69,12 +71,14 @@ noirc_frontend = { path = "compiler/noirc_frontend" }
noirc_printable_type = { path = "compiler/noirc_printable_type" }

# Noir tooling workspace dependencies
noir_fuzzer = { path = "tooling/fuzzer" }
nargo = { path = "tooling/nargo" }
nargo_fmt = { path = "tooling/nargo_fmt" }
nargo_toml = { path = "tooling/nargo_toml" }
noir_lsp = { path = "tooling/lsp" }
noir_debugger = { path = "tooling/debugger" }
noirc_abi = { path = "tooling/noirc_abi" }
noirc_artifacts = { path = "tooling/noirc_artifacts" }
bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" }
acvm_cli = { path = "tooling/acvm_cli" }

Expand Down Expand Up @@ -143,6 +147,8 @@ flate2 = "1.0.24"
color-eyre = "0.6.2"
rand = "0.8.5"
proptest = "1.2.0"
proptest-derive = "0.4.0"

im = { version = "15.1", features = ["serde"] }
tracing = "0.1.40"
tracing-web = "0.1.3"
Expand Down
106 changes: 98 additions & 8 deletions noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ use std::collections::BTreeMap;
use acvm::acir::circuit::ErrorSelector;
use acvm::AcirField;
use iter_extended::vecmap;
use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue};
use noirc_frontend::ast::Visibility;
use noirc_abi::{
Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign,
};
use noirc_frontend::ast::{Signedness, Visibility};
use noirc_frontend::{
hir::Context,
hir_def::{expr::HirArrayLiteral, function::Param, stmt::HirPattern, types::Type},
macros_api::{HirExpression, HirLiteral},
node_interner::{FuncId, NodeInterner},
};
use noirc_frontend::{TypeBinding, TypeVariableKind};

/// Arranges a function signature and a generated circuit's return witnesses into a
/// `noirc_abi::Abi`.
Expand All @@ -21,15 +24,102 @@ pub(super) fn gen_abi(
error_types: BTreeMap<ErrorSelector, Type>,
) -> Abi {
let (parameters, return_type) = compute_function_abi(context, func_id);
let return_type = return_type
.map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() });
let return_type = return_type.map(|typ| AbiReturnType {
abi_type: typ,
visibility: to_abi_visibility(return_visibility),
});
let error_types = error_types
.into_iter()
.map(|(selector, typ)| (selector, AbiErrorType::from_type(context, &typ)))
.map(|(selector, typ)| (selector, build_abi_error_type(context, &typ)))
.collect();
Abi { parameters, return_type, error_types }
}

fn build_abi_error_type(context: &Context, typ: &Type) -> AbiErrorType {
match typ {
Type::FmtString(len, item_types) => {
let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length");
let Type::Tuple(item_types) = item_types.as_ref() else {
unreachable!("FmtString items must be a tuple")
};
let item_types =
item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect();
AbiErrorType::FmtString { length, item_types }
}
_ => AbiErrorType::Custom(abi_type_from_hir_type(context, typ)),
}
}

pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
match typ {
Type::FieldElement => AbiType::Field,
Type::Array(size, typ) => {
let length = size
.evaluate_to_u32()
.expect("Cannot have variable sized arrays as a parameter to main");
let typ = typ.as_ref();
AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) }
}
Type::Integer(sign, bit_width) => {
let sign = match sign {
Signedness::Unsigned => Sign::Unsigned,
Signedness::Signed => Sign::Signed,
};

AbiType::Integer { sign, width: (*bit_width).into() }
}
Type::TypeVariable(binding, TypeVariableKind::IntegerOrField)
| Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() {
TypeBinding::Bound(typ) => abi_type_from_hir_type(context, typ),
TypeBinding::Unbound(_) => {
abi_type_from_hir_type(context, &Type::default_int_or_field_type())
}
},
Type::Bool => AbiType::Boolean,
Type::String(size) => {
let size = size
.evaluate_to_u32()
.expect("Cannot have variable sized strings as a parameter to main");
AbiType::String { length: size }
}

Type::Struct(def, args) => {
let struct_type = def.borrow();
let fields = struct_type.get_fields(args);
let fields =
vecmap(fields, |(name, typ)| (name, abi_type_from_hir_type(context, &typ)));
// For the ABI, we always want to resolve the struct paths from the root crate
let path = context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id);
AbiType::Struct { fields, path }
}
Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)),
Type::Tuple(fields) => {
let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ));
AbiType::Tuple { fields }
}
Type::Error
| Type::Unit
| Type::Constant(_)
| Type::TraitAsType(..)
| Type::TypeVariable(_, _)
| Type::NamedGeneric(..)
| Type::Forall(..)
| Type::Code
| Type::Slice(_)
| Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"),
Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"),
Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"),
}
}

fn to_abi_visibility(value: Visibility) -> AbiVisibility {
match value {
Visibility::Public => AbiVisibility::Public,
Visibility::Private => AbiVisibility::Private,
Visibility::DataBus => AbiVisibility::DataBus,
}
}

pub(super) fn compute_function_abi(
context: &Context,
func_id: &FuncId,
Expand All @@ -38,7 +128,7 @@ pub(super) fn compute_function_abi(

let (parameters, return_type) = func_meta.function_signature();
let parameters = into_abi_params(context, parameters);
let return_type = return_type.map(|typ| AbiType::from_type(context, &typ));
let return_type = return_type.map(|typ| abi_type_from_hir_type(context, &typ));
(parameters, return_type)
}

Expand All @@ -58,8 +148,8 @@ fn into_abi_params(context: &Context, params: Vec<Param>) -> Vec<AbiParameter> {
let param_name = get_param_name(&pattern, &context.def_interner)
.expect("Abi for tuple and struct parameters is unimplemented")
.to_owned();
let as_abi = AbiType::from_type(context, &typ);
AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() }
let as_abi = abi_type_from_hir_type(context, &typ);
AbiParameter { name: param_name, typ: as_abi, visibility: to_abi_visibility(vis) }
})
}

Expand Down
4 changes: 2 additions & 2 deletions noir/noir-repo/compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#![warn(unreachable_pub)]
#![warn(clippy::semicolon_if_nothing_returned)]

use abi_gen::value_from_hir_expression;
use abi_gen::{abi_type_from_hir_type, value_from_hir_expression};
use acvm::acir::circuit::ExpressionWidth;
use clap::Args;
use fm::{FileId, FileManager};
Expand Down Expand Up @@ -468,7 +468,7 @@ fn compile_contract_inner(
let typ = context.def_interner.get_struct(struct_id);
let typ = typ.borrow();
let fields = vecmap(typ.get_fields(&[]), |(name, typ)| {
(name, AbiType::from_type(context, &typ))
(name, abi_type_from_hir_type(context, &typ))
});
let path =
context.fully_qualified_struct_path(context.root_crate_id(), typ.id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,6 @@ pub(super) fn recursive_non_entrypoint_function(
}
}

/// Test functions cannot have arguments in order to be executable.
pub(super) fn test_function_with_args(func: &NoirFunction) -> Option<ResolverError> {
if func.attributes().is_test_function() && !func.parameters().is_empty() {
Some(ResolverError::TestFunctionHasParameters { span: func.name_ident().span() })
} else {
None
}
}

/// Check that we are not passing a mutable reference from a constrained runtime to an unconstrained runtime.
pub(super) fn unconstrained_function_args(
function_args: &[(Type, ExprId, Span)],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,6 @@ impl<'context> Elaborator<'context> {
self.run_lint(|elaborator| {
lints::low_level_function_outside_stdlib(func, elaborator.crate_id).map(Into::into)
});
self.run_lint(|_| lints::test_function_with_args(func).map(Into::into));
self.run_lint(|_| {
lints::recursive_non_entrypoint_function(func, is_entry_point).map(Into::into)
});
Expand Down
Loading

0 comments on commit 255d752

Please sign in to comment.