Skip to content

Commit

Permalink
feat: Add array_refcount and slice_refcount builtins for debugging (
Browse files Browse the repository at this point in the history
noir-lang/noir#6584)

chore!: Require types of globals to be specified (noir-lang/noir#6592)
fix: don't report visibility errors when elaborating comptime value (noir-lang/noir#6498)
fix: preserve newlines between comments when formatting statements (noir-lang/noir#6601)
fix: parse a bit more SSA stuff (noir-lang/noir#6599)
chore!: remove eddsa from stdlib (noir-lang/noir#6591)
chore: Typo in oracles how to (noir-lang/noir#6598)
feat(ssa): Loop invariant code motion (noir-lang/noir#6563)
fix: remove `compiler_version` from new `Nargo.toml` (noir-lang/noir#6590)
feat: Avoid incrementing reference counts in some cases (noir-lang/noir#6568)
chore: fix typo in test name (noir-lang/noir#6589)
fix: consider prereleases to be compatible with pre-1.0.0 releases (noir-lang/noir#6580)
feat: try to inline brillig calls with all constant arguments  (noir-lang/noir#6548)
fix: correct type when simplifying `derive_pedersen_generators` (noir-lang/noir#6579)
feat: Sync from aztec-packages (noir-lang/noir#6576)
  • Loading branch information
AztecBot committed Nov 23, 2024
2 parents d5e150c + 4fe76c4 commit ee7a338
Show file tree
Hide file tree
Showing 86 changed files with 1,076 additions and 436 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7216f0829dcece948d3243471e6d57380522e997
45eb7568d56b2d254453b85f236d554232aa5df9
7 changes: 7 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2762,6 +2762,13 @@ impl<'a> Context<'a> {
Intrinsic::FieldLessThan => {
unreachable!("FieldLessThan can only be called in unconstrained")
}
Intrinsic::ArrayRefCount | Intrinsic::SliceRefCount => {
let zero = self.acir_context.add_constant(FieldElement::zero());
Ok(vec![AcirValue::Var(
zero,
AcirType::NumericType(NumericType::Unsigned { bit_size: 32 }),
)])
}
}
}

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,18 @@ impl Context {
| Intrinsic::IsUnconstrained => {}
Intrinsic::ArrayLen
| Intrinsic::ArrayAsStrUnchecked
| Intrinsic::ArrayRefCount
| Intrinsic::AsField
| Intrinsic::AsSlice
| Intrinsic::BlackBox(..)
| Intrinsic::DerivePedersenGenerators
| Intrinsic::FromField
| Intrinsic::SliceInsert
| Intrinsic::SlicePushBack
| Intrinsic::SlicePushFront
| Intrinsic::SlicePopBack
| Intrinsic::SlicePopFront
| Intrinsic::SliceInsert
| Intrinsic::SliceRefCount
| Intrinsic::SliceRemove
| Intrinsic::StaticAssert
| Intrinsic::StrAsBytes
Expand Down
10 changes: 10 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub(crate) enum Intrinsic {
IsUnconstrained,
DerivePedersenGenerators,
FieldLessThan,
ArrayRefCount,
SliceRefCount,
}

impl std::fmt::Display for Intrinsic {
Expand Down Expand Up @@ -100,6 +102,8 @@ impl std::fmt::Display for Intrinsic {
Intrinsic::IsUnconstrained => write!(f, "is_unconstrained"),
Intrinsic::DerivePedersenGenerators => write!(f, "derive_pedersen_generators"),
Intrinsic::FieldLessThan => write!(f, "field_less_than"),
Intrinsic::ArrayRefCount => write!(f, "array_refcount"),
Intrinsic::SliceRefCount => write!(f, "slice_refcount"),
}
}
}
Expand All @@ -113,6 +117,10 @@ impl Intrinsic {
Intrinsic::AssertConstant
| Intrinsic::StaticAssert
| Intrinsic::ApplyRangeConstraint
// Array & slice ref counts are treated as having side effects since they operate
// on hidden variables on otherwise identical array values.
| Intrinsic::ArrayRefCount
| Intrinsic::SliceRefCount
| Intrinsic::AsWitness => true,

// These apply a constraint that the input must fit into a specified number of limbs.
Expand Down Expand Up @@ -171,6 +179,8 @@ impl Intrinsic {
"is_unconstrained" => Some(Intrinsic::IsUnconstrained),
"derive_pedersen_generators" => Some(Intrinsic::DerivePedersenGenerators),
"field_less_than" => Some(Intrinsic::FieldLessThan),
"array_refcount" => Some(Intrinsic::ArrayRefCount),
"slice_refcount" => Some(Intrinsic::SliceRefCount),

other => BlackBoxFunc::lookup(other).map(Intrinsic::BlackBox),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ pub(super) fn simplify_call(
SimplifyResult::None
}
}
Intrinsic::ArrayRefCount => SimplifyResult::None,
Intrinsic::SliceRefCount => SimplifyResult::None,
}
}

Expand Down
4 changes: 2 additions & 2 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,13 +272,13 @@ fn display_constrain_error(
) -> Result {
match error {
ConstrainError::StaticString(assert_message_string) => {
writeln!(f, " '{assert_message_string:?}'")
writeln!(f, ", {assert_message_string:?}")
}
ConstrainError::Dynamic(_, is_string, values) => {
if let Some(constant_string) =
try_to_extract_string_from_error_payload(*is_string, values, &function.dfg)
{
writeln!(f, " '{}'", constant_string)
writeln!(f, ", {constant_string:?}")
} else {
writeln!(f, ", data {}", value_list(function, values))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ impl Context {
| Intrinsic::AsWitness
| Intrinsic::IsUnconstrained
| Intrinsic::DerivePedersenGenerators
| Intrinsic::ArrayRefCount
| Intrinsic::SliceRefCount
| Intrinsic::FieldLessThan => false,
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ fn slice_capacity_change(
| Intrinsic::DerivePedersenGenerators
| Intrinsic::ToBits(_)
| Intrinsic::ToRadix(_)
| Intrinsic::ArrayRefCount
| Intrinsic::SliceRefCount
| Intrinsic::FieldLessThan => SizeChange::None,
}
}
7 changes: 7 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub(crate) enum ParsedInstruction {
Constrain {
lhs: ParsedValue,
rhs: ParsedValue,
assert_message: Option<AssertMessage>,
},
DecrementRc {
value: ParsedValue,
Expand Down Expand Up @@ -129,6 +130,12 @@ pub(crate) enum ParsedInstruction {
},
}

#[derive(Debug)]
pub(crate) enum AssertMessage {
Static(String),
Dynamic(Vec<ParsedValue>),
}

#[derive(Debug)]
pub(crate) enum ParsedTerminator {
Jmp { destination: Identifier, arguments: Vec<ParsedValue> },
Expand Down
41 changes: 34 additions & 7 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
use std::collections::HashMap;

use acvm::acir::circuit::ErrorSelector;

use crate::ssa::{
function_builder::FunctionBuilder,
ir::{basic_block::BasicBlockId, function::FunctionId, value::ValueId},
ir::{
basic_block::BasicBlockId, function::FunctionId, instruction::ConstrainError,
value::ValueId,
},
};

use super::{
Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedSsa, ParsedTerminator,
ParsedValue, RuntimeType, Ssa, SsaError,
ast::AssertMessage, Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedSsa,
ParsedTerminator, ParsedValue, RuntimeType, Ssa, SsaError,
};

impl ParsedSsa {
Expand All @@ -31,6 +36,8 @@ struct Translator {
/// passes already which replaced some of the original IDs. The translator
/// will recreate the SSA step by step, which can result in a new ID layout.
variables: HashMap<FunctionId, HashMap<String, ValueId>>,

error_selector_counter: u64,
}

impl Translator {
Expand Down Expand Up @@ -64,8 +71,13 @@ impl Translator {
functions.insert(function.internal_name.clone(), function_id);
}

let mut translator =
Self { builder, functions, variables: HashMap::new(), blocks: HashMap::new() };
let mut translator = Self {
builder,
functions,
variables: HashMap::new(),
blocks: HashMap::new(),
error_selector_counter: 0,
};
translator.translate_function_body(main_function)?;

Ok(translator)
Expand Down Expand Up @@ -198,10 +210,25 @@ impl Translator {
let value_id = self.builder.insert_cast(lhs, typ);
self.define_variable(target, value_id)?;
}
ParsedInstruction::Constrain { lhs, rhs } => {
ParsedInstruction::Constrain { lhs, rhs, assert_message } => {
let lhs = self.translate_value(lhs)?;
let rhs = self.translate_value(rhs)?;
self.builder.insert_constrain(lhs, rhs, None);
let assert_message = match assert_message {
Some(AssertMessage::Static(string)) => {
Some(ConstrainError::StaticString(string))
}
Some(AssertMessage::Dynamic(values)) => {
let error_selector = ErrorSelector::new(self.error_selector_counter);
self.error_selector_counter += 1;

let is_string_type = false;
let values = self.translate_values(values)?;

Some(ConstrainError::Dynamic(error_selector, is_string_type, values))
}
None => None,
};
self.builder.insert_constrain(lhs, rhs, assert_message);
}
ParsedInstruction::DecrementRc { value } => {
let value = self.translate_value(value)?;
Expand Down
46 changes: 45 additions & 1 deletion noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ impl<'a> Lexer<'a> {
Some('&') => self.single_char_token(Token::Ampersand),
Some('-') if self.peek_char() == Some('>') => self.double_char_token(Token::Arrow),
Some('-') => self.single_char_token(Token::Dash),
Some('"') => self.eat_string_literal(),
Some(ch) if ch.is_ascii_alphanumeric() || ch == '_' => self.eat_alpha_numeric(ch),
Some(char) => Err(LexerError::UnexpectedCharacter {
char,
Expand Down Expand Up @@ -177,6 +178,41 @@ impl<'a> Lexer<'a> {
Ok(integer_token.into_span(start, end))
}

fn eat_string_literal(&mut self) -> SpannedTokenResult {
let start = self.position;
let mut string = String::new();

while let Some(next) = self.next_char() {
let char = match next {
'"' => break,
'\\' => match self.next_char() {
Some('r') => '\r',
Some('n') => '\n',
Some('t') => '\t',
Some('0') => '\0',
Some('"') => '"',
Some('\\') => '\\',
Some(escaped) => {
let span = Span::inclusive(start, self.position);
return Err(LexerError::InvalidEscape { escaped, span });
}
None => {
let span = Span::inclusive(start, self.position);
return Err(LexerError::UnterminatedStringLiteral { span });
}
},
other => other,
};

string.push(char);
}

let str_literal_token = Token::Str(string);

let end = self.position;
Ok(str_literal_token.into_span(start, end))
}

fn eat_while<F: Fn(char) -> bool>(
&mut self,
initial_char: Option<char>,
Expand Down Expand Up @@ -247,14 +283,22 @@ pub(crate) enum LexerError {
InvalidIntegerLiteral { span: Span, found: String },
#[error("Integer literal too large")]
IntegerLiteralTooLarge { span: Span, limit: String },
#[error("Unterminated string literal")]
UnterminatedStringLiteral { span: Span },
#[error(
"'\\{escaped}' is not a valid escape sequence. Use '\\' for a literal backslash character."
)]
InvalidEscape { escaped: char, span: Span },
}

impl LexerError {
pub(crate) fn span(&self) -> Span {
match self {
LexerError::UnexpectedCharacter { span, .. }
| LexerError::InvalidIntegerLiteral { span, .. }
| LexerError::IntegerLiteralTooLarge { span, .. } => *span,
| LexerError::IntegerLiteralTooLarge { span, .. }
| LexerError::UnterminatedStringLiteral { span }
| LexerError::InvalidEscape { span, .. } => *span,
}
}
}
45 changes: 42 additions & 3 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use super::{

use acvm::{AcirField, FieldElement};
use ast::{
Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedParameter, ParsedSsa,
ParsedValue,
AssertMessage, Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedParameter,
ParsedSsa, ParsedValue,
};
use lexer::{Lexer, LexerError};
use noirc_errors::Span;
Expand Down Expand Up @@ -313,7 +313,20 @@ impl<'a> Parser<'a> {
let lhs = self.parse_value_or_error()?;
self.eat_or_error(Token::Equal)?;
let rhs = self.parse_value_or_error()?;
Ok(Some(ParsedInstruction::Constrain { lhs, rhs }))

let assert_message = if self.eat(Token::Comma)? {
if let Some(str) = self.eat_str()? {
Some(AssertMessage::Static(str))
} else if self.eat_keyword(Keyword::Data)? {
Some(AssertMessage::Dynamic(self.parse_comma_separated_values()?))
} else {
return self.expected_string_or_data();
}
} else {
None
};

Ok(Some(ParsedInstruction::Constrain { lhs, rhs, assert_message }))
}

fn parse_decrement_rc(&mut self) -> ParseResult<Option<ParsedInstruction>> {
Expand Down Expand Up @@ -654,6 +667,10 @@ impl<'a> Parser<'a> {
return Ok(Type::Reference(Arc::new(typ)));
}

if self.eat_keyword(Keyword::Function)? {
return Ok(Type::Function);
}

self.expected_type()
}

Expand Down Expand Up @@ -767,6 +784,18 @@ impl<'a> Parser<'a> {
}
}

fn eat_str(&mut self) -> ParseResult<Option<String>> {
if matches!(self.token.token(), Token::Str(..)) {
let token = self.bump()?;
match token.into_token() {
Token::Str(string) => Ok(Some(string)),
_ => unreachable!(),
}
} else {
Ok(None)
}
}

fn eat(&mut self, token: Token) -> ParseResult<bool> {
if self.token.token() == &token {
self.bump()?;
Expand Down Expand Up @@ -812,6 +841,13 @@ impl<'a> Parser<'a> {
})
}

fn expected_string_or_data<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedStringOrData {
found: self.token.token().clone(),
span: self.token.to_span(),
})
}

fn expected_identifier<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedIdentifier {
found: self.token.token().clone(),
Expand Down Expand Up @@ -873,6 +909,8 @@ pub(crate) enum ParserError {
ExpectedType { found: Token, span: Span },
#[error("Expected an instruction or terminator, found '{found}'")]
ExpectedInstructionOrTerminator { found: Token, span: Span },
#[error("Expected a string literal or 'data', found '{found}'")]
ExpectedStringOrData { found: Token, span: Span },
#[error("Expected a value, found '{found}'")]
ExpectedValue { found: Token, span: Span },
#[error("Multiple return values only allowed for call")]
Expand All @@ -889,6 +927,7 @@ impl ParserError {
| ParserError::ExpectedInt { span, .. }
| ParserError::ExpectedType { span, .. }
| ParserError::ExpectedInstructionOrTerminator { span, .. }
| ParserError::ExpectedStringOrData { span, .. }
| ParserError::ExpectedValue { span, .. } => *span,
ParserError::MultipleReturnValuesOnlyAllowedForCall { second_target, .. } => {
second_target.span
Expand Down
Loading

0 comments on commit ee7a338

Please sign in to comment.