From cc5045a56e31670d9c58cb0569457f7d536b09f2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 29 May 2019 23:14:06 +0200 Subject: [PATCH] [Yul] Run optimizer on all dialects. --- libsolidity/codegen/CompilerContext.cpp | 3 ++- libyul/AssemblyStack.cpp | 25 ++++++++++----------- libyul/Dialect.h | 3 +++ libyul/backends/wasm/EWasmCodeTransform.cpp | 4 ++-- libyul/backends/wasm/WasmDialect.h | 2 ++ libyul/optimiser/Suite.cpp | 8 +++++-- libyul/optimiser/Suite.h | 2 +- test/libyul/YulOptimizerTest.cpp | 2 +- 8 files changed, 29 insertions(+), 20 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 851038421..8c65b8a19 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -422,9 +422,10 @@ void CompilerContext::appendInlineAssembly( if (_optimiserSettings.runYulOptimiser && _localVariables.empty()) { bool const isCreation = m_runtimeContext != nullptr; + yul::GasMeter meter(dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); yul::OptimiserSuite::run( dialect, - yul::GasMeter(dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment), + &meter, *parserResult, analysisInfo, _optimiserSettings.optimizeStackAllocation, diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 1723e1fc2..549a599fe 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -94,8 +94,6 @@ void AssemblyStack::optimize() if (!m_optimiserSettings.runYulOptimiser) return; - if (m_language != Language::StrictAssembly) - solUnimplemented("Optimizer for both loose assembly and Yul is not yet implemented"); solAssert(m_analysisSuccessful, "Analysis was not successful."); m_analysisSuccessful = false; @@ -147,17 +145,18 @@ void AssemblyStack::optimize(Object& _object, bool _isCreation) for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) optimize(*subObject, false); - if (EVMDialect const* dialect = dynamic_cast(&languageToDialect(m_language, m_evmVersion))) - { - GasMeter meter(*dialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); - OptimiserSuite::run( - *dialect, - meter, - *_object.code, - *_object.analysisInfo, - m_optimiserSettings.optimizeStackAllocation - ); - } + + Dialect const& dialect = languageToDialect(m_language, m_evmVersion); + unique_ptr meter; + if (EVMDialect const* evmDialect = dynamic_cast(&dialect)) + meter = make_unique(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); + OptimiserSuite::run( + dialect, + meter.get(), + *_object.code, + *_object.analysisInfo, + m_optimiserSettings.optimizeStackAllocation + ); } MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 6e2fb6585..9dd41ca34 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -25,6 +25,7 @@ #include #include +#include namespace yul { @@ -69,6 +70,8 @@ struct Dialect: boost::noncopyable virtual BuiltinFunction const* discardFunction() const { return nullptr; } virtual BuiltinFunction const* equalityFunction() const { return nullptr; } + virtual std::set fixedFunctionNames() const { return {}; } + Dialect(AsmFlavour _flavour): flavour(_flavour) {} virtual ~Dialect() = default; diff --git a/libyul/backends/wasm/EWasmCodeTransform.cpp b/libyul/backends/wasm/EWasmCodeTransform.cpp index c25e5a1c9..90ca28d1c 100644 --- a/libyul/backends/wasm/EWasmCodeTransform.cpp +++ b/libyul/backends/wasm/EWasmCodeTransform.cpp @@ -115,9 +115,9 @@ wasm::Expression EWasmCodeTransform::operator()(Label const&) return {}; } -wasm::Expression EWasmCodeTransform::operator()(FunctionalInstruction const&) +wasm::Expression EWasmCodeTransform::operator()(FunctionalInstruction const& _f) { - yulAssert(false, ""); + yulAssert(false, "EVM instruction in ewasm code: " + eth::instructionInfo(_f.instruction).name); return {}; } diff --git a/libyul/backends/wasm/WasmDialect.h b/libyul/backends/wasm/WasmDialect.h index 4ade0be54..71f7c52ad 100644 --- a/libyul/backends/wasm/WasmDialect.h +++ b/libyul/backends/wasm/WasmDialect.h @@ -48,6 +48,8 @@ struct WasmDialect: public Dialect BuiltinFunction const* discardFunction() const override { return builtin("drop"_yulstring); } BuiltinFunction const* equalityFunction() const override { return builtin("i64.eq"_yulstring); } + std::set fixedFunctionNames() const override { return {"main"_yulstring}; } + static WasmDialect const& instance(); private: diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 05b4b1b40..b8bb1ccf8 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -60,7 +60,7 @@ using namespace yul; void OptimiserSuite::run( Dialect const& _dialect, - GasMeter const& _meter, + GasMeter const* _meter, Block& _ast, AsmAnalysisInfo const& _analysisInfo, bool _optimizeStackAllocation, @@ -68,6 +68,7 @@ void OptimiserSuite::run( ) { set reservedIdentifiers = _externallyUsedIdentifiers; + reservedIdentifiers += _dialect.fixedFunctionNames(); Block ast = boost::get(Disambiguator(_dialect, _analysisInfo, reservedIdentifiers)(_ast)); @@ -210,7 +211,10 @@ void OptimiserSuite::run( FunctionGrouper{}(ast); if (EVMDialect const* dialect = dynamic_cast(&_dialect)) - ConstantOptimiser{*dialect, _meter}(ast); + { + yulAssert(_meter, ""); + ConstantOptimiser{*dialect, *_meter}(ast); + } VarNameCleaner{ast, _dialect, reservedIdentifiers}(ast); yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, ast); diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 03806eee6..3f35b572a 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -41,7 +41,7 @@ class OptimiserSuite public: static void run( Dialect const& _dialect, - GasMeter const& _meter, + GasMeter const* _meter, Block& _ast, AsmAnalysisInfo const& _analysisInfo, bool _optimizeStackAllocation, diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 496f0837c..ece57267b 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -292,7 +292,7 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line else if (m_optimizerStep == "fullSuite") { GasMeter meter(dynamic_cast(*m_dialect), false, 200); - OptimiserSuite::run(*m_dialect, meter, *m_ast, *m_analysisInfo, true); + OptimiserSuite::run(*m_dialect, &meter, *m_ast, *m_analysisInfo, true); } else {