Take yul optimizer setting into account.

This commit is contained in:
chriseth 2019-02-21 18:23:46 +01:00
parent 1ff562d28a
commit 83d1382e78
3 changed files with 61 additions and 17 deletions

View File

@ -32,6 +32,7 @@
#include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmAnalysisInfo.h>
#include <libyul/backends/evm/AsmCodeGen.h> #include <libyul/backends/evm/AsmCodeGen.h>
#include <libyul/backends/evm/EVMDialect.h> #include <libyul/backends/evm/EVMDialect.h>
#include <libyul/optimiser/Suite.h>
#include <libyul/YulString.h> #include <libyul/YulString.h>
#include <liblangutil/ErrorReporter.h> #include <liblangutil/ErrorReporter.h>
@ -328,12 +329,19 @@ void CompilerContext::resetVisitedNodes(ASTNode const* _node)
void CompilerContext::appendInlineAssembly( void CompilerContext::appendInlineAssembly(
string const& _assembly, string const& _assembly,
vector<string> const& _localVariables, vector<string> const& _localVariables,
set<string> const&, set<string> const& _externallyUsedFunctions,
bool _system bool _system,
bool _optimise
) )
{ {
int startStackHeight = stackHeight(); int startStackHeight = stackHeight();
set<yul::YulString> externallyUsedIdentifiers;
for (auto const& fun: _externallyUsedFunctions)
externallyUsedIdentifiers.insert(yul::YulString(fun));
for (auto const& var: _localVariables)
externallyUsedIdentifiers.insert(yul::YulString(var));
yul::ExternalIdentifierAccess identifierAccess; yul::ExternalIdentifierAccess identifierAccess;
identifierAccess.resolve = [&]( identifierAccess.resolve = [&](
yul::Identifier const& _identifier, yul::Identifier const& _identifier,
@ -380,20 +388,12 @@ void CompilerContext::appendInlineAssembly(
#ifdef SOL_OUTPUT_ASM #ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter()(*parserResult) << endl; cout << yul::AsmPrinter()(*parserResult) << endl;
#endif #endif
yul::AsmAnalysisInfo analysisInfo;
bool analyzerResult = false; auto reportError = [&](string const& _context)
if (parserResult)
analyzerResult = yul::AsmAnalyzer(
analysisInfo,
errorReporter,
boost::none,
yul::EVMDialect::strictAssemblyForEVM(m_evmVersion),
identifierAccess.resolve
).analyze(*parserResult);
if (!parserResult || !errorReporter.errors().empty() || !analyzerResult)
{ {
string message = string message =
"Error parsing/analyzing inline assembly block:\n" "Error parsing/analyzing inline assembly block:\n" +
_context + "\n"
"------------------ Input: -----------------\n" + "------------------ Input: -----------------\n" +
_assembly + "\n" _assembly + "\n"
"------------------ Errors: ----------------\n"; "------------------ Errors: ----------------\n";
@ -405,10 +405,47 @@ void CompilerContext::appendInlineAssembly(
message += "-------------------------------------------\n"; message += "-------------------------------------------\n";
solAssert(false, message); solAssert(false, message);
};
yul::AsmAnalysisInfo analysisInfo;
bool analyzerResult = false;
if (parserResult)
analyzerResult = yul::AsmAnalyzer(
analysisInfo,
errorReporter,
boost::none,
yul::EVMDialect::strictAssemblyForEVM(m_evmVersion),
identifierAccess.resolve
).analyze(*parserResult);
if (!parserResult || !errorReporter.errors().empty() || !analyzerResult)
reportError("Invalid assembly generated by code generator.");
// Several optimizer steps cannot handle externally supplied stack variables,
// so we essentially only optimize the ABI functions.
if (_optimise && _localVariables.empty())
{
yul::OptimiserSuite::run(
yul::EVMDialect::strictAssemblyForEVM(m_evmVersion),
*parserResult,
analysisInfo,
externallyUsedIdentifiers
);
analysisInfo = yul::AsmAnalysisInfo{};
if (!yul::AsmAnalyzer(
analysisInfo,
errorReporter,
boost::none,
yul::EVMDialect::strictAssemblyForEVM(m_evmVersion),
identifierAccess.resolve
).analyze(*parserResult))
reportError("Optimizer introduced error into inline assembly.");
} }
if (!errorReporter.errors().empty())
reportError("Failed to analyze inline assembly block.");
solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block.");
yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, m_evmVersion, identifierAccess, _system); yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, m_evmVersion, identifierAccess, _system, _optimise);
// Reset the source location to the one of the node (instead of the CODEGEN source location) // Reset the source location to the one of the node (instead of the CODEGEN source location)
updateSourceLocation(); updateSourceLocation();

View File

@ -216,7 +216,8 @@ public:
std::string const& _assembly, std::string const& _assembly,
std::vector<std::string> const& _localVariables = std::vector<std::string>(), std::vector<std::string> const& _localVariables = std::vector<std::string>(),
std::set<std::string> const& _externallyUsedFunctions = std::set<std::string>(), std::set<std::string> const& _externallyUsedFunctions = std::set<std::string>(),
bool _system = false bool _system = false,
bool _optimise = false
); );
/// Appends arbitrary data to the end of the bytecode. /// Appends arbitrary data to the end of the bytecode.

View File

@ -978,7 +978,13 @@ void ContractCompiler::appendMissingFunctions()
m_context.appendMissingLowLevelFunctions(); m_context.appendMissingLowLevelFunctions();
auto abiFunctions = m_context.abiFunctions().requestedFunctions(); auto abiFunctions = m_context.abiFunctions().requestedFunctions();
if (!abiFunctions.first.empty()) if (!abiFunctions.first.empty())
m_context.appendInlineAssembly("{" + move(abiFunctions.first) + "}", {}, abiFunctions.second, true); m_context.appendInlineAssembly(
"{" + move(abiFunctions.first) + "}",
{},
abiFunctions.second,
true,
m_optimiserSettings.runYulOptimiser
);
} }
void ContractCompiler::appendModifierOrFunctionCode() void ContractCompiler::appendModifierOrFunctionCode()