Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: parse globals in SSA parser #7112

Merged
merged 10 commits into from
Jan 21, 2025
27 changes: 26 additions & 1 deletion compiler/noirc_evaluator/src/ssa/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,28 @@ use crate::ssa::ir::{function::RuntimeType, instruction::BinaryOp, types::Type};

#[derive(Debug)]
pub(crate) struct ParsedSsa {
pub(crate) globals: Vec<ParsedGlobal>,
pub(crate) functions: Vec<ParsedFunction>,
}

#[derive(Debug)]
pub(crate) struct ParsedGlobal {
pub(crate) name: Identifier,
pub(crate) value: ParsedGlobalValue,
}

#[derive(Debug)]
pub(crate) enum ParsedGlobalValue {
NumericConstant(ParsedNumericConstant),
MakeArray(ParsedMakeArray),
}

#[derive(Debug)]
pub(crate) struct ParsedMakeArray {
pub(crate) elements: Vec<ParsedValue>,
pub(crate) typ: Type,
}

#[derive(Debug)]
pub(crate) struct ParsedFunction {
pub(crate) runtime_type: RuntimeType,
Expand Down Expand Up @@ -145,6 +164,12 @@ pub(crate) enum ParsedTerminator {

#[derive(Debug, Clone)]
pub(crate) enum ParsedValue {
NumericConstant { constant: FieldElement, typ: Type },
NumericConstant(ParsedNumericConstant),
Variable(Identifier),
}

#[derive(Debug, Clone)]
pub(crate) struct ParsedNumericConstant {
pub(crate) value: FieldElement,
pub(crate) typ: Type,
}
79 changes: 72 additions & 7 deletions compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ use crate::ssa::{
function_builder::FunctionBuilder,
ir::{
basic_block::BasicBlockId,
call_stack::CallStackId,
function::{Function, FunctionId},
instruction::ConstrainError,
instruction::{ConstrainError, Instruction},
value::ValueId,
},
};

use super::{
ast::AssertMessage, Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedSsa,
ParsedTerminator, ParsedValue, RuntimeType, Ssa, SsaError,
ast::AssertMessage, Identifier, ParsedBlock, ParsedFunction, ParsedGlobal, ParsedGlobalValue,
ParsedInstruction, ParsedSsa, ParsedTerminator, ParsedValue, RuntimeType, Ssa, SsaError,
};

impl ParsedSsa {
Expand All @@ -39,6 +40,12 @@ struct Translator {
/// will recreate the SSA step by step, which can result in a new ID layout.
variables: HashMap<FunctionId, HashMap<String, ValueId>>,

/// The function that will hold the actual SSA globals.
globals_function: Function,

/// Maps names like g0, g1, etc., in the parsed SSA to global IDs.
globals: HashMap<String, ValueId>,

error_selector_counter: u64,
}

Expand All @@ -52,6 +59,10 @@ impl Translator {
translator.translate_non_main_function(function)?;
}

for global in parsed_ssa.globals {
translator.translate_global(global)?;
}

Ok(translator.finish())
}

Expand All @@ -74,11 +85,16 @@ impl Translator {
functions.insert(function.internal_name.clone(), function_id);
}

// Does not matter what ID we use here.
let globals = Function::new("globals".to_owned(), main_id);

let mut translator = Self {
builder,
functions,
variables: HashMap::new(),
blocks: HashMap::new(),
globals_function: globals,
globals: HashMap::new(),
error_selector_counter: 0,
};
translator.translate_function_body(main_function)?;
Expand Down Expand Up @@ -292,13 +308,45 @@ impl Translator {

fn translate_value(&mut self, value: ParsedValue) -> Result<ValueId, SsaError> {
match value {
ParsedValue::NumericConstant { constant, typ } => {
Ok(self.builder.numeric_constant(constant, typ.unwrap_numeric()))
ParsedValue::NumericConstant(constant) => {
Ok(self.builder.numeric_constant(constant.value, constant.typ.unwrap_numeric()))
}
ParsedValue::Variable(identifier) => self.lookup_variable(identifier),
}
}

fn translate_global(&mut self, global: ParsedGlobal) -> Result<(), SsaError> {
let value_id = match global.value {
ParsedGlobalValue::NumericConstant(constant) => self
.globals_function
.dfg
.make_constant(constant.value, constant.typ.unwrap_numeric()),
ParsedGlobalValue::MakeArray(make_array) => {
let mut elements = im::Vector::new();
for element in make_array.elements {
let element_id = match element {
ParsedValue::NumericConstant(constant) => self
.globals_function
.dfg
.make_constant(constant.value, constant.typ.unwrap_numeric()),
ParsedValue::Variable(identifier) => self.lookup_global(identifier)?,
};
elements.push_back(element_id);
}

let instruction = Instruction::MakeArray { elements, typ: make_array.typ };
let block = self.globals_function.entry_block();
let call_stack = CallStackId::root();
self.globals_function
.dfg
.insert_instruction_and_results(instruction, block, None, call_stack)
.first()
}
};

self.define_global(global.name, value_id)
}

fn define_variable(
&mut self,
identifier: Identifier,
Expand All @@ -324,6 +372,24 @@ impl Translator {
}
}

fn define_global(&mut self, identifier: Identifier, value_id: ValueId) -> Result<(), SsaError> {
if self.globals.contains_key(&identifier.name) {
return Err(SsaError::GlobalAlreadyDefined(identifier));
}

self.globals.insert(identifier.name, value_id);

Ok(())
}

fn lookup_global(&mut self, identifier: Identifier) -> Result<ValueId, SsaError> {
if let Some(value_id) = self.globals.get(&identifier.name) {
Ok(*value_id)
} else {
Err(SsaError::UnknownGlobal(identifier))
}
}

fn lookup_block(&mut self, identifier: Identifier) -> Result<BasicBlockId, SsaError> {
if let Some(block_id) = self.blocks[&self.current_function_id()].get(&identifier.name) {
Ok(*block_id)
Expand All @@ -347,8 +413,7 @@ impl Translator {
// that the SSA we parsed was printed by the `SsaBuilder`, which normalizes
// before each print.
ssa.normalize_ids();
// Does not matter what ID we use here.
ssa.globals = Function::new("globals".to_owned(), ssa.main_id);
ssa.globals = self.globals_function;
ssa
}

Expand Down
Loading
Loading