Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
ac0bf6e
Skeleton of an SSA interpreter based fuzz target
aakoshh May 9, 2025
828ff75
Make SSA interpreter parts public
aakoshh May 9, 2025
f8e2a26
Make results generic. Add interpreted results
aakoshh May 9, 2025
5b2b12f
Map ABI input to SSA
aakoshh May 9, 2025
3b730c6
Add cargo fuzz target
aakoshh May 9, 2025
3879323
Build the inputs from the SSA
aakoshh May 9, 2025
9e588d8
Remove println
aakoshh May 9, 2025
ec4b77e
Print SSA inputs
aakoshh May 12, 2025
97e446d
Fix negative int handling in the interpreter
aakoshh May 12, 2025
38e18b7
Map ABI types into specific numeric value
aakoshh May 12, 2025
d81213d
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 12, 2025
3b96985
Ignore value IDs in error comparison
aakoshh May 12, 2025
43e91b6
Fix SSA input formatting
aakoshh May 12, 2025
c233781
Pass tuples as separate values
aakoshh May 12, 2025
1e08d6d
Fix negative int conversion to Field in the interpreter
aakoshh May 12, 2025
a8a3801
Flatten tuples wherever they are
aakoshh May 12, 2025
44c403f
Use Comparable::equivalent for results as well as error
aakoshh May 12, 2025
3608983
Allow shifting u1
aakoshh May 12, 2025
4b66ef3
Comparable to recurse into the element
aakoshh May 12, 2025
b219fc0
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 12, 2025
b354cea
Avoid call_data parameters for now
aakoshh May 12, 2025
c0013f2
Allow arithmetic operations on u1 in the interpreter
aakoshh May 12, 2025
5a1fbfd
Add u1 ops to interpreter
jfecher May 12, 2025
7464b68
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 12, 2025
a152bd1
Revert "Avoid call_data parameters for now"
aakoshh May 12, 2025
8ae03c7
Fix clippy
aakoshh May 12, 2025
5074639
Add ticket number to TODO
aakoshh May 12, 2025
77d3d39
Use IntegerConstant
jfecher May 13, 2025
0e932a4
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 13, 2025
09e8403
Add test that shows the SSA failure on casting
aakoshh May 13, 2025
b26ac04
Merge remote-tracking branch 'origin/master' into jf/interpreter-addi…
aakoshh May 13, 2025
309075b
Fix odd cast semantics
jfecher May 13, 2025
51f928f
Merge branch 'jf/interpreter-additions' of https://github.com/noir-la…
jfecher May 13, 2025
3d9fedd
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 13, 2025
a943b98
Fix cast behavior... again
jfecher May 13, 2025
b4dede8
Remove accidental printlns
jfecher May 13, 2025
d78a113
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 13, 2025
fc98481
Add test that shows wrong value returned by the SSA interpreter
aakoshh May 13, 2025
2b1b9e9
Use log::debug! for printing stuff up front
aakoshh May 14, 2025
02e4f4d
Compare the details in Overflows
aakoshh May 14, 2025
caead66
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 14, 2025
6c76d5c
'fix' casting and truncate
jfecher May 14, 2025
25ee60e
Merge branch 'master' into jf/interpreter-additions
jfecher May 14, 2025
fdbeed9
New test on master needed to be updated
jfecher May 14, 2025
5c573bd
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 15, 2025
14b4487
Fix clippy
aakoshh May 15, 2025
5441875
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 15, 2025
eddf15e
Fix merge
aakoshh May 15, 2025
bb532cc
Enable fuzzing morphs and the SSA interpreter on CI
aakoshh May 15, 2025
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
3 changes: 3 additions & 0 deletions Cargo.lock

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

