Use NodeBuilder in DCE

This commit is contained in:
Pranav Gaddamadugu 2023-08-16 13:33:43 -04:00
parent 26fffd6746
commit 637e091abb
6 changed files with 31 additions and 70 deletions

View File

@ -15,14 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
Expression,
ExpressionReconstructor,
Identifier,
NodeID,
NodeReconstructor,
ProgramReconstructor,
Statement,
StatementReconstructor,
};
use std::cell::RefCell;
@ -45,24 +38,6 @@ impl NodeBuilder {
pub fn next_id(&self) -> NodeID {
self.inner.borrow_mut().next_id()
}
/// Returns the identifier, modified to have a unique `NodeID`.
pub fn unique_identifier(&self, identifier: Identifier) -> Identifier {
match self.inner.borrow_mut().reconstruct_identifier(identifier).0 {
Expression::Identifier(identifier) => identifier,
_ => unreachable!(),
}
}
/// Returns the expression, modified to have unique `NodeID`s.
pub fn unique_expression(&self, expression: Expression) -> Expression {
self.inner.borrow_mut().reconstruct_expression(expression).0
}
/// Returns the statement, modified to have unique `NodeID`s.
pub fn unique_statement(&self, statement: Statement) -> Statement {
self.inner.borrow_mut().reconstruct_statement(statement).0
}
}
impl Default for NodeBuilder {
@ -92,17 +67,3 @@ impl NodeBuilderInner {
next
}
}
impl NodeReconstructor for NodeBuilderInner {
fn reconstruct_node_id(&mut self, _: NodeID) -> NodeID {
self.next_id()
}
}
impl ExpressionReconstructor for NodeBuilderInner {
type AdditionalOutput = ();
}
impl StatementReconstructor for NodeBuilderInner {}
impl ProgramReconstructor for NodeBuilderInner {}

View File

@ -14,21 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::NodeBuilder;
use leo_span::Symbol;
use indexmap::IndexSet;
#[derive(Default)]
pub struct DeadCodeEliminator {
pub struct DeadCodeEliminator<'a> {
/// A counter to generate unique node IDs.
pub(crate) node_builder: &'a NodeBuilder,
/// The set of used variables in the current function body.
pub(crate) used_variables: IndexSet<Symbol>,
/// Whether or not the variables are necessary.
pub(crate) is_necessary: bool,
}
impl DeadCodeEliminator {
impl<'a> DeadCodeEliminator<'a> {
/// Initializes a new `DeadCodeEliminator`.
pub fn new() -> Self {
Self { used_variables: Default::default(), is_necessary: false }
pub fn new(node_builder: &'a NodeBuilder) -> Self {
Self { node_builder, used_variables: Default::default(), is_necessary: false }
}
}

View File

@ -23,7 +23,6 @@ use leo_ast::{
ExpressionReconstructor,
Identifier,
MemberAccess,
NodeID,
StructExpression,
StructVariableInitializer,
TupleAccess,
@ -31,7 +30,7 @@ use leo_ast::{
};
use leo_span::sym;
impl ExpressionReconstructor for DeadCodeEliminator {
impl ExpressionReconstructor for DeadCodeEliminator<'_> {
type AdditionalOutput = ();
/// Reconstructs the components of an access expression.
@ -58,7 +57,7 @@ impl ExpressionReconstructor for DeadCodeEliminator {
.map(|arg| self.reconstruct_expression(arg).0)
.collect(),
span: function.span,
id: NodeID::default(),
id: function.id,
});
// Unset `self.is_necessary`.
self.is_necessary = false;
@ -68,13 +67,13 @@ impl ExpressionReconstructor for DeadCodeEliminator {
inner: Box::new(self.reconstruct_expression(*member.inner).0),
name: member.name,
span: member.span,
id: NodeID::default(),
id: member.id
}),
AccessExpression::Tuple(tuple) => AccessExpression::Tuple(TupleAccess {
tuple: Box::new(self.reconstruct_expression(*tuple.tuple).0),
index: tuple.index,
span: tuple.span,
id: NodeID::default(),
id: tuple.id,
}),
AccessExpression::AssociatedConstant(constant) => AccessExpression::AssociatedConstant(constant),
}),
@ -99,11 +98,11 @@ impl ExpressionReconstructor for DeadCodeEliminator {
None => unreachable!("Static single assignment ensures that the expression always exists."),
},
span: member.span,
id: NodeID::default(),
id: member.id,
})
.collect(),
span: input.span,
id: NodeID::default(),
id: input.id,
}),
Default::default(),
)

View File

