Skip to content

Commit

Permalink
Merge branch 'master' into tf/require-unsafe-blocks
Browse files Browse the repository at this point in the history
* master:
  chore: simplify a couple of enum variants (#7025)
  chore: disallow inserting ACIR-only instructions into brillig functions (#7017)
  feat: unchecked math operations in SSA (#7011)
  chore: delete docs for versions which aren't used (#7020)
  feat!: Disable mocks in `execute` (#6869)
  chore(docs): backport 1.0.0-beta.0 doc fixes (#7014)
  feat(cli): Add CLI option to filter by contract function name (#7018)
  chore: Add more Field use info (#7019)
  fix: let static_assert fail with the provided message (#7005)
  chore: mark `aztec-nr` as expected to compile (#7015)
  chore: clarity fix in docs (#7016)
  • Loading branch information
TomAFrench committed Jan 10, 2025
2 parents a1fa88b + 65e1cba commit 1d04f95
Show file tree
Hide file tree
Showing 944 changed files with 867 additions and 89,997 deletions.
23 changes: 20 additions & 3 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@ pub struct CompileOptions {
/// Only show SSA passes whose name contains the provided string.
/// This setting takes precedence over `show_ssa` if it's not empty.
#[arg(long, hide = true)]
pub show_ssa_pass_name: Option<String>,
pub show_ssa_pass: Option<String>,

/// Only show the SSA and ACIR for the contract function with a given name.
#[arg(long, hide = true)]
pub show_contract_fn: Option<String>,

/// Emit the unoptimized SSA IR to file.
/// The IR will be dumped into the workspace target directory,
Expand Down Expand Up @@ -442,6 +446,11 @@ pub fn compile_contract(

if options.print_acir {
for contract_function in &compiled_contract.functions {
if let Some(ref name) = options.show_contract_fn {
if name != &contract_function.name {
continue;
}
}
println!(
"Compiled ACIR for {}::{} (unoptimized):",
compiled_contract.name, contract_function.name
Expand Down Expand Up @@ -486,7 +495,15 @@ fn compile_contract_inner(
continue;
}

let function = match compile_no_check(context, options, function_id, None, true) {
let mut options = options.clone();

if let Some(ref name_filter) = options.show_contract_fn {
let show = name == *name_filter;
options.show_ssa &= show;
options.show_ssa_pass = options.show_ssa_pass.filter(|_| show);
};

let function = match compile_no_check(context, &options, function_id, None, true) {
Ok(function) => function,
Err(new_error) => {
errors.push(FileDiagnostic::from(new_error));
Expand Down Expand Up @@ -642,7 +659,7 @@ pub fn compile_no_check(

let return_visibility = program.return_visibility;
let ssa_evaluator_options = noirc_evaluator::ssa::SsaEvaluatorOptions {
ssa_logging: match &options.show_ssa_pass_name {
ssa_logging: match &options.show_ssa_pass {
Some(string) => SsaLogging::Contains(string.clone()),
None => {
if options.show_ssa {
Expand Down
14 changes: 9 additions & 5 deletions compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1949,9 +1949,9 @@ impl<'a> Context<'a> {
let bit_count = binary_type.bit_size::<FieldElement>();
let num_type = binary_type.to_numeric_type();
let result = match binary.operator {
BinaryOp::Add => self.acir_context.add_var(lhs, rhs),
BinaryOp::Sub => self.acir_context.sub_var(lhs, rhs),
BinaryOp::Mul => self.acir_context.mul_var(lhs, rhs),
BinaryOp::Add { .. } => self.acir_context.add_var(lhs, rhs),
BinaryOp::Sub { .. } => self.acir_context.sub_var(lhs, rhs),
BinaryOp::Mul { .. } => self.acir_context.mul_var(lhs, rhs),
BinaryOp::Div => self.acir_context.div_var(
lhs,
rhs,
Expand Down Expand Up @@ -2070,7 +2070,7 @@ impl<'a> Context<'a> {
Value::Instruction { instruction, .. } => {
if matches!(
&dfg[*instruction],
Instruction::Binary(Binary { operator: BinaryOp::Sub, .. })
Instruction::Binary(Binary { operator: BinaryOp::Sub { .. }, .. })
) {
// Subtractions must first have the integer modulus added before truncation can be
// applied. This is done in order to prevent underflow.
Expand Down Expand Up @@ -3159,7 +3159,11 @@ mod test {
let func_with_nested_call_v1 = builder.add_parameter(Type::field());

let two = builder.field_constant(2u128);
let v0_plus_two = builder.insert_binary(func_with_nested_call_v0, BinaryOp::Add, two);
let v0_plus_two = builder.insert_binary(
func_with_nested_call_v0,
BinaryOp::Add { unchecked: false },
two,
);

let foo_id = Id::test_new(2);
let foo_call = builder.import_function(foo_id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ impl<'block> BrilligBlock<'block> {
self.brillig_context.deallocate_register(rc_register);
}
Instruction::EnableSideEffectsIf { .. } => {
todo!("enable_side_effects not supported by brillig")
unreachable!("enable_side_effects not supported by brillig")
}
Instruction::IfElse { .. } => {
unreachable!("IfElse instructions should not be possible in brillig")
Expand Down Expand Up @@ -1318,9 +1318,9 @@ impl<'block> BrilligBlock<'block> {
BrilligBinaryOp::Modulo
}
}
BinaryOp::Add => BrilligBinaryOp::Add,
BinaryOp::Sub => BrilligBinaryOp::Sub,
BinaryOp::Mul => BrilligBinaryOp::Mul,
BinaryOp::Add { .. } => BrilligBinaryOp::Add,
BinaryOp::Sub { .. } => BrilligBinaryOp::Sub,
BinaryOp::Mul { .. } => BrilligBinaryOp::Mul,
BinaryOp::Eq => BrilligBinaryOp::Equals,
BinaryOp::Lt => {
if is_signed {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,14 @@ mod test {
builder.switch_to_block(b2);

let twenty_seven = builder.field_constant(27u128);
let v7 = builder.insert_binary(v0, BinaryOp::Add, twenty_seven);
let v7 = builder.insert_binary(v0, BinaryOp::Add { unchecked: false }, twenty_seven);
builder.insert_store(v3, v7);

builder.terminate_with_jmp(b3, vec![]);

builder.switch_to_block(b1);

let v6 = builder.insert_binary(v1, BinaryOp::Add, twenty_seven);
let v6 = builder.insert_binary(v1, BinaryOp::Add { unchecked: false }, twenty_seven);
builder.insert_store(v3, v6);

builder.terminate_with_jmp(b3, vec![]);
Expand Down Expand Up @@ -501,7 +501,7 @@ mod test {

builder.switch_to_block(b2);

let v6 = builder.insert_binary(v4, BinaryOp::Mul, v4);
let v6 = builder.insert_binary(v4, BinaryOp::Mul { unchecked: false }, v4);

builder.terminate_with_jmp(b4, vec![v0]);

Expand All @@ -526,7 +526,7 @@ mod test {

let v12 = builder.insert_load(v3, Type::field());

let v13 = builder.insert_binary(v12, BinaryOp::Add, v6);
let v13 = builder.insert_binary(v12, BinaryOp::Add { unchecked: false }, v6);

builder.insert_store(v3, v13);

Expand All @@ -535,13 +535,13 @@ mod test {
builder.switch_to_block(b8);

let one = builder.field_constant(1u128);
let v15 = builder.insert_binary(v7, BinaryOp::Add, one);
let v15 = builder.insert_binary(v7, BinaryOp::Add { unchecked: false }, one);

builder.terminate_with_jmp(b4, vec![v15]);

builder.switch_to_block(b6);

let v16 = builder.insert_binary(v4, BinaryOp::Add, one);
let v16 = builder.insert_binary(v4, BinaryOp::Add { unchecked: false }, one);

builder.terminate_with_jmp(b1, vec![v16]);

Expand Down
6 changes: 3 additions & 3 deletions compiler/noirc_evaluator/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub enum RuntimeError {
StaticAssertDynamicMessage { call_stack: CallStack },
#[error("Argument is dynamic")]
StaticAssertDynamicPredicate { call_stack: CallStack },
#[error("Argument is false")]
StaticAssertFailed { call_stack: CallStack },
#[error("{message}")]
StaticAssertFailed { message: String, call_stack: CallStack },
#[error("Nested slices, i.e. slices within an array or slice, are not supported")]
NestedSlice { call_stack: CallStack },
#[error("Big Integer modulus do no match")]
Expand Down Expand Up @@ -165,7 +165,7 @@ impl RuntimeError {
| RuntimeError::AssertConstantFailed { call_stack }
| RuntimeError::StaticAssertDynamicMessage { call_stack }
| RuntimeError::StaticAssertDynamicPredicate { call_stack }
| RuntimeError::StaticAssertFailed { call_stack }
| RuntimeError::StaticAssertFailed { call_stack, .. }
| RuntimeError::IntegerOutOfBounds { call_stack, .. }
| RuntimeError::UnsupportedIntegerSize { call_stack, .. }
| RuntimeError::InvalidBlackBoxInputBitSize { call_stack, .. }
Expand Down
8 changes: 0 additions & 8 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,6 @@ impl FunctionBuilder {
operator: BinaryOp,
rhs: ValueId,
) -> ValueId {
let lhs_type = self.type_of_value(lhs);
let rhs_type = self.type_of_value(rhs);
if operator != BinaryOp::Shl && operator != BinaryOp::Shr {
assert_eq!(
lhs_type, rhs_type,
"ICE - Binary instruction operands must have the same type"
);
}
let instruction = Instruction::Binary(Binary { lhs, rhs, operator });
self.insert_instruction(instruction, None).first()
}
Expand Down
34 changes: 32 additions & 2 deletions compiler/noirc_evaluator/src/ssa/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use iter_extended::vecmap;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use serde_with::DisplayFromStr;
use tracing::warn;

/// The DataFlowGraph contains most of the actual data in a function including
/// its blocks, instructions, and values. This struct is largely responsible for
Expand Down Expand Up @@ -181,7 +182,16 @@ impl DataFlowGraph {

/// Check if the function runtime would simply ignore this instruction.
pub(crate) fn is_handled_by_runtime(&self, instruction: &Instruction) -> bool {
!(self.runtime().is_acir() && instruction.is_brillig_only())
match self.runtime() {
RuntimeType::Acir(_) => !matches!(
instruction,
Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. }
),
RuntimeType::Brillig(_) => !matches!(
instruction,
Instruction::EnableSideEffectsIf { .. } | Instruction::IfElse { .. }
),
}
}

fn insert_instruction_without_simplification(
Expand All @@ -205,7 +215,7 @@ impl DataFlowGraph {
call_stack: CallStackId,
) -> InsertInstructionResult {
if !self.is_handled_by_runtime(&instruction_data) {
return InsertInstructionResult::InstructionRemoved;
panic!("Attempted to insert instruction not handled by runtime: {instruction_data:?}");
}

let id = self.insert_instruction_without_simplification(
Expand All @@ -228,8 +238,10 @@ impl DataFlowGraph {
call_stack: CallStackId,
) -> InsertInstructionResult {
if !self.is_handled_by_runtime(&instruction) {
warn!("Attempted to insert instruction not handled by runtime: {instruction:?}");
return InsertInstructionResult::InstructionRemoved;
}

match instruction.simplify(self, block, ctrl_typevars.clone(), call_stack) {
SimplifyResult::SimplifiedTo(simplification) => {
InsertInstructionResult::SimplifiedTo(simplification)
Expand Down Expand Up @@ -525,6 +537,24 @@ impl DataFlowGraph {
}
}

/// If this value points to an array of constant bytes, returns a string
/// consisting of those bytes if they form a valid UTF-8 string.
pub(crate) fn get_string(&self, value: ValueId) -> Option<String> {
let (value_ids, _typ) = self.get_array_constant(value)?;

let mut bytes = Vec::new();
for value_id in value_ids {
let field_value = self.get_numeric_constant(value_id)?;
let u64_value = field_value.try_to_u64()?;
if u64_value > 255 {
return None;
};
let byte = u64_value as u8;
bytes.push(byte);
}
String::from_utf8(bytes).ok()
}

/// A constant index less than the array length is safe
pub(crate) fn is_safe_index(&self, index: ValueId, array: ValueId) -> bool {
#[allow(clippy::match_like_matches_macro)]
Expand Down
30 changes: 16 additions & 14 deletions compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,15 @@ impl Instruction {

// Some binary math can overflow or underflow
Binary(binary) => match binary.operator {
BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => {
true
}
BinaryOp::Eq
BinaryOp::Add { unchecked: false }
| BinaryOp::Sub { unchecked: false }
| BinaryOp::Mul { unchecked: false }
| BinaryOp::Div
| BinaryOp::Mod => true,
BinaryOp::Add { unchecked: true }
| BinaryOp::Sub { unchecked: true }
| BinaryOp::Mul { unchecked: true }
| BinaryOp::Eq
| BinaryOp::Lt
| BinaryOp::And
| BinaryOp::Or
Expand Down Expand Up @@ -566,16 +571,19 @@ impl Instruction {
match self {
Instruction::Binary(binary) => {
match binary.operator {
BinaryOp::Add
| BinaryOp::Sub
| BinaryOp::Mul
BinaryOp::Add { unchecked: false }
| BinaryOp::Sub { unchecked: false }
| BinaryOp::Mul { unchecked: false }
| BinaryOp::Div
| BinaryOp::Mod => {
// Some binary math can overflow or underflow, but this is only the case
// for unsigned types (here we assume the type of binary.lhs is the same)
dfg.type_of_value(binary.rhs).is_unsigned()
}
BinaryOp::Eq
BinaryOp::Add { unchecked: true }
| BinaryOp::Sub { unchecked: true }
| BinaryOp::Mul { unchecked: true }
| BinaryOp::Eq
| BinaryOp::Lt
| BinaryOp::And
| BinaryOp::Or
Expand Down Expand Up @@ -1058,12 +1066,6 @@ impl Instruction {
Instruction::Noop => Remove,
}
}

/// Some instructions are only to be used in Brillig and should be eliminated
/// after runtime separation, never to be be reintroduced in an ACIR runtime.
pub(crate) fn is_brillig_only(&self) -> bool {
matches!(self, Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. })
}
}

/// Given a chain of operations like:
Expand Down
Loading

0 comments on commit 1d04f95

Please sign in to comment.