From 9fb77b139cdca101b6582e63f466771e679ecc7b Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 9 Nov 2021 13:25:00 +0100 Subject: [PATCH] Keep canonical form of Yul code at all times. --- libyul/optimiser/BlockFlattener.cpp | 12 ++++++++++++ libyul/optimiser/BlockFlattener.h | 2 +- libyul/optimiser/CircularReferencesPruner.cpp | 2 ++ libyul/optimiser/ExpressionJoiner.cpp | 4 +++- libyul/optimiser/FunctionGrouper.h | 2 +- libyul/optimiser/OptimizerUtilities.h | 2 ++ libyul/optimiser/Suite.cpp | 2 +- libyul/optimiser/UnusedPruner.cpp | 7 +++++++ libyul/optimiser/UnusedPruner.h | 4 +--- 9 files changed, 30 insertions(+), 7 deletions(-) diff --git a/libyul/optimiser/BlockFlattener.cpp b/libyul/optimiser/BlockFlattener.cpp index bcbe19c18..0bb828ee5 100644 --- a/libyul/optimiser/BlockFlattener.cpp +++ b/libyul/optimiser/BlockFlattener.cpp @@ -43,3 +43,15 @@ void BlockFlattener::operator()(Block& _block) } ); } + +void BlockFlattener::run(OptimiserStepContext&, Block& _ast) +{ + BlockFlattener flattener; + for (auto& statement: _ast.statements) + if (auto* block = get_if(&statement)) + flattener(*block); + else if (auto* function = get_if(&statement)) + flattener(function->body); + else + yulAssert(false, "BlockFlattener requires the FunctionGrouper."); +} diff --git a/libyul/optimiser/BlockFlattener.h b/libyul/optimiser/BlockFlattener.h index 87a1af7cf..3825647de 100644 --- a/libyul/optimiser/BlockFlattener.h +++ b/libyul/optimiser/BlockFlattener.h @@ -27,7 +27,7 @@ class BlockFlattener: public ASTModifier { public: static constexpr char const* name{"BlockFlattener"}; - static void run(OptimiserStepContext&, Block& _ast) { BlockFlattener{}(_ast); } + static void run(OptimiserStepContext&, Block& _ast); using ASTModifier::operator(); void operator()(Block& _block) override; diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index 1078779c5..ba1fbf11d 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -29,6 +30,7 @@ using namespace solidity::yul; void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast) { CircularReferencesPruner{_context.reservedIdentifiers}(_ast); + FunctionGrouper::run(_context, _ast); } void CircularReferencesPruner::operator()(Block& _block) diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index 9d1df8694..dbb684007 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -37,9 +38,10 @@ using namespace std; using namespace solidity; using namespace solidity::yul; -void ExpressionJoiner::run(OptimiserStepContext&, Block& _ast) +void ExpressionJoiner::run(OptimiserStepContext& _context, Block& _ast) { ExpressionJoiner{_ast}(_ast); + FunctionGrouper::run(_context, _ast); } diff --git a/libyul/optimiser/FunctionGrouper.h b/libyul/optimiser/FunctionGrouper.h index fa5409936..57ea80cac 100644 --- a/libyul/optimiser/FunctionGrouper.h +++ b/libyul/optimiser/FunctionGrouper.h @@ -34,7 +34,7 @@ struct OptimiserStepContext; * all function definitions. * * After this step, a block is of the form - * { { I...} F... } + * { { I... } F... } * Where I are (non-function-definition) instructions and F are function definitions. */ class FunctionGrouper diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 09ea9ed5a..d80b16316 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -37,6 +37,8 @@ namespace solidity::yul { /// Removes statements that are just empty blocks (non-recursive). +/// If this is run on the outermost block, the FunctionGrouper should be run afterwards to keep +/// the canonical form. void removeEmptyBlocks(Block& _block); /// Returns true if a given literal can not be used as an identifier. diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 32ea08dbe..766cc93b9 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -118,7 +118,7 @@ void OptimiserSuite::run( // Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. - suite.runSequence("hfgo", ast); + suite.runSequence("hgfo", ast); NameSimplifier::run(suite.m_context, ast); // Now the user-supplied part diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index dae4d4c6f..cb60f9da8 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,12 @@ using namespace std; using namespace solidity; using namespace solidity::yul; +void UnusedPruner::run(OptimiserStepContext& _context, Block& _ast) +{ + UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers); + FunctionGrouper::run(_context, _ast); +} + UnusedPruner::UnusedPruner( Dialect const& _dialect, Block& _ast, diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index af77d911a..e4587d5d7 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -50,9 +50,7 @@ class UnusedPruner: public ASTModifier { public: static constexpr char const* name{"UnusedPruner"}; - static void run(OptimiserStepContext& _context, Block& _ast) { - UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers); - } + static void run(OptimiserStepContext& _context, Block& _ast); using ASTModifier::operator();