Skip to content
Merged
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
76 changes: 38 additions & 38 deletions compiler/noirc_evaluator/src/ssa/ir/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,33 @@ use super::{
pub(crate) fn display_function(function: &Function, f: &mut Formatter) -> Result {
writeln!(f, "{} fn {} {} {{", function.runtime(), function.name(), function.id())?;
for block_id in function.reachable_blocks() {
display_block(function, block_id, f)?;
display_block(&function.dfg, block_id, f)?;
}
write!(f, "}}")
}

/// Display a single block. This will not display the block's successors.
pub(crate) fn display_block(
function: &Function,
dfg: &DataFlowGraph,
block_id: BasicBlockId,
f: &mut Formatter,
) -> Result {
let block = &function.dfg[block_id];
let block = &dfg[block_id];

writeln!(f, " {}({}):", block_id, value_list_with_types(function, block.parameters()))?;
writeln!(f, " {}({}):", block_id, value_list_with_types(dfg, block.parameters()))?;

for instruction in block.instructions() {
display_instruction(function, *instruction, f)?;
display_instruction(dfg, *instruction, f)?;
}

display_terminator(function, block.terminator(), f)
display_terminator(dfg, block.terminator(), f)
}

/// Specialize displaying value ids so that if they refer to a numeric
/// constant or a function we print those directly.
fn value(function: &Function, id: ValueId) -> String {
let id = function.dfg.resolve(id);
match &function.dfg[id] {
fn value(dfg: &DataFlowGraph, id: ValueId) -> String {
let id = dfg.resolve(id);
match &dfg[id] {
Value::NumericConstant { constant, typ } => {
format!("{typ} {constant}")
}
Expand All @@ -57,29 +57,29 @@ fn value(function: &Function, id: ValueId) -> String {
}

/// Display each value along with its type. E.g. `v0: Field, v1: u64, v2: u1`
fn value_list_with_types(function: &Function, values: &[ValueId]) -> String {
fn value_list_with_types(dfg: &DataFlowGraph, values: &[ValueId]) -> String {
vecmap(values, |id| {
let value = value(function, *id);
let typ = function.dfg.type_of_value(*id);
let value = value(dfg, *id);
let typ = dfg.type_of_value(*id);
format!("{value}: {typ}")
})
.join(", ")
}

/// Display each value separated by a comma
fn value_list(function: &Function, values: &[ValueId]) -> String {
vecmap(values, |id| value(function, *id)).join(", ")
fn value_list(dfg: &DataFlowGraph, values: &[ValueId]) -> String {
vecmap(values, |id| value(dfg, *id)).join(", ")
}

/// Display a terminator instruction
pub(crate) fn display_terminator(
function: &Function,
dfg: &DataFlowGraph,
terminator: Option<&TerminatorInstruction>,
f: &mut Formatter,
) -> Result {
match terminator {
Some(TerminatorInstruction::Jmp { destination, arguments, call_stack: _ }) => {
writeln!(f, " jmp {}({})", destination, value_list(function, arguments))
writeln!(f, " jmp {}({})", destination, value_list(dfg, arguments))
}
Some(TerminatorInstruction::JmpIf {
condition,
Expand All @@ -90,7 +90,7 @@ pub(crate) fn display_terminator(
writeln!(
f,
" jmpif {} then: {}, else: {}",
value(function, *condition),
value(dfg, *condition),
then_destination,
else_destination
)
Expand All @@ -99,7 +99,7 @@ pub(crate) fn display_terminator(
if return_values.is_empty() {
writeln!(f, " return")
} else {
writeln!(f, " return {}", value_list(function, return_values))
writeln!(f, " return {}", value_list(dfg, return_values))
}
}
None => writeln!(f, " (no terminator instruction)"),
Expand All @@ -108,28 +108,28 @@ pub(crate) fn display_terminator(

/// Display an arbitrary instruction
pub(crate) fn display_instruction(
function: &Function,
dfg: &DataFlowGraph,
instruction: InstructionId,
f: &mut Formatter,
) -> Result {
// instructions are always indented within a function
write!(f, " ")?;

let results = function.dfg.instruction_results(instruction);
let results = dfg.instruction_results(instruction);
if !results.is_empty() {
write!(f, "{} = ", value_list(function, results))?;
write!(f, "{} = ", value_list(dfg, results))?;
}

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

fn display_instruction_inner(
function: &Function,
dfg: &DataFlowGraph,
instruction: &Instruction,
results: &[ValueId],
f: &mut Formatter,
) -> Result {
let show = |id| value(function, id);
let show = |id| value(dfg, id);

match instruction {
Instruction::Binary(binary) => {
Expand All @@ -144,20 +144,20 @@ fn display_instruction_inner(
Instruction::Constrain(lhs, rhs, error) => {
write!(f, "constrain {} == {}", show(*lhs), show(*rhs))?;
if let Some(error) = error {
display_constrain_error(function, error, f)
display_constrain_error(dfg, error, f)
} else {
writeln!(f)
}
}
Instruction::Call { func, arguments } => {
let arguments = value_list(function, arguments);
writeln!(f, "call {}({}){}", show(*func), arguments, result_types(function, results))
let arguments = value_list(dfg, arguments);
writeln!(f, "call {}({}){}", show(*func), arguments, result_types(dfg, results))
}
Instruction::Allocate => {
writeln!(f, "allocate{}", result_types(function, results))
writeln!(f, "allocate{}", result_types(dfg, results))
}
Instruction::Load { address } => {
writeln!(f, "load {}{}", show(*address), result_types(function, results))
writeln!(f, "load {}{}", show(*address), result_types(dfg, results))
}
Instruction::Store { address, value } => {
writeln!(f, "store {} at {}", show(*value), show(*address))
Expand All @@ -171,7 +171,7 @@ fn display_instruction_inner(
"array_get {}, index {}{}",
show(*array),
show(*index),
result_types(function, results)
result_types(dfg, results)
)
}
Instruction::ArraySet { array, index, value, mutable } => {
Expand Down Expand Up @@ -214,7 +214,7 @@ fn display_instruction_inner(
if element_types.len() == 1
&& element_types[0] == Type::Numeric(NumericType::Unsigned { bit_size: 8 })
{
if let Some(string) = try_byte_array_to_string(elements, function) {
if let Some(string) = try_byte_array_to_string(elements, dfg) {
if is_slice {
return writeln!(f, "make_array &b{:?}", string);
} else {
Expand All @@ -238,10 +238,10 @@ fn display_instruction_inner(
}
}

fn try_byte_array_to_string(elements: &Vector<ValueId>, function: &Function) -> Option<String> {
fn try_byte_array_to_string(elements: &Vector<ValueId>, dfg: &DataFlowGraph) -> Option<String> {
let mut string = String::new();
for element in elements {
let element = function.dfg.get_numeric_constant(*element)?;
let element = dfg.get_numeric_constant(*element)?;
let element = element.try_to_u32()?;
if element > 0xFF {
return None;
Expand All @@ -257,8 +257,8 @@ fn try_byte_array_to_string(elements: &Vector<ValueId>, function: &Function) ->
Some(string)
}

fn result_types(function: &Function, results: &[ValueId]) -> String {
let types = vecmap(results, |result| function.dfg.type_of_value(*result).to_string());
fn result_types(dfg: &DataFlowGraph, results: &[ValueId]) -> String {
let types = vecmap(results, |result| dfg.type_of_value(*result).to_string());
if types.is_empty() {
String::new()
} else if types.len() == 1 {
Expand Down Expand Up @@ -293,7 +293,7 @@ pub(crate) fn try_to_extract_string_from_error_payload(
}

fn display_constrain_error(
function: &Function,
dfg: &DataFlowGraph,
error: &ConstrainError,
f: &mut Formatter,
) -> Result {
Expand All @@ -303,11 +303,11 @@ fn display_constrain_error(
}
ConstrainError::Dynamic(_, is_string, values) => {
if let Some(constant_string) =
try_to_extract_string_from_error_payload(*is_string, values, &function.dfg)
try_to_extract_string_from_error_payload(*is_string, values, dfg)
{
writeln!(f, ", {constant_string:?}")
} else {
writeln!(f, ", data {}", value_list(function, values))
writeln!(f, ", data {}", value_list(dfg, values))
}
}
}
Expand Down