mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
Update SSA pass
This commit is contained in:
parent
17cdda2227
commit
3b720001d6
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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."),
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user