Make the dialect available everywhere.

This commit is contained in:
chriseth 2018-12-20 18:55:32 +01:00
parent d9910f2a12
commit 9222eff08f
29 changed files with 198 additions and 116 deletions

View File

@ -134,7 +134,7 @@ void AssemblyStack::optimize(yul::Object& _object)
for (auto& subNode: _object.subObjects) for (auto& subNode: _object.subObjects)
if (auto subObject = dynamic_cast<yul::Object*>(subNode.get())) if (auto subObject = dynamic_cast<yul::Object*>(subNode.get()))
optimize(*subObject); optimize(*subObject);
yul::OptimiserSuite::run(*_object.code, *_object.analysisInfo); yul::OptimiserSuite::run(*languageToDialect(m_language), *_object.code, *_object.analysisInfo);
} }
MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize) const MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize) const

View File

@ -34,6 +34,9 @@ namespace yul
*/ */
class CommonSubexpressionEliminator: public DataFlowAnalyzer class CommonSubexpressionEliminator: public DataFlowAnalyzer
{ {
public:
CommonSubexpressionEliminator(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}
protected: protected:
using ASTModifier::visit; using ASTModifier::visit;
void visit(Expression& _e) override; void visit(Expression& _e) override;

View File

@ -142,7 +142,7 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres
static Expression const zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; static Expression const zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}};
clearValues(_variables); clearValues(_variables);
MovableChecker movableChecker; MovableChecker movableChecker{m_dialect};
if (_value) if (_value)
movableChecker.visit(*_value); movableChecker.visit(*_value);
else else

View File

@ -30,6 +30,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Base class to perform data flow analysis during AST walks. * Base class to perform data flow analysis during AST walks.
@ -43,6 +44,8 @@ namespace yul
class DataFlowAnalyzer: public ASTModifier class DataFlowAnalyzer: public ASTModifier
{ {
public: public:
explicit DataFlowAnalyzer(Dialect const& _dialect): m_dialect(_dialect) {}
using ASTModifier::operator(); using ASTModifier::operator();
void operator()(Assignment& _assignment) override; void operator()(Assignment& _assignment) override;
void operator()(VariableDeclaration& _varDecl) override; void operator()(VariableDeclaration& _varDecl) override;
@ -84,6 +87,7 @@ protected:
}; };
/// List of scopes. /// List of scopes.
std::vector<Scope> m_variableScopes; std::vector<Scope> m_variableScopes;
Dialect const& m_dialect;
}; };
} }

View File

@ -23,6 +23,7 @@
#include <libyul/Exceptions.h> #include <libyul/Exceptions.h>
#include <libyul/AsmData.h> #include <libyul/AsmData.h>
#include <libyul/AsmScope.h> #include <libyul/AsmScope.h>
#include <libyul/Dialect.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -31,7 +32,7 @@ using namespace dev::solidity;
YulString Disambiguator::translateIdentifier(YulString _originalName) YulString Disambiguator::translateIdentifier(YulString _originalName)
{ {
if ((m_externallyUsedIdentifiers.count(_originalName))) if (m_dialect.builtin(_originalName) || m_externallyUsedIdentifiers.count(_originalName))
return _originalName; return _originalName;
assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, ""); assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, "");

View File

