Skip to content

Commit

Permalink
Merge branch 'master' into 6443-fix-ssa-mem2reg-mut-ref
Browse files Browse the repository at this point in the history
  • Loading branch information
aakoshh authored Nov 5, 2024
2 parents c3816a3 + 8b5afec commit 84f8d7c
Show file tree
Hide file tree
Showing 55 changed files with 1,891 additions and 781 deletions.
20 changes: 17 additions & 3 deletions compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use iter_extended::vecmap;
use noirc_abi::{
Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign,
};
use noirc_errors::Span;
use noirc_frontend::ast::{Signedness, Visibility};
use noirc_frontend::TypeBinding;
use noirc_frontend::{
Expand Down Expand Up @@ -39,10 +40,20 @@ pub(super) fn gen_abi(
Abi { parameters, return_type, error_types }
}

// Get the Span of the root crate's main function, or else a dummy span if that fails
fn get_main_function_span(context: &Context) -> Span {
if let Some(func_id) = context.get_main_function(context.root_crate_id()) {
context.function_meta(&func_id).location.span
} else {
Span::default()
}
}

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 span = get_main_function_span(context);
let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length");
let Type::Tuple(item_types) = item_types.as_ref() else {
unreachable!("FmtString items must be a tuple")
};
Expand All @@ -58,8 +69,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
match typ {
Type::FieldElement => AbiType::Field,
Type::Array(size, typ) => {
let span = get_main_function_span(context);
let length = size
.evaluate_to_u32()
.evaluate_to_u32(span)
.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)) }
Expand All @@ -86,8 +98,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
}
Type::Bool => AbiType::Boolean,
Type::String(size) => {
let span = get_main_function_span(context);
let size = size
.evaluate_to_u32()
.evaluate_to_u32(span)
.expect("Cannot have variable sized strings as a parameter to main");
AbiType::String { length: size }
}
Expand All @@ -102,6 +115,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
AbiType::Struct { fields, path }
}
Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)),
Type::CheckedCast { to, .. } => abi_type_from_hir_type(context, to),
Type::Tuple(fields) => {
let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ));
AbiType::Tuple { fields }
Expand Down
5 changes: 2 additions & 3 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,8 @@ fn compile_contract_inner(
.secondary
.iter()
.filter_map(|attr| match attr {
SecondaryAttribute::Tag(attribute) | SecondaryAttribute::Meta(attribute) => {
Some(attribute.contents.clone())
}
SecondaryAttribute::Tag(attribute) => Some(attribute.contents.clone()),
SecondaryAttribute::Meta(attribute) => Some(attribute.to_string()),
_ => None,
})
.collect();
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ fn split_public_and_private_inputs(
func_sig
.0
.iter()
.map(|(_, typ, visibility)| {
let num_field_elements_needed = typ.field_count() as usize;
.map(|(pattern, typ, visibility)| {
let num_field_elements_needed = typ.field_count(&pattern.location()) as usize;
let witnesses = input_witnesses[idx..idx + num_field_elements_needed].to_vec();
idx += num_field_elements_needed;
(visibility, witnesses)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl DataBusBuilder {
ast::Visibility::CallData(id) => DatabusVisibility::CallData(id),
ast::Visibility::ReturnData => DatabusVisibility::ReturnData,
};
let len = param.1.field_count() as usize;
let len = param.1.field_count(&param.0.location()) as usize;
params_is_databus.extend(vec![is_databus; len]);
}
params_is_databus
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ impl FunctionDefinition {
}

pub fn is_test(&self) -> bool {
if let Some(attribute) = &self.attributes.function {
if let Some(attribute) = self.attributes.function() {
matches!(attribute, FunctionAttribute::Test(..))
} else {
false
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/ast/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl NoirFunction {
&self.def.attributes
}
pub fn function_attribute(&self) -> Option<&FunctionAttribute> {
self.def.attributes.function.as_ref()
self.def.attributes.function()
}
pub fn secondary_attributes(&self) -> &[SecondaryAttribute] {
self.def.attributes.secondary.as_ref()
Expand Down Expand Up @@ -109,7 +109,7 @@ impl NoirFunction {
impl From<FunctionDefinition> for NoirFunction {
fn from(fd: FunctionDefinition) -> Self {
// The function type is determined by the existence of a function attribute
let kind = match fd.attributes.function {
let kind = match fd.attributes.function() {
Some(FunctionAttribute::Builtin(_)) => FunctionKind::Builtin,
Some(FunctionAttribute::Foreign(_)) => FunctionKind::LowLevel,
Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal,
Expand Down
21 changes: 15 additions & 6 deletions compiler/noirc_frontend/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
InternedUnresolvedTypeData, QuotedTypeId,
},
parser::{Item, ItemKind, ParsedSubModule},
token::{CustomAttribute, SecondaryAttribute, Tokens},
token::{MetaAttribute, SecondaryAttribute, Tokens},
ParsedModule, QuotedType,
};

Expand Down Expand Up @@ -474,7 +474,9 @@ pub trait Visitor {
true
}

fn visit_custom_attribute(&mut self, _: &CustomAttribute, _target: AttributeTarget) {}
fn visit_meta_attribute(&mut self, _: &MetaAttribute, _target: AttributeTarget) -> bool {
true
}
}

impl ParsedModule {
Expand Down Expand Up @@ -1441,15 +1443,22 @@ impl SecondaryAttribute {
}

pub fn accept_children(&self, target: AttributeTarget, visitor: &mut impl Visitor) {
if let SecondaryAttribute::Meta(custom) = self {
custom.accept(target, visitor);
if let SecondaryAttribute::Meta(meta_attribute) = self {
meta_attribute.accept(target, visitor);
}
}
}

impl CustomAttribute {
impl MetaAttribute {
pub fn accept(&self, target: AttributeTarget, visitor: &mut impl Visitor) {
visitor.visit_custom_attribute(self, target);
if visitor.visit_meta_attribute(self, target) {
self.accept_children(visitor);
}
}

pub fn accept_children(&self, visitor: &mut impl Visitor) {
self.name.accept(visitor);
visit_expressions(&self.arguments, visitor);
}
}

Expand Down
62 changes: 11 additions & 51 deletions compiler/noirc_frontend/src/elaborator/comptime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ use crate::{
resolution::errors::ResolverError,
},
hir_def::expr::{HirExpression, HirIdent},
lexer::Lexer,
node_interner::{DefinitionKind, DependencyId, FuncId, NodeInterner, StructId, TraitId},
parser::{Item, ItemKind, Parser},
token::SecondaryAttribute,
parser::{Item, ItemKind},
token::{MetaAttribute, SecondaryAttribute},
Type, TypeBindings, UnificationError,
};

Expand Down Expand Up @@ -162,10 +161,9 @@ impl<'context> Elaborator<'context> {
if let SecondaryAttribute::Meta(attribute) = attribute {
self.elaborate_in_comptime_context(|this| {
if let Err(error) = this.run_comptime_attribute_name_on_item(
&attribute.contents,
attribute,
item.clone(),
span,
attribute.contents_span,
attribute_context,
generated_items,
) {
Expand All @@ -177,27 +175,21 @@ impl<'context> Elaborator<'context> {

fn run_comptime_attribute_name_on_item(
&mut self,
attribute: &str,
attribute: &MetaAttribute,
item: Value,
span: Span,
attribute_span: Span,
attribute_context: AttributeContext,
generated_items: &mut CollectedItems,
) -> Result<(), (CompilationError, FileId)> {
self.file = attribute_context.attribute_file;
self.local_module = attribute_context.attribute_module;

let location = Location::new(attribute_span, self.file);
let Some((function, arguments)) = Self::parse_attribute(attribute, location)? else {
return Err((
ResolverError::UnableToParseAttribute {
attribute: attribute.to_string(),
span: attribute_span,
}
.into(),
self.file,
));
let location = Location::new(attribute.span, self.file);
let function = Expression {
kind: ExpressionKind::Variable(attribute.name.clone()),
span: attribute.span,
};
let arguments = attribute.arguments.clone();

// Elaborate the function, rolling back any errors generated in case it is unknown
let error_count = self.errors.len();
Expand All @@ -211,7 +203,7 @@ impl<'context> Elaborator<'context> {
return Err((
ResolverError::AttributeFunctionIsNotAPath {
function: function_string,
span: attribute_span,
span: attribute.span,
}
.into(),
self.file,
Expand All @@ -223,7 +215,7 @@ impl<'context> Elaborator<'context> {
return Err((
ResolverError::AttributeFunctionNotInScope {
name: function_string,
span: attribute_span,
span: attribute.span,
}
.into(),
self.file,
Expand Down Expand Up @@ -269,38 +261,6 @@ impl<'context> Elaborator<'context> {
Ok(())
}

/// Parses an attribute in the form of a function call (e.g. `#[foo(a b, c d)]`) into
/// the function and quoted arguments called (e.g. `("foo", vec![(a b, location), (c d, location)])`)
#[allow(clippy::type_complexity)]
pub(crate) fn parse_attribute(
annotation: &str,
location: Location,
) -> Result<Option<(Expression, Vec<Expression>)>, (CompilationError, FileId)> {
let (tokens, mut lexing_errors) = Lexer::lex(annotation);
if !lexing_errors.is_empty() {
return Err((lexing_errors.swap_remove(0).into(), location.file));
}

let Some(expression) = Parser::for_tokens(tokens).parse_option(Parser::parse_expression)
else {
return Ok(None);
};

let (mut func, mut arguments) = match expression.kind {
ExpressionKind::Call(call) => (*call.func, call.arguments),
ExpressionKind::Variable(_) => (expression, Vec::new()),
_ => return Ok(None),
};

func.span = func.span.shift_by(location.span.start());

for argument in &mut arguments {
argument.span = argument.span.shift_by(location.span.start());
}

Ok(Some((func, arguments)))
}

fn handle_attribute_arguments(
interpreter: &mut Interpreter,
item: &Value,
Expand Down
8 changes: 3 additions & 5 deletions compiler/noirc_frontend/src/elaborator/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub(super) fn low_level_function_outside_stdlib(
crate_id: CrateId,
) -> Option<ResolverError> {
let is_low_level_function =
modifiers.attributes.function.as_ref().map_or(false, |func| func.is_low_level());
modifiers.attributes.function().map_or(false, |func| func.is_low_level());
if !crate_id.is_stdlib() && is_low_level_function {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::LowLevelFunctionOutsideOfStdlib { ident })
Expand All @@ -81,8 +81,7 @@ pub(super) fn oracle_not_marked_unconstrained(
func: &FuncMeta,
modifiers: &FunctionModifiers,
) -> Option<ResolverError> {
let is_oracle_function =
modifiers.attributes.function.as_ref().map_or(false, |func| func.is_oracle());
let is_oracle_function = modifiers.attributes.function().map_or(false, |func| func.is_oracle());
if is_oracle_function && !modifiers.is_unconstrained {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::OracleMarkedAsConstrained { ident })
Expand All @@ -105,8 +104,7 @@ pub(super) fn oracle_called_from_constrained_function(
}

let function_attributes = interner.function_attributes(called_func);
let is_oracle_call =
function_attributes.function.as_ref().map_or(false, |func| func.is_oracle());
let is_oracle_call = function_attributes.function().map_or(false, |func| func.is_oracle());
if is_oracle_call {
Some(ResolverError::UnconstrainedOracleReturnToConstrained { span })
} else {
Expand Down
16 changes: 9 additions & 7 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use crate::{
DefinitionKind, DependencyId, ExprId, FuncId, FunctionModifiers, GlobalId, NodeInterner,
ReferenceId, StructId, TraitId, TraitImplId, TypeAliasId,
},
token::{CustomAttribute, SecondaryAttribute},
token::SecondaryAttribute,
Shared, Type, TypeVariable,
};

Expand Down Expand Up @@ -839,11 +839,6 @@ impl<'context> Elaborator<'context> {
None
};

let attributes = func.secondary_attributes().iter();
let attributes =
attributes.filter_map(|secondary_attribute| secondary_attribute.as_custom());
let attributes: Vec<CustomAttribute> = attributes.cloned().collect();

let meta = FuncMeta {
name: name_ident,
kind: func.kind,
Expand All @@ -867,7 +862,6 @@ impl<'context> Elaborator<'context> {
function_body: FunctionBody::Unresolved(func.kind, body, func.def.span),
self_type: self.self_type.clone(),
source_file: self.file,
custom_attributes: attributes,
};

self.interner.push_fn_meta(meta, func_id);
Expand Down Expand Up @@ -896,6 +890,10 @@ impl<'context> Elaborator<'context> {
Type::Alias(alias_type, generics) => {
self.mark_type_as_used(&alias_type.borrow().get_type(generics));
}
Type::CheckedCast { from, to } => {
self.mark_type_as_used(from);
self.mark_type_as_used(to);
}
Type::MutableReference(typ) => {
self.mark_type_as_used(typ);
}
Expand Down Expand Up @@ -1501,6 +1499,10 @@ impl<'context> Elaborator<'context> {
span,
);
}
Type::CheckedCast { from, to } => {
self.check_type_is_not_more_private_then_item(name, visibility, from, span);
self.check_type_is_not_more_private_then_item(name, visibility, to, span);
}
Type::Function(args, return_type, env, _) => {
for arg in args {
self.check_type_is_not_more_private_then_item(name, visibility, arg, span);
Expand Down
Loading

0 comments on commit 84f8d7c

Please sign in to comment.