13 changes: 9 additions & 4 deletions compiler/noirc_evaluator/src/ssa/interpreter/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::ssa::ir::{
basic_block::BasicBlockId,
instruction::{BinaryOp, Intrinsic},
types::NumericType,
value::ValueId,
};
use acvm::FieldElement;
Expand All @@ -9,8 +10,8 @@ use thiserror::Error;
pub(super) const MAX_SIGNED_BIT_SIZE: u32 = 64;
pub(super) const MAX_UNSIGNED_BIT_SIZE: u32 = 128;

#[derive(Debug, Error)]
pub(crate) enum InterpreterError {
#[derive(Debug, Error, PartialEq, Eq)]
pub enum InterpreterError {
/// These errors are all the result from malformed input SSA
#[error("{0}")]
Internal(InternalError),
Expand Down Expand Up @@ -61,8 +62,8 @@ pub(crate) enum InterpreterError {
}

/// These errors can only result from interpreting malformed SSA
#[derive(Debug, Error)]
pub(crate) enum InternalError {
#[derive(Debug, Error, PartialEq, Eq)]
pub enum InternalError {
#[error(
"Argument count {arguments} to block {block} does not match the expected parameter count {parameters}"
)]
Expand Down Expand Up @@ -93,6 +94,8 @@ pub(crate) enum InternalError {
},
#[error("Unsupported operator `{operator}` for type `{typ}`")]
UnsupportedOperatorForType { operator: &'static str, typ: &'static str },
#[error("Unsupported numeric type `{typ}`")]
UnsupportedNumericType { typ: NumericType },
#[error(
"Invalid bit size of `{bit_size}` given to truncate, maximum size allowed for unsigned values is {MAX_UNSIGNED_BIT_SIZE}"
)]
Expand Down Expand Up @@ -142,4 +145,6 @@ pub(crate) enum InternalError {
UnexpectedInstruction { reason: &'static str },
#[error("Expected array of {expected_size} elements, got {size}")]
InvalidInputSize { expected_size: usize, size: usize },
#[error("Constant `{constant}` does not fit in type `{typ}`")]
ConstantDoesNotFitInType { constant: FieldElement, typ: NumericType },
}
62 changes: 30 additions & 32 deletions compiler/noirc_evaluator/src/ssa/interpreter/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use acvm::{AcirField, BlackBoxFunctionSolver, BlackBoxResolutionError, FieldElement};
use bn254_blackbox_solver::derive_generators;
use iter_extended::vecmap;
use iter_extended::{try_vecmap, vecmap};
use num_bigint::BigUint;

use crate::ssa::{
Expand Down Expand Up @@ -31,7 +31,7 @@ impl Interpreter<'_> {
}
Intrinsic::ArrayAsStrUnchecked => {
check_argument_count(args, 1, intrinsic)?;
Ok(vec![self.lookup(args[0])])
Ok(vec![self.lookup(args[0])?])
}
Intrinsic::AsSlice => {
check_argument_count(args, 1, intrinsic)?;
Expand Down Expand Up @@ -73,7 +73,7 @@ impl Interpreter<'_> {
// Both of these are no-ops
Intrinsic::StrAsBytes | Intrinsic::AsWitness => {
check_argument_count(args, 1, intrinsic)?;
Ok(vec![self.lookup(args[0])])
Ok(vec![self.lookup(args[0])?])
}
Intrinsic::ToBits(endian) => {
check_argument_count(args, 1, intrinsic)?;
Expand Down Expand Up @@ -109,9 +109,8 @@ impl Interpreter<'_> {
let result =
acvm::blackbox_solver::aes128_encrypt(&inputs, iv_array, key_array)
.map_err(Self::convert_error)?;
let result: Vec<FieldElement> =
result.iter().map(|v| (*v as u128).into()).collect();
let result = Value::array_from_slice(&result, NumericType::NativeField);
let result = result.iter().map(|v| (*v as u128).into());
let result = Value::array_from_iter(result, NumericType::NativeField)?;
Ok(vec![result])
}
acvm::acir::BlackBoxFunc::AND => {
Expand All @@ -134,19 +133,17 @@ impl Interpreter<'_> {
let inputs = self.lookup_bytes(args[0], "call Blake2s BlackBox")?;
let result =
acvm::blackbox_solver::blake2s(&inputs).map_err(Self::convert_error)?;
let result: Vec<FieldElement> =
result.iter().map(|e| (*e as u128).into()).collect();
let result = Value::array_from_slice(&result, NumericType::NativeField);
let result = result.iter().map(|e| (*e as u128).into());
let result = Value::array_from_iter(result, NumericType::NativeField)?;
Ok(vec![result])
}
acvm::acir::BlackBoxFunc::Blake3 => {
check_argument_count(args, 1, intrinsic)?;
let inputs = self.lookup_bytes(args[0], "call Blake3 BlackBox")?;
let results =
acvm::blackbox_solver::blake3(&inputs).map_err(Self::convert_error)?;
let results: Vec<FieldElement> =
results.iter().map(|e| (*e as u128).into()).collect();
let results = Value::array_from_slice(&results, NumericType::NativeField);
let results = results.iter().map(|e| (*e as u128).into());
let results = Value::array_from_iter(results, NumericType::NativeField)?;
Ok(vec![results])
}
acvm::acir::BlackBoxFunc::EcdsaSecp256k1 => {
Expand Down Expand Up @@ -183,7 +180,7 @@ impl Interpreter<'_> {
Ok(vec![Value::from_constant(
result.into(),
NumericType::Unsigned { bit_size: 1 },
)])
)?])
}
acvm::acir::BlackBoxFunc::EcdsaSecp256r1 => {
check_argument_count(args, 4, intrinsic)?;
Expand Down Expand Up @@ -219,7 +216,7 @@ impl Interpreter<'_> {
Ok(vec![Value::from_constant(
result.into(),
NumericType::Unsigned { bit_size: 1 },
)])
)?])
}
acvm::acir::BlackBoxFunc::MultiScalarMul => {
check_argument_count(args, 2, intrinsic)?;
Expand Down Expand Up @@ -276,7 +273,7 @@ impl Interpreter<'_> {
let solver = bn254_blackbox_solver::Bn254BlackBoxSolver(false);
let result = solver.multi_scalar_mul(&points, &scalars_lo, &scalars_hi);
let (a, b, c) = result.map_err(Self::convert_error)?;
let result = Value::array_from_slice(&[a, b, c], NumericType::NativeField);
let result = Value::array_from_iter([a, b, c], NumericType::NativeField)?;
Ok(vec![result])
}
acvm::acir::BlackBoxFunc::Keccakf1600 => {
Expand All @@ -291,10 +288,9 @@ impl Interpreter<'_> {
})?;
let results = acvm::blackbox_solver::keccakf1600(inputs_array)
.map_err(Self::convert_error)?;
let results: Vec<FieldElement> =
results.iter().map(|e| (*e as u128).into()).collect();
let results = results.iter().map(|e| (*e as u128).into());
let results =
Value::array_from_slice(&results, NumericType::Unsigned { bit_size: 64 });
Value::array_from_iter(results, NumericType::Unsigned { bit_size: 64 })?;
Ok(vec![results])
}
acvm::acir::BlackBoxFunc::RecursiveAggregation => {
Expand All @@ -318,7 +314,7 @@ impl Interpreter<'_> {
let result =
solver.ec_add(&lhs.0, &lhs.1, &lhs.2.into(), &rhs.0, &rhs.1, &rhs.2.into());
let (x, y, inf) = result.map_err(Self::convert_error)?;
let result = Value::array_from_slice(&[x, y, inf], NumericType::NativeField);
let result = Value::array_from_iter([x, y, inf], NumericType::NativeField)?;
Ok(vec![result])
}
acvm::acir::BlackBoxFunc::BigIntAdd
Expand All @@ -339,7 +335,7 @@ impl Interpreter<'_> {
let result = solver
.poseidon2_permutation(&inputs, inputs.len() as u32)
.map_err(Self::convert_error)?;
let result = Value::array_from_slice(&result, NumericType::NativeField);
let result = Value::array_from_iter(result, NumericType::NativeField)?;
Ok(vec![result])
}
acvm::acir::BlackBoxFunc::Sha256Compression => {
Expand All @@ -361,13 +357,12 @@ impl Interpreter<'_> {
})
})?;
acvm::blackbox_solver::sha256_compression(&mut state, &inputs);
let result: Vec<FieldElement> =
state.iter().map(|e| (*e as u128).into()).collect();
let result = Value::array_from_slice(&result, NumericType::NativeField);
let result = state.iter().map(|e| (*e as u128).into());
let result = Value::array_from_iter(result, NumericType::NativeField)?;
Ok(vec![result])
}
},
Intrinsic::Hint(_) => Ok(self.lookup_all(args)),
Intrinsic::Hint(_) => self.lookup_all(args),
Intrinsic::IsUnconstrained => {
check_argument_count(args, 0, intrinsic)?;
Ok(vec![Value::bool(self.in_unconstrained_context())])
Expand All @@ -384,10 +379,10 @@ impl Interpreter<'_> {
let x = FieldElement::from_le_bytes_reduce(&x_big.to_bytes_le());
let y_big: BigUint = generator.y.into();
let y = FieldElement::from_le_bytes_reduce(&y_big.to_bytes_le());
let generator_slice = Value::array_from_slice(
&[x, y, generator.infinity.into()],
let generator_slice = Value::array_from_iter(
[x, y, generator.infinity.into()],
NumericType::NativeField,
);
)?;
result.push(generator_slice);
}
let results = Value::array(
Expand Down Expand Up @@ -417,7 +412,7 @@ impl Interpreter<'_> {
Intrinsic::ArrayRefCount | Intrinsic::SliceRefCount => {
let array = self.lookup_array_or_slice(args[0], "array/slice ref count")?;
let rc = *array.rc.borrow();
Ok(vec![Value::from_constant(rc.into(), NumericType::unsigned(32))])
Ok(vec![Value::from_constant(rc.into(), NumericType::unsigned(32))?])
}
}
}
Expand Down Expand Up @@ -449,7 +444,8 @@ impl Interpreter<'_> {
return Err(InterpreterError::ToRadixFailed { field_id, field, radix });
};

