Skip to content

Commit

Permalink
chore: pull SSA parser from sync PR (#9928)
Browse files Browse the repository at this point in the history
Please read [contributing guidelines](CONTRIBUTING.md) and remove this
line.
  • Loading branch information
TomAFrench authored Nov 13, 2024
1 parent 451feed commit 7661e42
Show file tree
Hide file tree
Showing 28 changed files with 2,966 additions and 1,055 deletions.
15 changes: 1 addition & 14 deletions noir/noir-repo/Cargo.lock

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

2 changes: 2 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fxhash.workspace = true
iter-extended.workspace = true
thiserror.workspace = true
num-bigint = "0.4"
num-traits.workspace = true
im.workspace = true
serde.workspace = true
serde_json.workspace = true
Expand All @@ -31,6 +32,7 @@ cfg-if.workspace = true

[dev-dependencies]
proptest.workspace = true
similar-asserts.workspace = true

[features]
bn254 = ["noirc_frontend/bn254"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ pub(crate) fn directive_invert<F: AcirField>() -> GeneratedBrillig<F> {
return_data: HeapVector { pointer: zero_usize, size: one_usize },
},
],
error_types: Default::default(),
locations: Default::default(),
name: "directive_invert".to_string(),
..Default::default()
}
Expand Down Expand Up @@ -144,8 +142,6 @@ pub(crate) fn directive_quotient<F: AcirField>() -> GeneratedBrillig<F> {
},
},
],
error_types: Default::default(),
locations: Default::default(),
name: "directive_integer_quotient".to_string(),
..Default::default()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use acvm::{
AcirField,
};

use crate::ErrorType;
use crate::ssa::ir::instruction::ErrorType;