@ -16,9 +16,9 @@
use crate::DeadCodeEliminator;
use leo_ast::{Finalize, Function, NodeID, ProgramReconstructor, StatementReconstructor};
use leo_ast::{Finalize, Function, ProgramReconstructor, StatementReconstructor};
impl ProgramReconstructor for DeadCodeEliminator {
impl ProgramReconstructor for DeadCodeEliminator<'_> {
fn reconstruct_function(&mut self, input: Function) -> Function {
// Reset the state of the dead code eliminator.
self.used_variables.clear();
@ -43,7 +43,7 @@ impl ProgramReconstructor for DeadCodeEliminator {
output_type: finalize.output_type,
block,
span: finalize.span,
id: NodeID::default(),
id: finalize.id,
}
});
@ -57,7 +57,7 @@ impl ProgramReconstructor for DeadCodeEliminator {
block,
finalize,
span: input.span,
id: NodeID::default(),
id: input.id,
}
}
}

View File

@ -29,13 +29,12 @@ use leo_ast::{
ExpressionReconstructor,
ExpressionStatement,
IterationStatement,
NodeID,
ReturnStatement,
Statement,
StatementReconstructor,
};
impl StatementReconstructor for DeadCodeEliminator {
impl StatementReconstructor for DeadCodeEliminator<'_> {
fn reconstruct_assert(&mut self, input: AssertStatement) -> (Statement, Self::AdditionalOutput) {
// Set the `is_necessary` flag.
self.is_necessary = true;
@ -52,7 +51,7 @@ impl StatementReconstructor for DeadCodeEliminator {
}
},
span: input.span,
id: NodeID::default(),
id: input.id,
});
// Unset the `is_necessary` flag.
@ -92,7 +91,7 @@ impl StatementReconstructor for DeadCodeEliminator {
place: input.place,
value: self.reconstruct_expression(input.value).0,
span: input.span,
id: NodeID::default(),
id: input.id,
}));
// Unset the `is_necessary` flag.
@ -101,7 +100,7 @@ impl StatementReconstructor for DeadCodeEliminator {
(statement, Default::default())
}
// Otherwise, we can eliminate it.
false => (Statement::dummy(Default::default()), Default::default()),
false => (Statement::dummy(Default::default(), self.node_builder.next_id()), Default::default()),
}
}
@ -114,7 +113,7 @@ impl StatementReconstructor for DeadCodeEliminator {
// Reverse the direction of `statements`.
statements.reverse();
(Block { statements, span: block.span, id: NodeID::default() }, Default::default())
(Block { statements, span: block.span, id: block.id }, Default::default())
}
/// Flattening removes conditional statements from the program.
@ -145,7 +144,7 @@ impl StatementReconstructor for DeadCodeEliminator {
let statement = Statement::Expression(ExpressionStatement {
expression: self.reconstruct_call(expression).0,
span: input.span,
id: NodeID::default(),
id: input.id,
});
// Unset the `is_necessary` flag.
@ -161,14 +160,14 @@ impl StatementReconstructor for DeadCodeEliminator {
.reconstruct_access(AccessExpression::AssociatedFunction(associated_function))
.0,
span: input.span,
id: NodeID::default(),
id: input.id,
}),
Default::default(),
)
}
// Any other expression is dead code, since they do not have side effects.
// Note: array access expressions will have side effects and need to be handled here.
_ => (Statement::dummy(Default::default()), Default::default()),
_ => (Statement::dummy(Default::default(), self.node_builder.next_id()), Default::default()),
}
}
@ -188,7 +187,7 @@ impl StatementReconstructor for DeadCodeEliminator {
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
}),
span: input.span,
id: NodeID::default(),
id: input.id,
});
// Unset the `is_necessary` flag.

View File

@ -60,15 +60,15 @@ pub use dead_code_eliminator::*;
use crate::Pass;
use leo_ast::{Ast, ProgramReconstructor};
use leo_ast::{Ast, NodeBuilder, ProgramReconstructor};
use leo_errors::Result;
impl Pass for DeadCodeEliminator {
type Input = Ast;
impl<'a> Pass for DeadCodeEliminator<'a> {
type Input = (Ast, &'a NodeBuilder);
type Output = Result<Ast>;
fn do_pass(ast: Self::Input) -> Self::Output {
let mut reconstructor = DeadCodeEliminator::new();
fn do_pass((ast, node_builder): Self::Input) -> Self::Output {
let mut reconstructor = DeadCodeEliminator::new(node_builder);
let program = reconstructor.reconstruct_program(ast.into_repr());
Ok(Ast::new(program))