let elements = vecmap(limbs, |limb| Value::from_constant(limb, NumericType::unsigned(8)));
let elements =
try_vecmap(limbs, |limb| Value::from_constant(limb, NumericType::unsigned(8)))?;
Ok(vec![Value::array(elements, vec![Type::unsigned(8)])])
}

Expand All @@ -463,7 +459,9 @@ impl Interpreter<'_> {
let mut new_elements = slice.elements.borrow().to_vec();
let element_types = slice.element_types.clone();

new_elements.extend(args.iter().skip(2).map(|arg| self.lookup(*arg)));
for arg in args.iter().skip(2) {
new_elements.push(self.lookup(*arg)?);
}

let new_length = Value::Numeric(NumericValue::U32(length + 1));
let new_slice = Value::slice(new_elements, element_types);
Expand All @@ -477,7 +475,7 @@ impl Interpreter<'_> {
let slice_elements = slice.elements.clone();
let element_types = slice.element_types.clone();

let mut new_elements = vecmap(args.iter().skip(2), |arg| self.lookup(*arg));
let mut new_elements = try_vecmap(args.iter().skip(2), |arg| self.lookup(*arg))?;
new_elements.extend_from_slice(&slice_elements.borrow());

let new_length = Value::Numeric(NumericValue::U32(length + 1));
Expand Down Expand Up @@ -543,7 +541,7 @@ impl Interpreter<'_> {

let mut index = index as usize * element_types.len();
for arg in args.iter().skip(3) {
slice_elements.insert(index, self.lookup(*arg));
slice_elements.insert(index, self.lookup(*arg)?);
index += 1;
}

Expand Down
Loading
Loading