Skip to content

Commit

Permalink
switch to Function from DataFlowGraph to represent globals
Browse files Browse the repository at this point in the history
  • Loading branch information
vezenovm committed Jan 10, 2025
1 parent 584cc92 commit 8ff2934
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 22 deletions.
16 changes: 12 additions & 4 deletions compiler/noirc_evaluator/src/ssa/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) struct Function {
/// Name of the function for debugging only
name: String,

id: FunctionId,
id: Option<FunctionId>,

/// The DataFlowGraph holds the majority of data pertaining to the function
/// including its blocks, instructions, and values.
Expand All @@ -90,14 +90,22 @@ impl Function {
pub(crate) fn new(name: String, id: FunctionId) -> Self {
let mut dfg = DataFlowGraph::default();
let entry_block = dfg.make_block();
Self { name, id, entry_block, dfg }
Self { name, id: Some(id), entry_block, dfg }
}

/// Globals are generated using the same codegen process as functions.
/// To avoid a recursive global context we should create a pseudo function to mock a globals context.
pub(crate) fn new_for_globals() -> Self {
let mut dfg = DataFlowGraph::default();
let entry_block = dfg.make_block();
Self { name: "globals".to_owned(), id: None, entry_block, dfg }
}

/// Creates a new function as a clone of the one passed in with the passed in id.
pub(crate) fn clone_with_id(id: FunctionId, another: &Function) -> Self {
let dfg = another.dfg.clone();
let entry_block = another.entry_block;
Self { name: another.name.clone(), id, entry_block, dfg }
Self { name: another.name.clone(), id: Some(id), entry_block, dfg }
}

/// Takes the signature (function name & runtime) from a function but does not copy the body.
Expand All @@ -115,7 +123,7 @@ impl Function {

/// The id of the function.
pub(crate) fn id(&self) -> FunctionId {
self.id
self.id.expect("FunctionId should be initialized")
}

/// Runtime type of the function.
Expand Down
6 changes: 3 additions & 3 deletions compiler/noirc_evaluator/src/ssa/ir/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ use super::{

impl Display for Ssa {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
for (id, global_value) in self.globals.values_iter() {
for (id, global_value) in self.globals.dfg.values_iter() {
match global_value {
Value::NumericConstant { constant, typ } => {
writeln!(f, "g{} = {typ} {constant}", id.to_u32())?;
}
Value::Instruction { instruction, .. } => {
display_instruction(&self.globals, *instruction, true, f)?;
display_instruction(&self.globals.dfg, *instruction, true, f)?;
}
Value::Global(_) => {
panic!("Value::Global should only be in the function dfg");
Expand All @@ -35,7 +35,7 @@ impl Display for Ssa {
};
}

if self.globals.values_iter().len() > 0 {
if self.globals.dfg.values_iter().len() > 0 {
writeln!(f)?;
}

Expand Down
10 changes: 5 additions & 5 deletions compiler/noirc_evaluator/src/ssa/opt/inlining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::ssa::{
ir::{
basic_block::BasicBlockId,
call_stack::CallStackId,
dfg::{DataFlowGraph, InsertInstructionResult},
dfg::InsertInstructionResult,
function::{Function, FunctionId, RuntimeType},
instruction::{Instruction, InstructionId, TerminatorInstruction},
value::{Value, ValueId},
Expand Down Expand Up @@ -99,7 +99,7 @@ struct InlineContext<'global> {
// These are the functions of the program that we shouldn't inline.
functions_not_to_inline: BTreeSet<FunctionId>,

globals: &'global DataFlowGraph,
globals: &'global Function,
}

/// The per-function inlining context contains information that is only valid for one function.
Expand Down Expand Up @@ -382,7 +382,7 @@ impl<'global> InlineContext<'global> {
let mut context = PerFunctionContext::new(&mut self, entry_point);
context.inlining_entry = true;

for (_, value) in ssa.globals.values_iter() {
for (_, value) in ssa.globals.dfg.values_iter() {
context.context.builder.current_function.dfg.make_global(value.get_type().into_owned());
}

Expand Down Expand Up @@ -491,10 +491,10 @@ impl<'function, 'global> PerFunctionContext<'function, 'global> {
Value::Global(_) => {
// TODO: Inlining the global into the function is only a temporary measure
// until Brillig gen with globals is working end to end
match &self.context.globals[id] {
match &self.context.globals.dfg[id] {
Value::Instruction { instruction, .. } => {
let Instruction::MakeArray { elements, typ } =
&self.context.globals[*instruction]
&self.context.globals.dfg[*instruction]
else {
panic!("Only expect Instruction::MakeArray for a global");
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl Ssa {
let mut context = Context::default();
context.populate_functions(&self.functions);
for function in self.functions.values_mut() {
context.normalize_ids(function, &self.globals);
context.normalize_ids(function, &self.globals.dfg);
}
self.functions = context.functions.into_btree();
}
Expand Down
27 changes: 21 additions & 6 deletions compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use noirc_frontend::monomorphization::ast::{FuncId, Program};
use crate::errors::RuntimeError;
use crate::ssa::function_builder::FunctionBuilder;
use crate::ssa::ir::basic_block::BasicBlockId;
use crate::ssa::ir::dfg::DataFlowGraph;
use crate::ssa::ir::function::FunctionId as IrFunctionId;
use crate::ssa::ir::function::{Function, RuntimeType};
use crate::ssa::ir::instruction::BinaryOp;
Expand Down Expand Up @@ -56,7 +55,6 @@ pub(super) struct FunctionContext<'a> {
/// SSA can be generated by continuously popping from this function_queue and using
/// FunctionContext to generate from the popped function id. Once the queue is empty,
/// no other functions are reachable and the SSA generation is finished.
#[derive(Default)]
pub(super) struct SharedContext {
/// All currently known functions which have already been assigned function ids.
/// These functions are all either currently having their SSA generated or are
Expand All @@ -74,7 +72,11 @@ pub(super) struct SharedContext {
/// Shared counter used to assign the ID of the next function
function_counter: AtomicCounter<Function>,

pub(super) globals_context: DataFlowGraph,
/// A pseudo function that represents global values.
/// Globals are only concerned with the values and instructions (due to Instruction::MakeArray)
/// in a function's DataFlowGraph. However, in order to re-use various codegen methods
/// we need to use the same `Function` type.
pub(super) globals_context: Function,

pub(super) globals: BTreeMap<GlobalId, Values>,

Expand Down Expand Up @@ -142,7 +144,7 @@ impl<'a> FunctionContext<'a> {
}

fn add_globals(&mut self) {
for (_, value) in self.shared_context.globals_context.values_iter() {
for (_, value) in self.shared_context.globals_context.dfg.values_iter() {
self.builder.current_function.dfg.make_global(value.get_type().into_owned());
}
}
Expand Down Expand Up @@ -1044,7 +1046,7 @@ fn convert_operator(op: BinaryOpKind) -> BinaryOp {
impl SharedContext {
/// Create a new SharedContext for the given monomorphized program.
pub(super) fn new(program: Program) -> Self {
let globals_shared_context = SharedContext::default();
let globals_shared_context = SharedContext::new_for_globals();

let globals_id = Program::global_space_id();

Expand All @@ -1068,11 +1070,24 @@ impl SharedContext {
function_queue: Default::default(),
function_counter: Default::default(),
program,
globals_context: context.builder.current_function.dfg,
globals_context: context.builder.current_function,
globals,
}
}

pub(super) fn new_for_globals() -> Self {
let globals_context = Function::new_for_globals();

Self {
functions: Default::default(),
function_queue: Default::default(),
function_counter: Default::default(),
program: Default::default(),
globals_context,
globals: Default::default(),
}
}

/// Pops the next function from the shared function queue, returning None if the queue is empty.
pub(super) fn pop_next_function_in_queue(&self) -> Option<(FuncId, IrFunctionId)> {
self.function_queue.lock().expect("Failed to lock function_queue").pop()
Expand Down
7 changes: 4 additions & 3 deletions compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize};
use serde_with::serde_as;

use crate::ssa::ir::{
dfg::DataFlowGraph,
function::{Function, FunctionId},
map::AtomicCounter,
};
Expand All @@ -18,7 +17,7 @@ use noirc_frontend::hir_def::types::Type as HirType;
pub(crate) struct Ssa {
#[serde_as(as = "Vec<(_, _)>")]
pub(crate) functions: BTreeMap<FunctionId, Function>,
pub(crate) globals: DataFlowGraph,
pub(crate) globals: Function,
pub(crate) main_id: FunctionId,
#[serde(skip)]
pub(crate) next_id: AtomicCounter<Function>,
Expand Down Expand Up @@ -55,7 +54,9 @@ impl Ssa {
next_id: AtomicCounter::starting_after(max_id),
entry_point_to_generated_index: BTreeMap::new(),
error_selector_to_type: error_types,
globals: DataFlowGraph::default(),
// This field should be set afterwards as globals are generated
// outside of the FunctionBuilder, which is where the `Ssa` is instantiated.
globals: Function::new_for_globals(),
}
}

Expand Down

0 comments on commit 8ff2934

Please sign in to comment.