use super::{
artifact::BrilligParameter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use noirc_errors::debug_info::ProcedureDebugId;
use prepare_vector_insert::compile_prepare_vector_insert_procedure;
use prepare_vector_push::compile_prepare_vector_push_procedure;
use revert_with_string::compile_revert_with_string_procedure;
use serde::{Deserialize, Serialize};
use vector_copy::compile_vector_copy_procedure;
use vector_pop_back::compile_vector_pop_back_procedure;
use vector_pop_front::compile_vector_pop_front_procedure;
Expand All @@ -34,7 +35,7 @@ use super::{
/// Procedures are a set of complex operations that are common in the noir language.
/// Extracting them to reusable procedures allows us to reduce the size of the generated Brillig.
/// Procedures receive their arguments on scratch space to avoid stack dumping&restoring.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)]
pub enum ProcedureId {
ArrayCopy,
ArrayReverse,
Expand Down
18 changes: 18 additions & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,21 @@ pub mod brillig;
pub use ssa::create_program;

pub use ssa::ir::instruction::ErrorType;

/// Trims leading whitespace from each line of the input string, according to
/// how much leading whitespace there is on the first non-empty line.
#[cfg(test)]
pub(crate) fn trim_leading_whitespace_from_lines(src: &str) -> String {
let mut lines = src.trim_end().lines();
let mut first_line = lines.next().unwrap();
while first_line.is_empty() {
first_line = lines.next().unwrap();
}
let indent = first_line.len() - first_line.trim_start().len();
let mut result = first_line.trim_start().to_string();
for line in lines {
result.push('\n');
result.push_str(&line[indent..]);
}
result
}
1 change: 1 addition & 0 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ mod checks;
pub(super) mod function_builder;
pub mod ir;
mod opt;
mod parser;
pub mod ssa_gen;

pub struct SsaEvaluatorOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1009,13 +1009,13 @@ impl<'a> Context<'a> {
};
entry_point.link_with(artifact);
// Insert the range of opcode locations occupied by a procedure
if let Some(procedure_id) = artifact.procedure.clone() {
if let Some(procedure_id) = &artifact.procedure {
let num_opcodes = entry_point.byte_code.len();
let previous_num_opcodes = entry_point.byte_code.len() - artifact.byte_code.len();
// We subtract one as to keep the range inclusive on both ends
entry_point
.procedure_locations
.insert(procedure_id, (previous_num_opcodes, num_opcodes - 1));
.insert(procedure_id.clone(), (previous_num_opcodes, num_opcodes - 1));
}
}
// Generate the final bytecode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,16 @@ impl FunctionBuilder {
.first()
}

pub(crate) fn insert_mutable_array_set(
&mut self,
array: ValueId,
index: ValueId,
value: ValueId,
) -> ValueId {
self.insert_instruction(Instruction::ArraySet { array, index, value, mutable: true }, None)
.first()
}

/// Insert an instruction to increment an array's reference count. This only has an effect
/// in unconstrained code where arrays are reference counted and copy on write.
pub(crate) fn insert_inc_rc(&mut self, value: ValueId) {
Expand Down
5 changes: 3 additions & 2 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ pub(crate) struct DataFlowGraph {
blocks: DenseMap<BasicBlock>,

/// Debugging information about which `ValueId`s have had their underlying `Value` substituted
/// for that of another. This information is purely used for printing the SSA, and has no
/// material effect on the SSA itself.
/// for that of another. In theory this information is purely used for printing the SSA,
/// and has no material effect on the SSA itself, however in practice the IDs can get out of
/// sync and may need this resolution before they can be compared.
#[serde(skip)]
replaced_value_ids: HashMap<ValueId, ValueId>,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ impl Binary {
let zero = dfg.make_constant(FieldElement::zero(), operand_type);
return SimplifyResult::SimplifiedTo(zero);
}

// `two_pow_rhs` is limited to be at most `2 ^ {operand_bitsize - 1}` so it fits in `operand_type`.
let two_pow_rhs = FieldElement::from(2u128).pow(&rhs_const);
let two_pow_rhs = dfg.make_constant(two_pow_rhs, operand_type);
Expand Down
50 changes: 42 additions & 8 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,16 @@ fn value(function: &Function, id: ValueId) -> String {
}
Value::Function(id) => id.to_string(),
Value::Intrinsic(intrinsic) => intrinsic.to_string(),
Value::Array { array, .. } => {
Value::Array { array, typ } => {
let elements = vecmap(array, |element| value(function, *element));
format!("[{}]", elements.join(", "))
let element_types = &typ.clone().element_types();
let element_types_str =
element_types.iter().map(|typ| typ.to_string()).collect::<Vec<String>>().join(", ");
if element_types.len() == 1 {
format!("[{}] of {}", elements.join(", "), element_types_str)
} else {
format!("[{}] of ({})", elements.join(", "), element_types_str)
}
}
Value::Param { .. } | Value::Instruction { .. } | Value::ForeignFunction(_) => {
id.to_string()
Expand Down Expand Up @@ -119,7 +126,11 @@ pub(crate) fn display_terminator(
)
}
Some(TerminatorInstruction::Return { return_values, .. }) => {
writeln!(f, " return {}", value_list(function, return_values))
if return_values.is_empty() {
writeln!(f, " return")
} else {
writeln!(f, " return {}", value_list(function, return_values))
}
}
None => writeln!(f, " (no terminator instruction)"),
}
Expand All @@ -139,12 +150,13 @@ pub(crate) fn display_instruction(
write!(f, "{} = ", value_list(function, results))?;
}

display_instruction_inner(function, &function.dfg[instruction], f)
display_instruction_inner(function, &function.dfg[instruction], results, f)
}

fn display_instruction_inner(
function: &Function,
instruction: &Instruction,
results: &[ValueId],
f: &mut Formatter,
) -> Result {
let show = |id| value(function, id);
Expand All @@ -168,18 +180,29 @@ fn display_instruction_inner(
}
}
Instruction::Call { func, arguments } => {
writeln!(f, "call {}({})", show(*func), value_list(function, arguments))
let arguments = value_list(function, arguments);
writeln!(f, "call {}({}){}", show(*func), arguments, result_types(function, results))
}
Instruction::Allocate => {
writeln!(f, "allocate{}", result_types(function, results))
}
Instruction::Load { address } => {
writeln!(f, "load {}{}", show(*address), result_types(function, results))
}
Instruction::Allocate => writeln!(f, "allocate"),
Instruction::Load { address } => writeln!(f, "load {}", show(*address)),
Instruction::Store { address, value } => {
writeln!(f, "store {} at {}", show(*value), show(*address))
}
Instruction::EnableSideEffectsIf { condition } => {
writeln!(f, "enable_side_effects {}", show(*condition))
}
Instruction::ArrayGet { array, index } => {
writeln!(f, "array_get {}, index {}", show(*array), show(*index))
writeln!(
f,
"array_get {}, index {}{}",
show(*array),
show(*index),
result_types(function, results)
)
}
Instruction::ArraySet { array, index, value, mutable } => {
let array = show(*array);
Expand Down Expand Up @@ -210,6 +233,17 @@ fn display_instruction_inner(
}
}

fn result_types(function: &Function, results: &[ValueId]) -> String {
let types = vecmap(results, |result| function.dfg.type_of_value(*result).to_string());
if types.is_empty() {
String::new()
} else if types.len() == 1 {
format!(" -> {}", types[0])
} else {
format!(" -> ({})", types.join(", "))
}
}

/// Tries to extract a constant string from an error payload.
pub(crate) fn try_to_extract_string_from_error_payload(
is_string_type: bool,
Expand Down
6 changes: 5 additions & 1 deletion noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,11 @@ impl std::fmt::Display for Type {
Type::Reference(element) => write!(f, "&mut {element}"),
Type::Array(element, length) => {
let elements = vecmap(element.iter(), |element| element.to_string());
write!(f, "[{}; {length}]", elements.join(", "))
if elements.len() == 1 {
write!(f, "[{}; {length}]", elements.join(", "))
} else {
write!(f, "[({}); {length}]", elements.join(", "))
}
}
Type::Slice(element) => {
let elements = vecmap(element.iter(), |element| element.to_string());
Expand Down
Loading

0 comments on commit 7661e42

Please sign in to comment.