@ -32,6 +32,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Creates a copy of a Yul AST replacing all identifiers by unique names. * Creates a copy of a Yul AST replacing all identifiers by unique names.
@ -40,10 +41,14 @@ class Disambiguator: public ASTCopier
{ {
public: public:
explicit Disambiguator( explicit Disambiguator(
Dialect const& _dialect,
AsmAnalysisInfo const& _analysisInfo, AsmAnalysisInfo const& _analysisInfo,
std::set<YulString> const& _externallyUsedIdentifiers = {} std::set<YulString> const& _externallyUsedIdentifiers = {}
): ):
m_info(_analysisInfo), m_externallyUsedIdentifiers(_externallyUsedIdentifiers), m_nameDispenser(m_externallyUsedIdentifiers) m_info(_analysisInfo),
m_dialect(_dialect),
m_externallyUsedIdentifiers(_externallyUsedIdentifiers),
m_nameDispenser(_dialect, m_externallyUsedIdentifiers)
{ {
} }
@ -58,6 +63,7 @@ protected:
void leaveScopeInternal(Scope& _scope); void leaveScopeInternal(Scope& _scope);
AsmAnalysisInfo const& m_info; AsmAnalysisInfo const& m_info;
Dialect const& m_dialect;
std::set<YulString> const& m_externallyUsedIdentifiers; std::set<YulString> const& m_externallyUsedIdentifiers;
std::vector<Scope*> m_scopes; std::vector<Scope*> m_scopes;

View File

@ -56,7 +56,7 @@ void ExpressionInliner::visit(Expression& _expression)
bool movable = boost::algorithm::all_of( bool movable = boost::algorithm::all_of(
funCall.arguments, funCall.arguments,
[=](Expression const& _arg) { return MovableChecker(_arg).movable(); } [=](Expression const& _arg) { return MovableChecker(m_dialect, _arg).movable(); }
); );
if (m_inlinableFunctions.count(funCall.functionName.name) && movable) if (m_inlinableFunctions.count(funCall.functionName.name) && movable)
{ {

View File

@ -29,6 +29,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Optimiser component that modifies an AST in place, inlining functions that can be * Optimiser component that modifies an AST in place, inlining functions that can be
@ -44,8 +45,8 @@ namespace yul
class ExpressionInliner: public ASTModifier class ExpressionInliner: public ASTModifier
{ {
public: public:
ExpressionInliner(Block& _block): ExpressionInliner(Dialect const& _dialect, Block& _block):
m_block(_block) m_block(_block), m_dialect(_dialect)
{} {}
void run(); void run();
@ -62,6 +63,7 @@ private:
std::set<YulString> m_currentFunctions; std::set<YulString> m_currentFunctions;
Block& m_block; Block& m_block;
Dialect const& m_dialect;
}; };

View File

@ -36,7 +36,7 @@ using namespace dev::solidity;
void ExpressionSimplifier::visit(Expression& _expression) void ExpressionSimplifier::visit(Expression& _expression)
{ {
ASTModifier::visit(_expression); ASTModifier::visit(_expression);
while (auto match = SimplificationRules::findFirstMatch(_expression, m_ssaValues)) while (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_ssaValues))
{ {
// Do not apply the rule if it removes non-constant parts of the expression. // Do not apply the rule if it removes non-constant parts of the expression.
// TODO: The check could actually be less strict than "movable". // TODO: The check could actually be less strict than "movable".
@ -45,15 +45,15 @@ void ExpressionSimplifier::visit(Expression& _expression)
// so if the value of the variable is not movable, the expression that references // so if the value of the variable is not movable, the expression that references
// the variable still is. // the variable still is.
if (match->removesNonConstants && !MovableChecker(_expression).movable()) if (match->removesNonConstants && !MovableChecker(m_dialect, _expression).movable())
return; return;
_expression = match->action().toExpression(locationOf(_expression)); _expression = match->action().toExpression(locationOf(_expression));
} }
} }
void ExpressionSimplifier::run(Block& _ast) void ExpressionSimplifier::run(Dialect const& _dialect, Block& _ast)
{ {
SSAValueTracker ssaValues; SSAValueTracker ssaValues;
ssaValues(_ast); ssaValues(_ast);
ExpressionSimplifier{ssaValues.values()}(_ast); ExpressionSimplifier{_dialect, ssaValues.values()}(_ast);
} }

View File

@ -26,6 +26,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Applies simplification rules to all expressions. * Applies simplification rules to all expressions.
@ -40,12 +41,13 @@ public:
using ASTModifier::operator(); using ASTModifier::operator();
virtual void visit(Expression& _expression); virtual void visit(Expression& _expression);
static void run(Block& _ast); static void run(Dialect const& _dialect, Block& _ast);
private: private:
explicit ExpressionSimplifier(std::map<YulString, Expression const*> _ssaValues): explicit ExpressionSimplifier(Dialect const& _dialect, std::map<YulString, Expression const*> _ssaValues):
m_ssaValues(std::move(_ssaValues)) m_dialect(_dialect), m_ssaValues(std::move(_ssaValues))
{} {}
Dialect const& m_dialect;
std::map<YulString, Expression const*> m_ssaValues; std::map<YulString, Expression const*> m_ssaValues;
}; };

View File

@ -22,17 +22,19 @@
#include <libyul/optimiser/NameCollector.h> #include <libyul/optimiser/NameCollector.h>
#include <libyul/AsmData.h> #include <libyul/AsmData.h>
#include <libyul/Dialect.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace yul; using namespace yul;
NameDispenser::NameDispenser(Block const& _ast): NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast):
NameDispenser(NameCollector(_ast).names()) NameDispenser(_dialect, NameCollector(_ast).names())
{ {
} }
NameDispenser::NameDispenser(set<YulString> _usedNames): NameDispenser::NameDispenser(Dialect const& _dialect, set<YulString> _usedNames):
m_dialect(_dialect),
m_usedNames(std::move(_usedNames)) m_usedNames(std::move(_usedNames))
{ {
} }
@ -51,7 +53,7 @@ YulString NameDispenser::newName(YulString _nameHint, YulString _context)
YulString NameDispenser::newNameInternal(YulString _nameHint) YulString NameDispenser::newNameInternal(YulString _nameHint)
{ {
YulString name = _nameHint; YulString name = _nameHint;
while (name.empty() || m_usedNames.count(name)) while (name.empty() || m_usedNames.count(name) || m_dialect.builtin(name))
{ {
m_counter++; m_counter++;
name = YulString(_nameHint.str() + "_" + to_string(m_counter)); name = YulString(_nameHint.str() + "_" + to_string(m_counter));

View File

@ -27,6 +27,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Optimizer component that can be used to generate new names that * Optimizer component that can be used to generate new names that
@ -38,9 +39,9 @@ class NameDispenser
{ {
public: public:
/// Initialize the name dispenser with all the names used in the given AST. /// Initialize the name dispenser with all the names used in the given AST.
explicit NameDispenser(Block const& _ast); explicit NameDispenser(Dialect const& _dialect, Block const& _ast);
/// Initialize the name dispenser with the given used names. /// Initialize the name dispenser with the given used names.
explicit NameDispenser(std::set<YulString> _usedNames); explicit NameDispenser(Dialect const& _dialect, std::set<YulString> _usedNames);
/// @returns a currently unused name that should be similar to _nameHint /// @returns a currently unused name that should be similar to _nameHint
/// and prefixed by _context if present. /// and prefixed by _context if present.
@ -51,6 +52,7 @@ public:
private: private:
YulString newNameInternal(YulString _nameHint); YulString newNameInternal(YulString _nameHint);
Dialect const& m_dialect;
std::set<YulString> m_usedNames; std::set<YulString> m_usedNames;
size_t m_counter = 0; size_t m_counter = 0;
}; };

View File

@ -150,9 +150,9 @@ void RedundantAssignEliminator::operator()(Block const& _block)
ASTWalker::operator()(_block); ASTWalker::operator()(_block);
} }
void RedundantAssignEliminator::run(Block& _ast) void RedundantAssignEliminator::run(Dialect const& _dialect, Block& _ast)
{ {
RedundantAssignEliminator rae; RedundantAssignEliminator rae{_dialect};
rae(_ast); rae(_ast);
AssignmentRemover remover{rae.m_assignmentsToRemove}; AssignmentRemover remover{rae.m_assignmentsToRemove};
@ -211,7 +211,7 @@ void RedundantAssignEliminator::finalize(YulString _variable)
for (auto& assignment: m_assignments[_variable]) for (auto& assignment: m_assignments[_variable])
{ {
assertThrow(assignment.second != State::Undecided, OptimizerException, ""); assertThrow(assignment.second != State::Undecided, OptimizerException, "");
if (assignment.second == State{State::Unused} && MovableChecker{*assignment.first->value}.movable()) if (assignment.second == State{State::Unused} && MovableChecker{*m_dialect, *assignment.first->value}.movable())
// TODO the only point where we actually need this // TODO the only point where we actually need this
// to be a set is for the for loop // to be a set is for the for loop
m_assignmentsToRemove.insert(assignment.first); m_assignmentsToRemove.insert(assignment.first);

View File

@ -28,6 +28,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Optimiser component that removes assignments to variables that are not used * Optimiser component that removes assignments to variables that are not used
@ -98,6 +99,7 @@ namespace yul
class RedundantAssignEliminator: public ASTWalker class RedundantAssignEliminator: public ASTWalker
{ {
public: public:
explicit RedundantAssignEliminator(Dialect const& _dialect): m_dialect(&_dialect) {}
RedundantAssignEliminator(RedundantAssignEliminator const&) = default; RedundantAssignEliminator(RedundantAssignEliminator const&) = default;
RedundantAssignEliminator& operator=(RedundantAssignEliminator const&) = default; RedundantAssignEliminator& operator=(RedundantAssignEliminator const&) = default;
RedundantAssignEliminator(RedundantAssignEliminator&&) = default; RedundantAssignEliminator(RedundantAssignEliminator&&) = default;
@ -112,7 +114,7 @@ public:
void operator()(ForLoop const&) override; void operator()(ForLoop const&) override;
void operator()(Block const& _block) override; void operator()(Block const& _block) override;
static void run(Block& _ast); static void run(Dialect const& _dialect, Block& _ast);
private: private:
RedundantAssignEliminator() = default; RedundantAssignEliminator() = default;
@ -167,6 +169,7 @@ private:
void changeUndecidedTo(YulString _variable, State _newState); void changeUndecidedTo(YulString _variable, State _newState);
void finalize(YulString _variable); void finalize(YulString _variable);
Dialect const* m_dialect;
std::set<YulString> m_declaredVariables; std::set<YulString> m_declaredVariables;
// TODO check that this does not cause nondeterminism! // TODO check that this does not cause nondeterminism!
// This could also be a pseudo-map from state to assignment. // This could also be a pseudo-map from state to assignment.

View File

@ -30,12 +30,13 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace yul; using namespace yul;
void Rematerialiser::run(Block& _ast) void Rematerialiser::run(Dialect const& _dialect, Block& _ast)
{ {
Rematerialiser{_ast}(_ast); Rematerialiser{_dialect, _ast}(_ast);
} }
Rematerialiser::Rematerialiser(Block& _ast): Rematerialiser::Rematerialiser(Dialect const& _dialect, Block& _ast):
DataFlowAnalyzer(_dialect),
m_referenceCounts(ReferencesCounter::countReferences(_ast)) m_referenceCounts(ReferencesCounter::countReferences(_ast))
{ {
} }

View File

@ -38,10 +38,10 @@ namespace yul
class Rematerialiser: public DataFlowAnalyzer class Rematerialiser: public DataFlowAnalyzer
{ {
public: public:
static void run(Block& _ast); static void run(Dialect const& _dialect, Block& _ast);
protected: protected:
Rematerialiser(Block& _ast); Rematerialiser(Dialect const& _dialect, Block& _ast);
using ASTModifier::visit; using ASTModifier::visit;
void visit(Expression& _e) override; void visit(Expression& _e) override;

View File

@ -22,6 +22,7 @@
#include <libyul/Exceptions.h> #include <libyul/Exceptions.h>
#include <libyul/AsmData.h> #include <libyul/AsmData.h>
#include <libyul/Dialect.h>
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
@ -31,7 +32,13 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace yul; using namespace yul;
MovableChecker::MovableChecker(Expression const& _expression) MovableChecker::MovableChecker(Dialect const& _dialect):
m_dialect(_dialect)
{
}
MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression):
MovableChecker(_dialect)
{ {
visit(_expression); visit(_expression);
} }
@ -50,8 +57,14 @@ void MovableChecker::operator()(FunctionalInstruction const& _instr)
ASTWalker::operator()(_instr); ASTWalker::operator()(_instr);
} }
void MovableChecker::operator()(FunctionCall const&) void MovableChecker::operator()(FunctionCall const& _functionCall)
{ {
if (BuiltinFunction const* f = m_dialect.builtin(_functionCall.functionName.name))
if (f->movable)
{
ASTWalker::operator()(_functionCall);
return;
}
m_movable = false; m_movable = false;
} }

View File

@ -26,6 +26,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Specific AST walker that determines whether an expression is movable. * Specific AST walker that determines whether an expression is movable.
@ -33,8 +34,8 @@ namespace yul
class MovableChecker: public ASTWalker class MovableChecker: public ASTWalker
{ {
public: public:
MovableChecker() = default; explicit MovableChecker(Dialect const& _dialect);
explicit MovableChecker(Expression const& _expression); MovableChecker(Dialect const& _dialect, Expression const& _expression);
void operator()(Identifier const& _identifier) override; void operator()(Identifier const& _identifier) override;
void operator()(FunctionalInstruction const& _functionalInstruction) override; void operator()(FunctionalInstruction const& _functionalInstruction) override;
@ -48,6 +49,7 @@ public:
std::set<YulString> const& referencedVariables() const { return m_variableReferences; } std::set<YulString> const& referencedVariables() const { return m_variableReferences; }
private: private:
Dialect const& m_dialect;
/// Which variables the current expression references. /// Which variables the current expression references.
std::set<YulString> m_variableReferences; std::set<YulString> m_variableReferences;
/// Is the current expression movable or not. /// Is the current expression movable or not.

View File

@ -36,6 +36,7 @@ using namespace yul;
SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch( SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch(
Expression const& _expr, Expression const& _expr,
Dialect const& _dialect,
map<YulString, Expression const*> const& _ssaValues map<YulString, Expression const*> const& _ssaValues
) )
{ {
@ -49,7 +50,7 @@ SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch(
for (auto const& rule: rules.m_rules[uint8_t(instruction.instruction)]) for (auto const& rule: rules.m_rules[uint8_t(instruction.instruction)])
{ {
rules.resetMatchGroups(); rules.resetMatchGroups();
if (rule.pattern.matches(_expr, _ssaValues)) if (rule.pattern.matches(_expr, _dialect, _ssaValues))
return &rule; return &rule;
} }
return nullptr; return nullptr;
@ -104,7 +105,11 @@ void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _
m_matchGroups = &_matchGroups; m_matchGroups = &_matchGroups;
} }
bool Pattern::matches(Expression const& _expr, map<YulString, Expression const*> const& _ssaValues) const bool Pattern::matches(
Expression const& _expr,
Dialect const& _dialect,
map<YulString, Expression const*> const& _ssaValues
) const
{ {
Expression const* expr = &_expr; Expression const* expr = &_expr;
@ -139,7 +144,7 @@ bool Pattern::matches(Expression const& _expr, map<YulString, Expression const*>
return false; return false;
assertThrow(m_arguments.size() == instr.arguments.size(), OptimizerException, ""); assertThrow(m_arguments.size() == instr.arguments.size(), OptimizerException, "");
for (size_t i = 0; i < m_arguments.size(); ++i) for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i].matches(instr.arguments.at(i), _ssaValues)) if (!m_arguments[i].matches(instr.arguments.at(i), _dialect, _ssaValues))
return false; return false;
} }
else else
@ -167,7 +172,7 @@ bool Pattern::matches(Expression const& _expr, map<YulString, Expression const*>
assertThrow(firstMatch, OptimizerException, "Match set but to null."); assertThrow(firstMatch, OptimizerException, "Match set but to null.");
return return
SyntacticalEqualityChecker::equal(*firstMatch, _expr) && SyntacticalEqualityChecker::equal(*firstMatch, _expr) &&
MovableChecker(_expr).movable(); MovableChecker(_dialect, _expr).movable();
} }
else if (m_kind == PatternKind::Any) else if (m_kind == PatternKind::Any)
(*m_matchGroups)[m_matchGroup] = &_expr; (*m_matchGroups)[m_matchGroup] = &_expr;

View File

@ -33,7 +33,7 @@
namespace yul namespace yul
{ {
struct Dialect;
class Pattern; class Pattern;
/** /**
@ -49,6 +49,7 @@ public:
/// @param _ssaValues values of variables that are assigned exactly once. /// @param _ssaValues values of variables that are assigned exactly once.
static SimplificationRule<Pattern> const* findFirstMatch( static SimplificationRule<Pattern> const* findFirstMatch(
Expression const& _expr, Expression const& _expr,
Dialect const& _dialect,
std::map<YulString, Expression const*> const& _ssaValues std::map<YulString, Expression const*> const& _ssaValues
); );
@ -93,7 +94,11 @@ public:
/// same expression equivalence class. /// same expression equivalence class.
void setMatchGroup(unsigned _group, std::map<unsigned, Expression const*>& _matchGroups); void setMatchGroup(unsigned _group, std::map<unsigned, Expression const*>& _matchGroups);
unsigned matchGroup() const { return m_matchGroup; } unsigned matchGroup() const { return m_matchGroup; }
bool matches(Expression const& _expr, std::map<YulString, Expression const*> const& _ssaValues) const; bool matches(
Expression const& _expr,
Dialect const& _dialect,
std::map<YulString, Expression const*> const& _ssaValues
) const;
std::vector<Pattern> arguments() const { return m_arguments; } std::vector<Pattern> arguments() const { return m_arguments; }

View File

@ -38,6 +38,8 @@ namespace yul
class StructuralSimplifier: public DataFlowAnalyzer class StructuralSimplifier: public DataFlowAnalyzer
{ {
public: public:
explicit StructuralSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}
using DataFlowAnalyzer::operator(); using DataFlowAnalyzer::operator();
void operator()(Block& _block) override; void operator()(Block& _block) override;
private: private:

View File

@ -47,6 +47,7 @@ using namespace dev;
using namespace yul; using namespace yul;
void OptimiserSuite::run( void OptimiserSuite::run(
Dialect const& _dialect,
Block& _ast, Block& _ast,
AsmAnalysisInfo const& _analysisInfo, AsmAnalysisInfo const& _analysisInfo,
set<YulString> const& _externallyUsedIdentifiers set<YulString> const& _externallyUsedIdentifiers
@ -54,69 +55,69 @@ void OptimiserSuite::run(
{ {
set<YulString> reservedIdentifiers = _externallyUsedIdentifiers; set<YulString> reservedIdentifiers = _externallyUsedIdentifiers;
Block ast = boost::get<Block>(Disambiguator(_analysisInfo, reservedIdentifiers)(_ast)); Block ast = boost::get<Block>(Disambiguator(_dialect, _analysisInfo, reservedIdentifiers)(_ast));
(VarDeclInitializer{})(ast); (VarDeclInitializer{})(ast);
(FunctionHoister{})(ast); (FunctionHoister{})(ast);
(FunctionGrouper{})(ast); (FunctionGrouper{})(ast);
(ForLoopInitRewriter{})(ast); (ForLoopInitRewriter{})(ast);
StructuralSimplifier{}(ast); StructuralSimplifier{_dialect}(ast);
NameDispenser dispenser{ast}; NameDispenser dispenser{_dialect, ast};
for (size_t i = 0; i < 4; i++) for (size_t i = 0; i < 4; i++)
{ {
ExpressionSplitter{dispenser}(ast); ExpressionSplitter{dispenser}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{_dialect}(ast);
ExpressionSimplifier::run(ast); ExpressionSimplifier::run(_dialect, ast);
StructuralSimplifier{}(ast); StructuralSimplifier{_dialect}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{_dialect}(ast);
UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
ExpressionInliner(ast).run(); ExpressionInliner(_dialect, ast).run();
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(_dialect, ast);
ExpressionSplitter{dispenser}(ast); ExpressionSplitter{dispenser}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{_dialect}(ast);
FullInliner{ast, dispenser}.run(); FullInliner{ast, dispenser}.run();
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
ExpressionSimplifier::run(ast); ExpressionSimplifier::run(_dialect, ast);
StructuralSimplifier{}(ast); StructuralSimplifier{_dialect}(ast);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{_dialect}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(_dialect, ast);
UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{_dialect}(ast);
} }
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
Rematerialiser::run(ast); Rematerialiser::run(_dialect, ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(_dialect, ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(_dialect, ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(_dialect, ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
Rematerialiser::run(ast); Rematerialiser::run(_dialect, ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(_dialect, ast);
_ast = std::move(ast); _ast = std::move(ast);
} }

View File

@ -29,6 +29,7 @@ namespace yul
{ {
struct AsmAnalysisInfo; struct AsmAnalysisInfo;
struct Dialect;
/** /**
* Optimiser suite that combines all steps and also provides the settings for the heuristics * Optimiser suite that combines all steps and also provides the settings for the heuristics
@ -37,6 +38,7 @@ class OptimiserSuite
{ {
public: public:
static void run( static void run(
Dialect const& _dialect,
Block& _ast, Block& _ast,
AsmAnalysisInfo const& _analysisInfo, AsmAnalysisInfo const& _analysisInfo,

View File

@ -32,7 +32,8 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace yul; using namespace yul;
UnusedPruner::UnusedPruner(Block& _ast, set<YulString> const& _externallyUsedFunctions) UnusedPruner::UnusedPruner(Dialect const& _dialect, Block& _ast, set<YulString> const& _externallyUsedFunctions):
m_dialect(_dialect)
{ {
ReferencesCounter counter; ReferencesCounter counter;
counter(_ast); counter(_ast);
@ -69,7 +70,7 @@ void UnusedPruner::operator()(Block& _block)
{ {
if (!varDecl.value) if (!varDecl.value)
statement = Block{std::move(varDecl.location), {}}; statement = Block{std::move(varDecl.location), {}};
else if (MovableChecker(*varDecl.value).movable()) else if (MovableChecker(m_dialect, *varDecl.value).movable())
{ {
subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); subtractReferences(ReferencesCounter::countReferences(*varDecl.value));
statement = Block{std::move(varDecl.location), {}}; statement = Block{std::move(varDecl.location), {}};
@ -87,7 +88,7 @@ void UnusedPruner::operator()(Block& _block)
else if (statement.type() == typeid(ExpressionStatement)) else if (statement.type() == typeid(ExpressionStatement))
{ {
ExpressionStatement& exprStmt = boost::get<ExpressionStatement>(statement); ExpressionStatement& exprStmt = boost::get<ExpressionStatement>(statement);
if (MovableChecker(exprStmt.expression).movable()) if (MovableChecker(m_dialect, exprStmt.expression).movable())
{ {
// pop(x) should be movable! // pop(x) should be movable!
subtractReferences(ReferencesCounter::countReferences(exprStmt.expression)); subtractReferences(ReferencesCounter::countReferences(exprStmt.expression));
@ -100,11 +101,15 @@ void UnusedPruner::operator()(Block& _block)
ASTModifier::operator()(_block); ASTModifier::operator()(_block);
} }
void UnusedPruner::runUntilStabilised(Block& _ast, set<YulString> const& _externallyUsedFunctions) void UnusedPruner::runUntilStabilised(
Dialect const& _dialect,
Block& _ast,
set<YulString> const& _externallyUsedFunctions
)
{ {
while (true) while (true)
{ {
UnusedPruner pruner(_ast, _externallyUsedFunctions); UnusedPruner pruner(_dialect, _ast, _externallyUsedFunctions);
pruner(_ast); pruner(_ast);
if (!pruner.shouldRunAgain()) if (!pruner.shouldRunAgain())
return; return;

View File

@ -28,6 +28,7 @@
namespace yul namespace yul
{ {
struct Dialect;
/** /**
* Optimisation stage that removes unused variables and functions and also * Optimisation stage that removes unused variables and functions and also
@ -40,7 +41,11 @@ namespace yul
class UnusedPruner: public ASTModifier class UnusedPruner: public ASTModifier
{ {
public: public:
explicit UnusedPruner(Block& _ast, std::set<YulString> const& _externallyUsedFunctions = {}); UnusedPruner(
Dialect const& _dialect,
Block& _ast,
std::set<YulString> const& _externallyUsedFunctions = {}
);
using ASTModifier::operator(); using ASTModifier::operator();
void operator()(Block& _block) override; void operator()(Block& _block) override;
@ -49,12 +54,17 @@ public:
bool shouldRunAgain() const { return m_shouldRunAgain; } bool shouldRunAgain() const { return m_shouldRunAgain; }
// Run the pruner until the code does not change anymore. // Run the pruner until the code does not change anymore.
static void runUntilStabilised(Block& _ast, std::set<YulString> const& _externallyUsedFunctions = {}); static void runUntilStabilised(
Dialect const& _dialect,
Block& _ast,
std::set<YulString> const& _externallyUsedFunctions = {}
);
private: private:
bool used(YulString _name) const; bool used(YulString _name) const;
void subtractReferences(std::map<YulString, size_t> const& _subtrahend); void subtractReferences(std::map<YulString, size_t> const& _subtrahend);
Dialect const& m_dialect;
bool m_shouldRunAgain = false; bool m_shouldRunAgain = false;
std::map<YulString, size_t> m_references; std::map<YulString, size_t> m_references;
}; };

View File

@ -41,6 +41,14 @@ using namespace langutil;
using namespace yul; using namespace yul;
using namespace dev::solidity; using namespace dev::solidity;
namespace
{
shared_ptr<Dialect> defaultDialect(bool _yul)
{
return _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM();
}
}
void yul::test::printErrors(ErrorList const& _errors) void yul::test::printErrors(ErrorList const& _errors)
{ {
SourceReferenceFormatter formatter(cout); SourceReferenceFormatter formatter(cout);
@ -55,7 +63,7 @@ void yul::test::printErrors(ErrorList const& _errors)
pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul) pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul)
{ {
shared_ptr<Dialect> dialect = _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(); shared_ptr<Dialect> dialect = defaultDialect(_yul);
ErrorList errors; ErrorList errors;
ErrorReporter errorReporter(errors); ErrorReporter errorReporter(errors);
auto scanner = make_shared<Scanner>(CharStream(_source, "")); auto scanner = make_shared<Scanner>(CharStream(_source, ""));
@ -87,7 +95,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin
yul::Block yul::test::disambiguate(string const& _source, bool _yul) yul::Block yul::test::disambiguate(string const& _source, bool _yul)
{ {
auto result = parse(_source, _yul); auto result = parse(_source, _yul);
return boost::get<Block>(Disambiguator(*result.second, {})(*result.first)); return boost::get<Block>(Disambiguator(*defaultDialect(_yul), *result.second, {})(*result.first));
} }
string yul::test::format(string const& _source, bool _yul) string yul::test::format(string const& _source, bool _yul)

View File

@ -117,11 +117,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
else if (m_optimizerStep == "commonSubexpressionEliminator") else if (m_optimizerStep == "commonSubexpressionEliminator")
{ {
disambiguate(); disambiguate();
(CommonSubexpressionEliminator{})(*m_ast); (CommonSubexpressionEliminator{*m_dialect})(*m_ast);
} }
else if (m_optimizerStep == "expressionSplitter") else if (m_optimizerStep == "expressionSplitter")
{ {
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser{*m_dialect, *m_ast};
ExpressionSplitter{nameDispenser}(*m_ast); ExpressionSplitter{nameDispenser}(*m_ast);
} }
else if (m_optimizerStep == "expressionJoiner") else if (m_optimizerStep == "expressionJoiner")
@ -132,7 +132,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
else if (m_optimizerStep == "splitJoin") else if (m_optimizerStep == "splitJoin")
{ {
disambiguate(); disambiguate();
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser{*m_dialect, *m_ast};
ExpressionSplitter{nameDispenser}(*m_ast); ExpressionSplitter{nameDispenser}(*m_ast);
ExpressionJoiner::run(*m_ast); ExpressionJoiner::run(*m_ast);
ExpressionJoiner::run(*m_ast); ExpressionJoiner::run(*m_ast);
@ -150,14 +150,14 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
else if (m_optimizerStep == "expressionInliner") else if (m_optimizerStep == "expressionInliner")
{ {
disambiguate(); disambiguate();
ExpressionInliner(*m_ast).run(); ExpressionInliner(*m_dialect, *m_ast).run();
} }
else if (m_optimizerStep == "fullInliner") else if (m_optimizerStep == "fullInliner")
{ {
disambiguate(); disambiguate();
(FunctionHoister{})(*m_ast); (FunctionHoister{})(*m_ast);
(FunctionGrouper{})(*m_ast); (FunctionGrouper{})(*m_ast);
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser{*m_dialect, *m_ast};
ExpressionSplitter{nameDispenser}(*m_ast); ExpressionSplitter{nameDispenser}(*m_ast);
FullInliner(*m_ast, nameDispenser).run(); FullInliner(*m_ast, nameDispenser).run();
ExpressionJoiner::run(*m_ast); ExpressionJoiner::run(*m_ast);
@ -171,54 +171,54 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
else if (m_optimizerStep == "rematerialiser") else if (m_optimizerStep == "rematerialiser")
{ {
disambiguate(); disambiguate();
Rematerialiser::run(*m_ast); Rematerialiser::run(*m_dialect, *m_ast);
} }
else if (m_optimizerStep == "expressionSimplifier") else if (m_optimizerStep == "expressionSimplifier")
{ {
disambiguate(); disambiguate();
ExpressionSimplifier::run(*m_ast); ExpressionSimplifier::run(*m_dialect, *m_ast);
} }
else if (m_optimizerStep == "fullSimplify") else if (m_optimizerStep == "fullSimplify")
{ {
disambiguate(); disambiguate();
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser{*m_dialect, *m_ast};
ExpressionSplitter{nameDispenser}(*m_ast); ExpressionSplitter{nameDispenser}(*m_ast);
CommonSubexpressionEliminator{}(*m_ast); CommonSubexpressionEliminator{*m_dialect}(*m_ast);
ExpressionSimplifier::run(*m_ast); ExpressionSimplifier::run(*m_dialect, *m_ast);
UnusedPruner::runUntilStabilised(*m_ast); UnusedPruner::runUntilStabilised(*m_dialect, *m_ast);
ExpressionJoiner::run(*m_ast); ExpressionJoiner::run(*m_ast);
ExpressionJoiner::run(*m_ast); ExpressionJoiner::run(*m_ast);
} }
else if (m_optimizerStep == "unusedPruner") else if (m_optimizerStep == "unusedPruner")
{ {
disambiguate(); disambiguate();
UnusedPruner::runUntilStabilised(*m_ast); UnusedPruner::runUntilStabilised(*m_dialect, *m_ast);
} }
else if (m_optimizerStep == "ssaTransform") else if (m_optimizerStep == "ssaTransform")
{ {
disambiguate(); disambiguate();
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser{*m_dialect, *m_ast};
SSATransform::run(*m_ast, nameDispenser); SSATransform::run(*m_ast, nameDispenser);
} }
else if (m_optimizerStep == "redundantAssignEliminator") else if (m_optimizerStep == "redundantAssignEliminator")
{ {
disambiguate(); disambiguate();
RedundantAssignEliminator::run(*m_ast); RedundantAssignEliminator::run(*m_dialect, *m_ast);
} }
else if (m_optimizerStep == "ssaPlusCleanup") else if (m_optimizerStep == "ssaPlusCleanup")
{ {
disambiguate(); disambiguate();
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser{*m_dialect, *m_ast};
SSATransform::run(*m_ast, nameDispenser); SSATransform::run(*m_ast, nameDispenser);
RedundantAssignEliminator::run(*m_ast); RedundantAssignEliminator::run(*m_dialect, *m_ast);
} }
else if (m_optimizerStep == "structuralSimplifier") else if (m_optimizerStep == "structuralSimplifier")
{ {
disambiguate(); disambiguate();
StructuralSimplifier{}(*m_ast); StructuralSimplifier{*m_dialect}(*m_ast);
} }
else if (m_optimizerStep == "fullSuite") else if (m_optimizerStep == "fullSuite")
OptimiserSuite::run(*m_ast, *m_analysisInfo); OptimiserSuite::run(*m_dialect, *m_ast, *m_analysisInfo);
else else
{ {
FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl;
@ -260,11 +260,11 @@ void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, st
bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted) bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted)
{ {
shared_ptr<yul::Dialect> dialect = m_yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(); m_dialect = m_yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM();
ErrorList errors; ErrorList errors;
ErrorReporter errorReporter(errors); ErrorReporter errorReporter(errors);
shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, "")); shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, ""));
m_ast = yul::Parser(errorReporter, dialect).parse(scanner, false); m_ast = yul::Parser(errorReporter, m_dialect).parse(scanner, false);
if (!m_ast || !errorReporter.errors().empty()) if (!m_ast || !errorReporter.errors().empty())
{ {
FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
@ -277,7 +277,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
errorReporter, errorReporter,
dev::test::Options::get().evmVersion(), dev::test::Options::get().evmVersion(),
boost::none, boost::none,
dialect m_dialect
); );
if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty())
{ {
@ -290,7 +290,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
void YulOptimizerTest::disambiguate() void YulOptimizerTest::disambiguate()
{ {
*m_ast = boost::get<Block>(Disambiguator(*m_analysisInfo)(*m_ast)); *m_ast = boost::get<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast));
m_analysisInfo.reset(); m_analysisInfo.reset();
} }

View File

@ -30,6 +30,7 @@ namespace yul
{ {
struct AsmAnalysisInfo; struct AsmAnalysisInfo;
struct Block; struct Block;
struct Dialect;
} }
namespace yul namespace yul
@ -64,6 +65,7 @@ private:
std::string m_optimizerStep; std::string m_optimizerStep;
std::string m_expectation; std::string m_expectation;
std::shared_ptr<Dialect> m_dialect;
std::shared_ptr<Block> m_ast; std::shared_ptr<Block> m_ast;
std::shared_ptr<AsmAnalysisInfo> m_analysisInfo; std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
std::string m_obtainedResult; std::string m_obtainedResult;

View File

@ -85,7 +85,7 @@ public:
{ {
ErrorReporter errorReporter(m_errors); ErrorReporter errorReporter(m_errors);
shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(_input, "")); shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(_input, ""));
m_ast = yul::Parser(errorReporter, yul::EVMDialect::strictAssemblyForEVM()).parse(scanner, false); m_ast = yul::Parser(errorReporter, m_dialect).parse(scanner, false);
if (!m_ast || !errorReporter.errors().empty()) if (!m_ast || !errorReporter.errors().empty())
{ {
cout << "Error parsing source." << endl; cout << "Error parsing source." << endl;
@ -98,7 +98,7 @@ public:
errorReporter, errorReporter,
EVMVersion::byzantium(), EVMVersion::byzantium(),
langutil::Error::Type::SyntaxError, langutil::Error::Type::SyntaxError,
EVMDialect::strictAssemblyForEVM() m_dialect
); );
if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty())
{ {
@ -120,9 +120,9 @@ public:
return; return;
if (!disambiguated) if (!disambiguated)
{ {
*m_ast = boost::get<yul::Block>(Disambiguator(*m_analysisInfo)(*m_ast)); *m_ast = boost::get<yul::Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast));
m_analysisInfo.reset(); m_analysisInfo.reset();
m_nameDispenser = make_shared<NameDispenser>(*m_ast); m_nameDispenser = make_shared<NameDispenser>(*m_dialect, *m_ast);
disambiguated = true; disambiguated = true;
} }
cout << "(q)quit/(f)flatten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; cout << "(q)quit/(f)flatten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl;
@ -143,7 +143,7 @@ public:
ForLoopInitRewriter{}(*m_ast); ForLoopInitRewriter{}(*m_ast);
break; break;
case 'c': case 'c':
(CommonSubexpressionEliminator{})(*m_ast); (CommonSubexpressionEliminator{*m_dialect})(*m_ast);
break; break;
case 'd': case 'd':
(VarDeclInitializer{})(*m_ast); (VarDeclInitializer{})(*m_ast);
@ -161,28 +161,28 @@ public:
(FunctionHoister{})(*m_ast); (FunctionHoister{})(*m_ast);
break; break;
case 'e': case 'e':
ExpressionInliner{*m_ast}.run(); ExpressionInliner{*m_dialect, *m_ast}.run();
break; break;
case 'i': case 'i':
FullInliner(*m_ast, *m_nameDispenser).run(); FullInliner(*m_ast, *m_nameDispenser).run();
break; break;
case 's': case 's':
ExpressionSimplifier::run(*m_ast); ExpressionSimplifier::run(*m_dialect, *m_ast);
break; break;
case 't': case 't':
(StructuralSimplifier{})(*m_ast); (StructuralSimplifier{*m_dialect})(*m_ast);
break; break;
case 'u': case 'u':
UnusedPruner::runUntilStabilised(*m_ast); UnusedPruner::runUntilStabilised(*m_dialect, *m_ast);
break; break;
case 'a': case 'a':
SSATransform::run(*m_ast, *m_nameDispenser); SSATransform::run(*m_ast, *m_nameDispenser);
break; break;
case 'r': case 'r':
RedundantAssignEliminator::run(*m_ast); RedundantAssignEliminator::run(*m_dialect, *m_ast);
break; break;
case 'm': case 'm':
Rematerialiser::run(*m_ast); Rematerialiser::run(*m_dialect, *m_ast);
break; break;
default: default:
cout << "Unknown option." << endl; cout << "Unknown option." << endl;
@ -194,6 +194,7 @@ public:
private: private:
ErrorList m_errors; ErrorList m_errors;
shared_ptr<yul::Block> m_ast; shared_ptr<yul::Block> m_ast;
shared_ptr<Dialect> m_dialect{EVMDialect::strictAssemblyForEVMObjects()};
shared_ptr<AsmAnalysisInfo> m_analysisInfo; shared_ptr<AsmAnalysisInfo> m_analysisInfo;
shared_ptr<NameDispenser> m_nameDispenser; shared_ptr<NameDispenser> m_nameDispenser;
}; };