Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions compiler/noirc_evaluator/src/acir/acir_context/black_box.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use acvm::acir::{AcirField, BlackBoxFunc, circuit::opcodes::FunctionInput};
use iter_extended::vecmap;

use crate::errors::{InternalError, RuntimeError};
use crate::{
errors::{InternalError, RuntimeError},
ssa::ir::types::NumericType,
};

use super::{AcirContext, AcirType, AcirValue, AcirVar};
use super::{AcirContext, AcirValue, AcirVar};

impl<F: AcirField> AcirContext<F> {
/// Calls a Blackbox function on the given inputs and returns a given set of outputs
Expand Down Expand Up @@ -60,7 +63,7 @@ impl<F: AcirField> AcirContext<F> {
}));
}
};
inputs.push(AcirValue::Var(predicate.unwrap(), AcirType::unsigned(1)));
inputs.push(AcirValue::Var(predicate.unwrap(), NumericType::bool()));
vec![proof_type_constant]
}
_ => Vec::new(),
Expand Down
25 changes: 10 additions & 15 deletions compiler/noirc_evaluator/src/acir/acir_context/brillig_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ impl<F: AcirField> AcirContext<F> {
// We can then immediately zero out all of its outputs as this is the value which would be written
// if we waited until runtime to resolve this call.
let outputs_var = vecmap(outputs, |output| match output {
AcirType::NumericType(_) => {
AcirType::NumericType(numeric_type) => {
let var = self.add_constant(F::zero());
AcirValue::Var(var, output.clone())
AcirValue::Var(var, numeric_type)
}
AcirType::Array(element_types, size) => {
self.zeroed_array_output(&element_types, size)
Expand Down Expand Up @@ -85,12 +85,12 @@ impl<F: AcirField> AcirContext<F> {

let mut brillig_outputs = Vec::new();
let outputs_var = vecmap(outputs, |output| match output {
AcirType::NumericType(_) => {
AcirType::NumericType(numeric_type) => {
let var = self.add_variable();
let witness_index =
self.var_to_witness(var).expect("variable has just been created as witness");
brillig_outputs.push(BrilligOutputs::Simple(witness_index));
AcirValue::Var(var, output.clone())
AcirValue::Var(var, numeric_type)
}
AcirType::Array(element_types, size) => {
let (acir_value, witnesses) = self.brillig_array_output(&element_types, size);
Expand All @@ -114,11 +114,7 @@ impl<F: AcirField> AcirContext<F> {
) -> Result<(), RuntimeError> {
let one = context.add_constant(G::one());
match value {
AcirValue::Var(var, typ) => {
let numeric_type = match typ {
AcirType::NumericType(numeric_type) => numeric_type,
_ => unreachable!("`AcirValue::Var` may only hold primitive values"),
};
AcirValue::Var(var, numeric_type) => {
// Predicate is one so that the constrain is always applied, because
// values returned from Brillig will be 0 under a false predicate.
context.range_constrain_var(*var, numeric_type, None, one)?;
Expand Down Expand Up @@ -166,8 +162,7 @@ impl<F: AcirField> AcirContext<F> {

let value_read_var = self.read_from_memory(block_id, &index_var)?;
let value_typ = value_types[i % value_types.len()];
let value_read =
AcirValue::Var(value_read_var, AcirType::NumericType(value_typ));
let value_read = AcirValue::Var(value_read_var, value_typ);

self.brillig_array_input(var_expressions, value_read)?;
}
Expand All @@ -187,9 +182,9 @@ impl<F: AcirField> AcirContext<F> {
self.zeroed_array_output(nested_element_types, *nested_size);
array_values.push_back(nested_acir_value);
}
AcirType::NumericType(_) => {
AcirType::NumericType(numeric_type) => {
let var = self.add_constant(F::zero());
array_values.push_back(AcirValue::Var(var, element_type.clone()));
array_values.push_back(AcirValue::Var(var, *numeric_type));
}
}
}
Expand All @@ -215,9 +210,9 @@ impl<F: AcirField> AcirContext<F> {
witnesses.append(&mut nested_witnesses);
array_values.push_back(nested_acir_value);
}
AcirType::NumericType(_) => {
AcirType::NumericType(numeric_type) => {
let var = self.add_variable();
array_values.push_back(AcirValue::Var(var, element_type.clone()));
array_values.push_back(AcirValue::Var(var, *numeric_type));
witnesses.push(
self.var_to_witness(var)
.expect("variable has just been created as witness"),
Expand Down
77 changes: 39 additions & 38 deletions compiler/noirc_evaluator/src/acir/acir_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ impl<F: AcirField> AcirContext<F> {
let results = self.stdlib_brillig_call(
predicate,
BrilligStdlibFunc::Inverse,
vec![AcirValue::Var(var, AcirType::field())],
vec![AcirType::field()],
vec![AcirValue::Var(var, NumericType::NativeField)],
vec![AcirType::NumericType(NumericType::NativeField)],
)?;
Self::expect_one_var(results)
};
Expand Down Expand Up @@ -334,7 +334,7 @@ impl<F: AcirField> AcirContext<F> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
typ: AcirType,
typ: NumericType,
) -> Result<AcirVar, RuntimeError> {
let lhs_expr = self.var_to_expression(lhs)?;
let rhs_expr = self.var_to_expression(rhs)?;
Expand All @@ -351,7 +351,7 @@ impl<F: AcirField> AcirContext<F> {
return Ok(lhs);
}

match typ.to_numeric_type() {
match typ {
NumericType::Signed { bit_size: 1 } | NumericType::Unsigned { bit_size: 1 } => {
// Operands are booleans.
//
Expand All @@ -361,7 +361,7 @@ impl<F: AcirField> AcirContext<F> {
self.add_mul_var(sum, -F::from(2_u128), prod)
}
NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => {
let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)];
let inputs = vec![AcirValue::Var(lhs, typ), AcirValue::Var(rhs, typ)];
let outputs =
self.black_box_function(BlackBoxFunc::XOR, inputs, Some(bit_size), 1, None)?;
Ok(outputs[0])
Expand All @@ -377,7 +377,7 @@ impl<F: AcirField> AcirContext<F> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
typ: AcirType,
typ: NumericType,
) -> Result<AcirVar, RuntimeError> {
let lhs_expr = self.var_to_expression(lhs)?;
let rhs_expr = self.var_to_expression(rhs)?;
Expand All @@ -391,13 +391,13 @@ impl<F: AcirField> AcirContext<F> {
return Ok(zero);
}

match typ.to_numeric_type() {
match typ {
NumericType::Signed { bit_size: 1 } | NumericType::Unsigned { bit_size: 1 } => {
// Operands are booleans.
self.mul_var(lhs, rhs)
}
NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => {
let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)];
let inputs = vec![AcirValue::Var(lhs, typ), AcirValue::Var(rhs, typ)];
let outputs =
self.black_box_function(BlackBoxFunc::AND, inputs, Some(bit_size), 1, None)?;
Ok(outputs[0])
Expand All @@ -413,7 +413,7 @@ impl<F: AcirField> AcirContext<F> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
typ: AcirType,
typ: NumericType,
) -> Result<AcirVar, RuntimeError> {
let lhs_expr = self.var_to_expression(lhs)?;
let rhs_expr = self.var_to_expression(rhs)?;
Expand All @@ -429,7 +429,7 @@ impl<F: AcirField> AcirContext<F> {
return Ok(lhs);
}

match typ.to_numeric_type() {
match typ {
NumericType::Signed { bit_size: 1 } | NumericType::Unsigned { bit_size: 1 } => {
// Operands are booleans
// a + b - a*b
Expand All @@ -440,9 +440,9 @@ impl<F: AcirField> AcirContext<F> {
NumericType::Signed { .. } | NumericType::Unsigned { .. } => {
// Implement OR in terms of AND
// (NOT a) AND (NOT b) => NOT (a OR b)
let a = self.not_var(lhs, typ.clone())?;
let b = self.not_var(rhs, typ.clone())?;
let a_and_b = self.and_var(a, b, typ.clone())?;
let a = self.not_var(lhs, typ)?;
let b = self.not_var(rhs, typ)?;
let a_and_b = self.and_var(a, b, typ)?;
self.not_var(a_and_b, typ)
}
NumericType::NativeField => {
Expand Down Expand Up @@ -567,25 +567,22 @@ impl<F: AcirField> AcirContext<F> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
typ: AcirType,
typ: NumericType,
predicate: AcirVar,
) -> Result<AcirVar, RuntimeError> {
match typ {
AcirType::NumericType(NumericType::NativeField) => {
NumericType::NativeField => {
let inv_rhs = self.inv_var(rhs, predicate)?;
self.mul_var(lhs, inv_rhs)
}
AcirType::NumericType(NumericType::Unsigned { bit_size }) => {
NumericType::Unsigned { bit_size } => {
let (quotient_var, _remainder_var) =
self.euclidean_division_var(lhs, rhs, bit_size, predicate)?;
Ok(quotient_var)
}
AcirType::NumericType(NumericType::Signed { .. }) => {
NumericType::Signed { .. } => {
unreachable!("Signed division should have been removed before ACIRgen")
}
AcirType::Array(_, _) => {
unreachable!("cannot divide arrays. This should have been caught by the frontend")
}
}
}

Expand Down Expand Up @@ -750,7 +747,11 @@ impl<F: AcirField> AcirContext<F> {
}

/// Adds a new variable that is constrained to be the logical NOT of `x`.
pub(crate) fn not_var(&mut self, x: AcirVar, typ: AcirType) -> Result<AcirVar, RuntimeError> {
pub(crate) fn not_var(
&mut self,
x: AcirVar,
typ: NumericType,
) -> Result<AcirVar, RuntimeError> {
let bit_size = typ.bit_size::<F>();
// Subtracting from max flips the bits
let max = power_of_two::<F>(bit_size) - F::one();
Expand Down Expand Up @@ -866,10 +867,13 @@ impl<F: AcirField> AcirContext<F> {
predicate,
BrilligStdlibFunc::Quotient,
vec![
AcirValue::Var(lhs, AcirType::unsigned(bit_size)),
AcirValue::Var(rhs, AcirType::unsigned(bit_size)),
AcirValue::Var(lhs, NumericType::unsigned(bit_size)),
AcirValue::Var(rhs, NumericType::unsigned(bit_size)),
],
vec![
AcirType::NumericType(NumericType::unsigned(max_q_bits)),
AcirType::NumericType(NumericType::unsigned(max_rhs_bits)),
],
vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)],
)?
.try_into()
.expect("quotient only returns two values");
Expand Down Expand Up @@ -1072,25 +1076,22 @@ impl<F: AcirField> AcirContext<F> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
typ: AcirType,
typ: NumericType,
bit_size: u32,
predicate: AcirVar,
) -> Result<AcirVar, RuntimeError> {
match typ {
AcirType::NumericType(NumericType::Unsigned { .. }) => {
NumericType::Unsigned { .. } => {
let (_, remainder_var) =
self.euclidean_division_var(lhs, rhs, bit_size, predicate)?;
Ok(remainder_var)
}
AcirType::NumericType(NumericType::Signed { .. }) => {
NumericType::Signed { .. } => {
unreachable!("Signed modulo should have been removed before ACIRgen")
}
AcirType::NumericType(NumericType::NativeField) => {
NumericType::NativeField => {
unreachable!("cannot module fields. This should have been caught by the frontend")
}
AcirType::Array(_, _) => {
unreachable!("cannot modulo arrays. This should have been caught by the frontend")
}
}
}

Expand Down Expand Up @@ -1247,7 +1248,7 @@ impl<F: AcirField> AcirContext<F> {
input_var: AcirVar,
radix_var: AcirVar,
limb_count: u32,
result_element_type: AcirType,
result_element_type: NumericType,
) -> Result<AcirValue, RuntimeError> {
let radix = match self.vars[&radix_var].as_constant() {
Some(radix) => radix.try_into_u128().expect("expected radix to fit within a u128"),
Expand All @@ -1271,7 +1272,7 @@ impl<F: AcirField> AcirContext<F> {

let mut limb_vars = vecmap(limbs, |witness| {
let witness = self.add_data(AcirVarData::Witness(witness));
AcirValue::Var(witness, result_element_type.clone())
AcirValue::Var(witness, result_element_type)
});

if endian == Endian::Big {
Expand All @@ -1287,7 +1288,7 @@ impl<F: AcirField> AcirContext<F> {
endian: Endian,
input_var: AcirVar,
limb_count: u32,
result_element_type: AcirType,
result_element_type: NumericType,
) -> Result<AcirValue, RuntimeError> {
let two_var = self.add_constant(2_u128);
self.radix_decompose(endian, input_var, two_var, limb_count, result_element_type)
Expand All @@ -1299,7 +1300,7 @@ impl<F: AcirField> AcirContext<F> {
pub(crate) fn flatten(
&mut self,
value: AcirValue,
) -> Result<Vec<(AcirVar, AcirType)>, InternalError> {
) -> Result<Vec<(AcirVar, NumericType)>, InternalError> {
match value {
AcirValue::Var(acir_var, typ) => Ok(vec![(acir_var, typ)]),
AcirValue::Array(array) => {
Expand All @@ -1313,9 +1314,9 @@ impl<F: AcirField> AcirContext<F> {
try_vecmap(0..len, |i| {
let index_var = self.add_constant(i);

Ok::<(AcirVar, AcirType), InternalError>((
Ok::<(AcirVar, NumericType), InternalError>((
self.read_from_memory(block_id, &index_var)?,
value_types[i % value_types.len()].into(),
value_types[i % value_types.len()],
))
})
}
Expand Down Expand Up @@ -1450,7 +1451,7 @@ impl<F: AcirField> AcirContext<F> {
let index_var = self.add_constant(i);
let read = self.read_from_memory(block_id, &index_var)?;
let typ = value_types[i % value_types.len()];
let value = AcirValue::Var(read, AcirType::NumericType(typ));
let value = AcirValue::Var(read, typ);
self.initialize_array_inner(witnesses, value)?;
}
}
Expand Down
Loading
Loading