Update SSA pass

This commit is contained in:
Pranav Gaddamadugu 2023-10-12 09:24:13 -04:00 committed by Pranav Gaddamadugu
parent 17cdda2227
commit 3b720001d6
4 changed files with 34 additions and 18 deletions

View File

@ -65,13 +65,13 @@ use leo_ast::{Ast, NodeBuilder, ProgramConsumer};
use leo_errors::Result;
impl<'a> Pass for StaticSingleAssigner<'a> {
type Input = (Ast, &'a NodeBuilder, &'a Assigner, &'a SymbolTable, TypeTable);
type Output = Result<(Ast, TypeTable)>;
type Input = (Ast, &'a NodeBuilder, &'a Assigner, &'a SymbolTable, &'a TypeTable);
type Output = Result<Ast>;
fn do_pass((ast, node_builder, assigner, symbol_table, type_table): Self::Input) -> Self::Output {
let mut consumer = StaticSingleAssigner::new(node_builder, symbol_table, type_table, assigner);
let program = consumer.consume_program(ast.into_repr());
Ok((Ast::new(program), consumer.type_table))
Ok(Ast::new(program))
}
}

View File

@ -298,7 +298,9 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
/// Consumes and returns the literal without making any modifications.
fn consume_literal(&mut self, input: Literal) -> Self::Output {
(Expression::Literal(input), Default::default())
// Construct and accumulate a new assignment statement for the literal.
let (place, statement) = self.unique_simple_assign_statement(Expression::Literal(input));
(Expression::Identifier(place), vec![statement])
}
/// Consumes a ternary expression, accumulating any statements that are generated.

View File

@ -176,8 +176,8 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
let name =
*table.lookup(symbol).unwrap_or_else(|| panic!("Symbol {symbol} should exist in the program."));
let id = *table
.lookup_id(symbol)
.unwrap_or_else(|| panic!("Symbol {symbol} should exist in the program."));
.lookup_id(&name)
.unwrap_or_else(|| panic!("Symbol {name} should exist in the rename table."));
Box::new(Expression::Identifier(Identifier { name, span: Default::default(), id }))
};
@ -192,7 +192,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
let id = self.node_builder.next_id();
// Update the type of the node ID.
let type_ = match self.type_table.get(&if_true.id()) {
Some(type_) => type_.clone(),
Some(type_) => type_,
None => unreachable!("Type checking guarantees that all expressions have a type."),
};
self.type_table.insert(id, type_);
@ -208,15 +208,19 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
statements.extend(stmts);
// Update the `RenameTable` with the new name of the variable.
let id = match self.rename_table.lookup_id(**symbol) {
Some(id) => id,
None => unreachable!("The ID for the symbol `{}` should already exist in the program.", symbol),
// Get the ID for the new name of the variable.
let id = match self.rename_table.lookup_id(symbol) {
Some(id) => *id,
None => {
unreachable!("The ID for the symbol `{}` should already exist in the rename table.", symbol)
}
};
self.rename_table.update(*(*symbol), new_name, *id);
// Update the `RenameTable` with the new name of the variable.
self.rename_table.update(*(*symbol), new_name, id);
// Create a new `AssignStatement` for the phi function.
let identifier = Identifier { name: new_name, span: Default::default(), id: *id };
let identifier = Identifier { name: new_name, span: Default::default(), id };
let assignment = self.simple_assign_statement(identifier, value);
// Store the generated phi function.
@ -246,20 +250,28 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
self.is_lhs = true;
match definition.place {
Expression::Identifier(identifier) => {
// Add the identifier to the rename table.
self.rename_table.update(identifier.name, identifier.name, identifier.id);
// Rename the identifier.
let identifier = match self.consume_identifier(identifier).0 {
Expression::Identifier(identifier) => identifier,
_ => unreachable!("`self.consume_identifier` will always return an `Identifier`."),
};
// Create a new assignment statement.
statements.push(self.simple_assign_statement(identifier, value));
}
Expression::Tuple(tuple) => {
let elements: Vec<Expression> = tuple.elements.into_iter().map(|element| {
match element {
Expression::Identifier(identifier) => {
// Add the identifier to the rename table.
self.rename_table.update(identifier.name, identifier.name, identifier.id);
// Rename the identifier.
let identifier = match self.consume_identifier(identifier).0 {
Expression::Identifier(identifier) => identifier,
_ => unreachable!("`self.consume_identifier` will always return an `Identifier`."),
};
// Return the renamed identifier.
Expression::Identifier(identifier)
}
_ => unreachable!("Type checking guarantees that the tuple elements on the lhs of a `DefinitionStatement` are always be identifiers."),
@ -268,7 +280,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
// Get the type of `value`.
let tuple_type_ = match self.type_table.get(&value.id()) {
Some(Type::Tuple(type_)) => type_.clone(),
Some(Type::Tuple(type_)) => type_,
_ => unreachable!("Type checking guarantees that this expression is a tuple."),
};

View File

@ -24,7 +24,7 @@ pub struct StaticSingleAssigner<'a> {
/// The `SymbolTable` of the program.
pub(crate) symbol_table: &'a SymbolTable,
/// A mapping from node IDs to their types.
pub(crate) type_table: TypeTable,
pub(crate) type_table: &'a TypeTable,
/// The `RenameTable` for the current basic block in the AST
pub(crate) rename_table: RenameTable,
/// A flag to determine whether or not the traversal is on the left-hand side of a definition or an assignment.
@ -38,7 +38,7 @@ impl<'a> StaticSingleAssigner<'a> {
pub(crate) fn new(
node_builder: &'a NodeBuilder,
symbol_table: &'a SymbolTable,
type_table: TypeTable,
type_table: &'a TypeTable,
assigner: &'a Assigner,
) -> Self {
Self { node_builder, symbol_table, type_table, rename_table: RenameTable::new(None), is_lhs: false, assigner }
@ -59,10 +59,12 @@ impl<'a> StaticSingleAssigner<'a> {
pub(crate) fn simple_assign_statement(&mut self, identifier: Identifier, rhs: Expression) -> Statement {
// Update the type table.
let type_ = match self.type_table.get(&rhs.id()) {
Some(type_) => type_.clone(),
Some(type_) => type_,
None => unreachable!("Type checking guarantees that all expressions have a type."),
};
self.type_table.insert(identifier.id(), type_);
// Update the rename table.
self.rename_table.update(identifier.name, identifier.name, identifier.id);
// Construct the statement.
self.assigner.simple_assign_statement(identifier, rhs, self.node_builder.next_id())
}
@ -78,7 +80,7 @@ impl<'a> StaticSingleAssigner<'a> {
let place = Identifier { name, span: Default::default(), id: self.node_builder.next_id() };
// Construct the statement.
let statement = self.simple_assign_statement(place.clone(), expr);
let statement = self.simple_assign_statement(place, expr);
(place, statement)
}