Merge branch 'develop' into Akkii4-patch-1

This commit is contained in:
Akshit Choudhary 2023-08-28 23:22:10 +05:30 committed by GitHub
commit bee0b9c9a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 671 additions and 737 deletions

View File

@ -4,9 +4,9 @@ FetchContent_Declare(
fmtlib fmtlib
PREFIX "${PROJECT_BINARY_DIR}/deps" PREFIX "${PROJECT_BINARY_DIR}/deps"
DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads" DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads"
DOWNLOAD_NAME fmt-8.0.1.tar.gz DOWNLOAD_NAME fmt-9.1.0.tar.gz
URL https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz URL https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
URL_HASH SHA256=b06ca3130158c625848f3fb7418f235155a4d389b2abc3a6245fb01cb0eb1e01 URL_HASH SHA256=5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
) )
if (CMAKE_VERSION VERSION_LESS "3.14.0") if (CMAKE_VERSION VERSION_LESS "3.14.0")

View File

@ -118,7 +118,7 @@ void SemanticTokensBuilder::encode(
auto const [line, startChar] = m_charStream->translatePositionToLineColumn(_sourceLocation.start); auto const [line, startChar] = m_charStream->translatePositionToLineColumn(_sourceLocation.start);
auto const length = _sourceLocation.end - _sourceLocation.start; auto const length = _sourceLocation.end - _sourceLocation.start;
lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, _tokenType)); lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, static_cast<int>(_tokenType)));
m_encodedTokens.append(line - m_lastLine); m_encodedTokens.append(line - m_lastLine);
if (line == m_lastLine) if (line == m_lastLine)

View File

@ -28,7 +28,6 @@
#include <libsolutil/StackTooDeepString.h> #include <libsolutil/StackTooDeepString.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;

View File

@ -30,7 +30,6 @@
#include <variant> #include <variant>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -48,9 +47,9 @@ struct MiniEVMInterpreter
return std::visit(*this, _expr); return std::visit(*this, _expr);
} }
u256 eval(evmasm::Instruction _instr, vector<Expression> const& _arguments) u256 eval(evmasm::Instruction _instr, std::vector<Expression> const& _arguments)
{ {
vector<u256> args; std::vector<u256> args;
for (auto const& arg: _arguments) for (auto const& arg: _arguments)
args.emplace_back(eval(arg)); args.emplace_back(eval(arg));
switch (_instr) switch (_instr)
@ -92,7 +91,7 @@ struct MiniEVMInterpreter
void ConstantOptimiser::visit(Expression& _e) void ConstantOptimiser::visit(Expression& _e)
{ {
if (holds_alternative<Literal>(_e)) if (std::holds_alternative<Literal>(_e))
{ {
Literal const& literal = std::get<Literal>(_e); Literal const& literal = std::get<Literal>(_e);
if (literal.kind != LiteralKind::Number) if (literal.kind != LiteralKind::Number)
@ -115,7 +114,7 @@ Expression const* RepresentationFinder::tryFindRepresentation(u256 const& _value
return nullptr; return nullptr;
Representation const& repr = findRepresentation(_value); Representation const& repr = findRepresentation(_value);
if (holds_alternative<Literal>(*repr.expression)) if (std::holds_alternative<Literal>(*repr.expression))
return nullptr; return nullptr;
else else
return repr.expression.get(); return repr.expression.get();
@ -180,7 +179,7 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu
Representation RepresentationFinder::represent(u256 const& _value) const Representation RepresentationFinder::represent(u256 const& _value) const
{ {
Representation repr; Representation repr;
repr.expression = make_unique<Expression>(Literal{m_debugData, LiteralKind::Number, YulString{formatNumber(_value)}, {}}); repr.expression = std::make_unique<Expression>(Literal{m_debugData, LiteralKind::Number, YulString{formatNumber(_value)}, {}});
repr.cost = m_meter.costs(*repr.expression); repr.cost = m_meter.costs(*repr.expression);
return repr; return repr;
} }
@ -191,7 +190,7 @@ Representation RepresentationFinder::represent(
) const ) const
{ {
Representation repr; Representation repr;
repr.expression = make_unique<Expression>(FunctionCall{ repr.expression = std::make_unique<Expression>(FunctionCall{
m_debugData, m_debugData,
Identifier{m_debugData, _instruction}, Identifier{m_debugData, _instruction},
{ASTCopier{}.translate(*_argument.expression)} {ASTCopier{}.translate(*_argument.expression)}
@ -207,7 +206,7 @@ Representation RepresentationFinder::represent(
) const ) const
{ {
Representation repr; Representation repr;
repr.expression = make_unique<Expression>(FunctionCall{ repr.expression = std::make_unique<Expression>(FunctionCall{
m_debugData, m_debugData,
Identifier{m_debugData, _instruction}, Identifier{m_debugData, _instruction},
{ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)} {ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)}

View File

@ -45,7 +45,6 @@
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace std;
namespace namespace
{ {
@ -82,15 +81,15 @@ void cleanUnreachable(CFG& _cfg)
/// Sets the ``recursive`` member to ``true`` for all recursive function calls. /// Sets the ``recursive`` member to ``true`` for all recursive function calls.
void markRecursiveCalls(CFG& _cfg) void markRecursiveCalls(CFG& _cfg)
{ {
map<CFG::BasicBlock*, vector<CFG::FunctionCall*>> callsPerBlock; std::map<CFG::BasicBlock*, std::vector<CFG::FunctionCall*>> callsPerBlock;
auto const& findCalls = [&](CFG::BasicBlock* _block) auto const& findCalls = [&](CFG::BasicBlock* _block)
{ {
if (auto* calls = util::valueOrNullptr(callsPerBlock, _block)) if (auto* calls = util::valueOrNullptr(callsPerBlock, _block))
return *calls; return *calls;
vector<CFG::FunctionCall*>& calls = callsPerBlock[_block]; std::vector<CFG::FunctionCall*>& calls = callsPerBlock[_block];
util::BreadthFirstSearch<CFG::BasicBlock*>{{_block}}.run([&](CFG::BasicBlock* _block, auto _addChild) { util::BreadthFirstSearch<CFG::BasicBlock*>{{_block}}.run([&](CFG::BasicBlock* _block, auto _addChild) {
for (auto& operation: _block->operations) for (auto& operation: _block->operations)
if (auto* functionCall = get_if<CFG::FunctionCall>(&operation.operation)) if (auto* functionCall = std::get_if<CFG::FunctionCall>(&operation.operation))
calls.emplace_back(functionCall); calls.emplace_back(functionCall);
std::visit(util::GenericVisitor{ std::visit(util::GenericVisitor{
[&](CFG::BasicBlock::MainExit const&) {}, [&](CFG::BasicBlock::MainExit const&) {},
@ -131,7 +130,7 @@ void markRecursiveCalls(CFG& _cfg)
/// Entering such a block means that control flow will never return to a previously visited block. /// Entering such a block means that control flow will never return to a previously visited block.
void markStartsOfSubGraphs(CFG& _cfg) void markStartsOfSubGraphs(CFG& _cfg)
{ {
vector<CFG::BasicBlock*> entries; std::vector<CFG::BasicBlock*> entries;
entries.emplace_back(_cfg.entry); entries.emplace_back(_cfg.entry);
for (auto&& functionInfo: _cfg.functionInfo | ranges::views::values) for (auto&& functionInfo: _cfg.functionInfo | ranges::views::values)
entries.emplace_back(functionInfo.entry); entries.emplace_back(functionInfo.entry);
@ -141,17 +140,17 @@ void markStartsOfSubGraphs(CFG& _cfg)
* Detect bridges following Algorithm 1 in https://arxiv.org/pdf/2108.07346.pdf * Detect bridges following Algorithm 1 in https://arxiv.org/pdf/2108.07346.pdf
* and mark the bridge targets as starts of sub-graphs. * and mark the bridge targets as starts of sub-graphs.
*/ */
set<CFG::BasicBlock*> visited; std::set<CFG::BasicBlock*> visited;
map<CFG::BasicBlock*, size_t> disc; std::map<CFG::BasicBlock*, size_t> disc;
map<CFG::BasicBlock*, size_t> low; std::map<CFG::BasicBlock*, size_t> low;
map<CFG::BasicBlock*, CFG::BasicBlock*> parent; std::map<CFG::BasicBlock*, CFG::BasicBlock*> parent;
size_t time = 0; size_t time = 0;
auto dfs = [&](CFG::BasicBlock* _u, auto _recurse) -> void { auto dfs = [&](CFG::BasicBlock* _u, auto _recurse) -> void {
visited.insert(_u); visited.insert(_u);
disc[_u] = low[_u] = time; disc[_u] = low[_u] = time;
time++; time++;
vector<CFG::BasicBlock*> children = _u->entries; std::vector<CFG::BasicBlock*> children = _u->entries;
visit(util::GenericVisitor{ visit(util::GenericVisitor{
[&](CFG::BasicBlock::Jump const& _jump) { [&](CFG::BasicBlock::Jump const& _jump) {
children.emplace_back(_jump.target); children.emplace_back(_jump.target);
@ -171,7 +170,7 @@ void markStartsOfSubGraphs(CFG& _cfg)
{ {
parent[v] = _u; parent[v] = _u;
_recurse(v, _recurse); _recurse(v, _recurse);
low[_u] = min(low[_u], low[v]); low[_u] = std::min(low[_u], low[v]);
if (low[v] > disc[_u]) if (low[v] > disc[_u])
{ {
// _u <-> v is a cut edge in the undirected graph // _u <-> v is a cut edge in the undirected graph
@ -186,7 +185,7 @@ void markStartsOfSubGraphs(CFG& _cfg)
} }
} }
else if (v != parent[_u]) else if (v != parent[_u])
low[_u] = min(low[_u], disc[v]); low[_u] = std::min(low[_u], disc[v]);
}; };
dfs(entry, dfs); dfs(entry, dfs);
} }
@ -234,7 +233,7 @@ std::unique_ptr<CFG> ControlFlowGraphBuilder::build(
ControlFlowGraphBuilder::ControlFlowGraphBuilder( ControlFlowGraphBuilder::ControlFlowGraphBuilder(
CFG& _graph, CFG& _graph,
AsmAnalysisInfo const& _analysisInfo, AsmAnalysisInfo const& _analysisInfo,
map<FunctionDefinition const*, ControlFlowSideEffects> const& _functionSideEffects, std::map<FunctionDefinition const*, ControlFlowSideEffects> const& _functionSideEffects,
Dialect const& _dialect Dialect const& _dialect
): ):
m_graph(_graph), m_graph(_graph),
@ -271,7 +270,7 @@ void ControlFlowGraphBuilder::operator()(VariableDeclaration const& _varDecl)
yulAssert(m_currentBlock, ""); yulAssert(m_currentBlock, "");
auto declaredVariables = _varDecl.variables | ranges::views::transform([&](TypedName const& _var) { auto declaredVariables = _varDecl.variables | ranges::views::transform([&](TypedName const& _var) {
return VariableSlot{lookupVariable(_var.name), _var.debugData}; return VariableSlot{lookupVariable(_var.name), _var.debugData};
}) | ranges::to<vector<VariableSlot>>; }) | ranges::to<std::vector<VariableSlot>>;
Stack input; Stack input;
if (_varDecl.value) if (_varDecl.value)
input = visitAssignmentRightHandSide(*_varDecl.value, declaredVariables.size()); input = visitAssignmentRightHandSide(*_varDecl.value, declaredVariables.size());
@ -287,7 +286,7 @@ void ControlFlowGraphBuilder::operator()(Assignment const& _assignment)
{ {
auto assignedVariables = _assignment.variableNames | ranges::views::transform([&](Identifier const& _var) { auto assignedVariables = _assignment.variableNames | ranges::views::transform([&](Identifier const& _var) {
return VariableSlot{lookupVariable(_var.name), _var.debugData}; return VariableSlot{lookupVariable(_var.name), _var.debugData};
}) | ranges::to<vector<VariableSlot>>; }) | ranges::to<std::vector<VariableSlot>>;
Stack input = visitAssignmentRightHandSide(*_assignment.value, assignedVariables.size()); Stack input = visitAssignmentRightHandSide(*_assignment.value, assignedVariables.size());
yulAssert(m_currentBlock); yulAssert(m_currentBlock);
@ -314,7 +313,7 @@ void ControlFlowGraphBuilder::operator()(Block const& _block)
{ {
ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get());
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
if (auto const* function = get_if<FunctionDefinition>(&statement)) if (auto const* function = std::get_if<FunctionDefinition>(&statement))
registerFunction(*function); registerFunction(*function);
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
std::visit(*this, statement); std::visit(*this, statement);
@ -334,10 +333,10 @@ void ControlFlowGraphBuilder::operator()(If const& _if)
void ControlFlowGraphBuilder::operator()(Switch const& _switch) void ControlFlowGraphBuilder::operator()(Switch const& _switch)
{ {
yulAssert(m_currentBlock, ""); yulAssert(m_currentBlock, "");
shared_ptr<DebugData const> preSwitchDebugData = debugDataOf(_switch); std::shared_ptr<DebugData const> preSwitchDebugData = debugDataOf(_switch);
auto ghostVariableId = m_graph.ghostVariables.size(); auto ghostVariableId = m_graph.ghostVariables.size();
YulString ghostVariableName("GHOST[" + to_string(ghostVariableId) + "]"); YulString ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]");
auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{""_yulstring, ghostVariableName}); auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{""_yulstring, ghostVariableName});
// Artificially generate: // Artificially generate:
@ -394,12 +393,12 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch)
void ControlFlowGraphBuilder::operator()(ForLoop const& _loop) void ControlFlowGraphBuilder::operator()(ForLoop const& _loop)
{ {
shared_ptr<DebugData const> preLoopDebugData = debugDataOf(_loop); std::shared_ptr<DebugData const> preLoopDebugData = debugDataOf(_loop);
ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get()); ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get());
(*this)(_loop.pre); (*this)(_loop.pre);
std::optional<bool> constantCondition; std::optional<bool> constantCondition;
if (auto const* literalCondition = get_if<yul::Literal>(_loop.condition.get())) if (auto const* literalCondition = std::get_if<yul::Literal>(_loop.condition.get()))
constantCondition = valueOfLiteral(*literalCondition) != 0; constantCondition = valueOfLiteral(*literalCondition) != 0;
CFG::BasicBlock& loopCondition = m_graph.makeBlock(debugDataOf(*_loop.condition)); CFG::BasicBlock& loopCondition = m_graph.makeBlock(debugDataOf(*_loop.condition));
@ -497,13 +496,13 @@ void ControlFlowGraphBuilder::registerFunction(FunctionDefinition const& _functi
std::get<Scope::Variable>(virtualFunctionScope->identifiers.at(_param.name)), std::get<Scope::Variable>(virtualFunctionScope->identifiers.at(_param.name)),
_param.debugData _param.debugData
}; };
}) | ranges::to<vector>, }) | ranges::to<std::vector>,
_functionDefinition.returnVariables | ranges::views::transform([&](auto const& _retVar) { _functionDefinition.returnVariables | ranges::views::transform([&](auto const& _retVar) {
return VariableSlot{ return VariableSlot{
std::get<Scope::Variable>(virtualFunctionScope->identifiers.at(_retVar.name)), std::get<Scope::Variable>(virtualFunctionScope->identifiers.at(_retVar.name)),
_retVar.debugData _retVar.debugData
}; };
}) | ranges::to<vector>, }) | ranges::to<std::vector>,
{}, {},
m_functionSideEffects.at(&_functionDefinition).canContinue m_functionSideEffects.at(&_functionDefinition).canContinue
})).second; })).second;
@ -609,7 +608,7 @@ Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulString _name)
} }
void ControlFlowGraphBuilder::makeConditionalJump( void ControlFlowGraphBuilder::makeConditionalJump(
shared_ptr<DebugData const> _debugData, std::shared_ptr<DebugData const> _debugData,
StackSlot _condition, StackSlot _condition,
CFG::BasicBlock& _nonZero, CFG::BasicBlock& _nonZero,
CFG::BasicBlock& _zero CFG::BasicBlock& _zero
@ -628,7 +627,7 @@ void ControlFlowGraphBuilder::makeConditionalJump(
} }
void ControlFlowGraphBuilder::jump( void ControlFlowGraphBuilder::jump(
shared_ptr<DebugData const> _debugData, std::shared_ptr<DebugData const> _debugData,
CFG::BasicBlock& _target, CFG::BasicBlock& _target,
bool backwards bool backwards
) )

View File

@ -42,7 +42,6 @@
#include <utility> #include <utility>
#include <variant> #include <variant>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -56,9 +55,9 @@ CodeTransform::CodeTransform(
BuiltinContext& _builtinContext, BuiltinContext& _builtinContext,
ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen,
UseNamedLabels _useNamedLabelsForFunctions, UseNamedLabels _useNamedLabelsForFunctions,
shared_ptr<Context> _context, std::shared_ptr<Context> _context,
vector<TypedName> _delayedReturnVariables, std::vector<TypedName> _delayedReturnVariables,
optional<AbstractAssembly::LabelID> _functionExitLabel std::optional<AbstractAssembly::LabelID> _functionExitLabel
): ):
m_assembly(_assembly), m_assembly(_assembly),
m_info(_analysisInfo), m_info(_analysisInfo),
@ -74,7 +73,7 @@ CodeTransform::CodeTransform(
if (!m_context) if (!m_context)
{ {
// initialize // initialize
m_context = make_shared<Context>(); m_context = std::make_shared<Context>();
if (m_allowStackOpt) if (m_allowStackOpt)
m_context->variableReferences = VariableReferenceCounter::run(m_info, _block); m_context->variableReferences = VariableReferenceCounter::run(m_info, _block);
} }
@ -103,7 +102,7 @@ void CodeTransform::freeUnusedVariables(bool _popUnusedSlotsAtStackTop)
return; return;
for (auto const& identifier: m_scope->identifiers) for (auto const& identifier: m_scope->identifiers)
if (Scope::Variable const* var = get_if<Scope::Variable>(&identifier.second)) if (Scope::Variable const* var = std::get_if<Scope::Variable>(&identifier.second))
if (m_variablesScheduledForDeletion.count(var)) if (m_variablesScheduledForDeletion.count(var))
deleteVariable(*var); deleteVariable(*var);
// Directly in a function body block, we can also delete the function arguments, // Directly in a function body block, we can also delete the function arguments,
@ -112,7 +111,7 @@ void CodeTransform::freeUnusedVariables(bool _popUnusedSlotsAtStackTop)
// effect, so we only do it before that. // effect, so we only do it before that.
if (!returnVariablesAndFunctionExitAreSetup() && !m_scope->functionScope && m_scope->superScope && m_scope->superScope->functionScope) if (!returnVariablesAndFunctionExitAreSetup() && !m_scope->functionScope && m_scope->superScope && m_scope->superScope->functionScope)
for (auto const& identifier: m_scope->superScope->identifiers) for (auto const& identifier: m_scope->superScope->identifiers)
if (Scope::Variable const* var = get_if<Scope::Variable>(&identifier.second)) if (Scope::Variable const* var = std::get_if<Scope::Variable>(&identifier.second))
if (m_variablesScheduledForDeletion.count(var)) if (m_variablesScheduledForDeletion.count(var))
deleteVariable(*var); deleteVariable(*var);
@ -317,7 +316,7 @@ void CodeTransform::operator()(Switch const& _switch)
{ {
visitExpression(*_switch.expression); visitExpression(*_switch.expression);
int expressionHeight = m_assembly.stackHeight(); int expressionHeight = m_assembly.stackHeight();
map<Case const*, AbstractAssembly::LabelID> caseBodies; std::map<Case const*, AbstractAssembly::LabelID> caseBodies;
AbstractAssembly::LabelID end = m_assembly.newLabelId(); AbstractAssembly::LabelID end = m_assembly.newLabelId();
for (Case const& c: _switch.cases) for (Case const& c: _switch.cases)
{ {
@ -447,7 +446,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
// This vector holds the desired target positions of all stack slots and is // This vector holds the desired target positions of all stack slots and is
// modified parallel to the actual stack. // modified parallel to the actual stack.
vector<int> stackLayout(static_cast<size_t>(m_assembly.stackHeight()), -1); std::vector<int> stackLayout(static_cast<size_t>(m_assembly.stackHeight()), -1);
stackLayout[0] = static_cast<int>(_function.returnVariables.size()); // Move return label to the top stackLayout[0] = static_cast<int>(_function.returnVariables.size()); // Move return label to the top
for (auto&& [n, returnVariable]: ranges::views::enumerate(_function.returnVariables)) for (auto&& [n, returnVariable]: ranges::views::enumerate(_function.returnVariables))
stackLayout.at(m_context->variableStackHeights.at( stackLayout.at(m_context->variableStackHeights.at(
@ -463,7 +462,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
"The function " + "The function " +
_function.name.str() + _function.name.str() +
" has " + " has " +
to_string(stackLayout.size() - 17) + std::to_string(stackLayout.size() - 17) +
" parameters or return variables too many to fit the stack size." " parameters or return variables too many to fit the stack size."
); );
stackError(std::move(error), m_assembly.stackHeight() - static_cast<int>(_function.parameters.size())); stackError(std::move(error), m_assembly.stackHeight() - static_cast<int>(_function.parameters.size()));
@ -479,7 +478,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
else else
{ {
m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(stackLayout.size()) - static_cast<unsigned>(stackLayout.back()) - 1u)); m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(stackLayout.size()) - static_cast<unsigned>(stackLayout.back()) - 1u));
swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back()); std::swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
} }
for (size_t i = 0; i < stackLayout.size(); ++i) for (size_t i = 0; i < stackLayout.size(); ++i)
yulAssert(i == static_cast<size_t>(stackLayout[i]), "Error reshuffling stack."); yulAssert(i == static_cast<size_t>(stackLayout[i]), "Error reshuffling stack.");
@ -571,7 +570,7 @@ void CodeTransform::operator()(Block const& _block)
m_scope = m_info.scopes.at(&_block).get(); m_scope = m_info.scopes.at(&_block).get();
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
if (auto function = get_if<FunctionDefinition>(&statement)) if (auto function = std::get_if<FunctionDefinition>(&statement))
createFunctionEntryID(*function); createFunctionEntryID(*function);
int blockStartStackHeight = m_assembly.stackHeight(); int blockStartStackHeight = m_assembly.stackHeight();
@ -579,7 +578,7 @@ void CodeTransform::operator()(Block const& _block)
bool isOutermostFunctionBodyBlock = m_scope && m_scope->superScope && m_scope->superScope->functionScope; bool isOutermostFunctionBodyBlock = m_scope && m_scope->superScope && m_scope->superScope->functionScope;
bool performValidation = !m_allowStackOpt || !isOutermostFunctionBodyBlock; bool performValidation = !m_allowStackOpt || !isOutermostFunctionBodyBlock;
finalizeBlock(_block, performValidation ? make_optional(blockStartStackHeight) : nullopt); finalizeBlock(_block, performValidation ? std::make_optional(blockStartStackHeight) : std::nullopt);
m_scope = originalScope; m_scope = originalScope;
} }
@ -588,7 +587,7 @@ void CodeTransform::createFunctionEntryID(FunctionDefinition const& _function)
Scope::Function& scopeFunction = std::get<Scope::Function>(m_scope->identifiers.at(_function.name)); Scope::Function& scopeFunction = std::get<Scope::Function>(m_scope->identifiers.at(_function.name));
yulAssert(!m_context->functionEntryIDs.count(&scopeFunction), ""); yulAssert(!m_context->functionEntryIDs.count(&scopeFunction), "");
optional<size_t> astID; std::optional<size_t> astID;
if (_function.debugData) if (_function.debugData)
astID = _function.debugData->astID; astID = _function.debugData->astID;
@ -659,16 +658,16 @@ void CodeTransform::setupReturnVariablesAndFunctionExit()
namespace namespace
{ {
bool statementNeedsReturnVariableSetup(Statement const& _statement, vector<TypedName> const& _returnVariables) bool statementNeedsReturnVariableSetup(Statement const& _statement, std::vector<TypedName> const& _returnVariables)
{ {
if (holds_alternative<FunctionDefinition>(_statement)) if (std::holds_alternative<FunctionDefinition>(_statement))
return true; return true;
if ( if (
holds_alternative<ExpressionStatement>(_statement) || std::holds_alternative<ExpressionStatement>(_statement) ||
holds_alternative<Assignment>(_statement) std::holds_alternative<Assignment>(_statement)
) )
{ {
map<YulString, size_t> references = VariableReferencesCounter::countReferences(_statement); std::map<YulString, size_t> references = VariableReferencesCounter::countReferences(_statement);
auto isReferenced = [&references](TypedName const& _returnVariable) { auto isReferenced = [&references](TypedName const& _returnVariable) {
return references.count(_returnVariable.name); return references.count(_returnVariable.name);
}; };
@ -680,7 +679,7 @@ bool statementNeedsReturnVariableSetup(Statement const& _statement, vector<Typed
} }
void CodeTransform::visitStatements(vector<Statement> const& _statements) void CodeTransform::visitStatements(std::vector<Statement> const& _statements)
{ {
std::optional<AbstractAssembly::LabelID> jumpTarget = std::nullopt; std::optional<AbstractAssembly::LabelID> jumpTarget = std::nullopt;
@ -716,7 +715,7 @@ void CodeTransform::visitStatements(vector<Statement> const& _statements)
freeUnusedVariables(); freeUnusedVariables();
} }
void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartStackHeight) void CodeTransform::finalizeBlock(Block const& _block, std::optional<int> blockStartStackHeight)
{ {
m_assembly.setSourceLocation(originLocationOf(_block)); m_assembly.setSourceLocation(originLocationOf(_block));
@ -725,7 +724,7 @@ void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartS
// pop variables // pop variables
yulAssert(m_info.scopes.at(&_block).get() == m_scope, ""); yulAssert(m_info.scopes.at(&_block).get() == m_scope, "");
for (auto const& id: m_scope->identifiers) for (auto const& id: m_scope->identifiers)
if (holds_alternative<Scope::Variable>(id.second)) if (std::holds_alternative<Scope::Variable>(id.second))
{ {
Scope::Variable const& var = std::get<Scope::Variable>(id.second); Scope::Variable const& var = std::get<Scope::Variable>(id.second);
if (m_allowStackOpt) if (m_allowStackOpt)
@ -740,11 +739,11 @@ void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartS
if (blockStartStackHeight) if (blockStartStackHeight)
{ {
int deposit = m_assembly.stackHeight() - *blockStartStackHeight; int deposit = m_assembly.stackHeight() - *blockStartStackHeight;
yulAssert(deposit == 0, "Invalid stack height at end of block: " + to_string(deposit)); yulAssert(deposit == 0, "Invalid stack height at end of block: " + std::to_string(deposit));
} }
} }
void CodeTransform::generateMultiAssignment(vector<Identifier> const& _variableNames) void CodeTransform::generateMultiAssignment(std::vector<Identifier> const& _variableNames)
{ {
yulAssert(m_scope, ""); yulAssert(m_scope, "");
for (auto const& variableName: _variableNames | ranges::views::reverse) for (auto const& variableName: _variableNames | ranges::views::reverse)
@ -786,7 +785,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString
"Variable " + "Variable " +
_varName.str() + _varName.str() +
" is " + " is " +
to_string(heightDiff - limit) + std::to_string(heightDiff - limit) +
" slot(s) too deep inside the stack. " + " slot(s) too deep inside the stack. " +
stackTooDeepString stackTooDeepString
); );
@ -798,7 +797,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString
int CodeTransform::variableStackHeight(YulString _name) const int CodeTransform::variableStackHeight(YulString _name) const
{ {
Scope::Variable const* var = get_if<Scope::Variable>(m_scope->lookup(_name)); Scope::Variable const* var = std::get_if<Scope::Variable>(m_scope->lookup(_name));
yulAssert(var, ""); yulAssert(var, "");
return static_cast<int>(m_context->variableStackHeights.at(var)); return static_cast<int>(m_context->variableStackHeights.at(var));
} }

View File

@ -38,7 +38,7 @@
#include <regex> #include <regex>
using namespace std; using namespace std::string_literals;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -46,9 +46,9 @@ using namespace solidity::util;
namespace namespace
{ {
pair<YulString, BuiltinFunctionForEVM> createEVMFunction( std::pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
langutil::EVMVersion _evmVersion, langutil::EVMVersion _evmVersion,
string const& _name, std::string const& _name,
evmasm::Instruction _instruction evmasm::Instruction _instruction
) )
{ {
@ -87,12 +87,12 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
return {name, std::move(f)}; return {name, std::move(f)};
} }
pair<YulString, BuiltinFunctionForEVM> createFunction( std::pair<YulString, BuiltinFunctionForEVM> createFunction(
string _name, std::string _name,
size_t _params, size_t _params,
size_t _returns, size_t _returns,
SideEffects _sideEffects, SideEffects _sideEffects,
vector<optional<LiteralKind>> _literalArguments, std::vector<std::optional<LiteralKind>> _literalArguments,
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&)> _generateCode std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&)> _generateCode
) )
{ {
@ -111,7 +111,7 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
return {name, f}; return {name, f};
} }
set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion) std::set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
{ {
// TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
// basefee for VMs before london. // basefee for VMs before london.
@ -122,20 +122,20 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
// TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
// prevrandao for VMs before paris. // prevrandao for VMs before paris.
auto prevRandaoException = [&](string const& _instrName) -> bool auto prevRandaoException = [&](std::string const& _instrName) -> bool
{ {
// Using string comparison as the opcode is the same as for "difficulty" // Using string comparison as the opcode is the same as for "difficulty"
return _instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris(); return _instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris();
}; };
set<YulString> reserved; std::set<YulString> reserved;
for (auto const& instr: evmasm::c_instructions) for (auto const& instr: evmasm::c_instructions)
{ {
string name = toLower(instr.first); std::string name = toLower(instr.first);
if (!baseFeeException(instr.second) && !prevRandaoException(name)) if (!baseFeeException(instr.second) && !prevRandaoException(name))
reserved.emplace(name); reserved.emplace(name);
} }
reserved += vector<YulString>{ reserved += std::vector<YulString>{
"linkersymbol"_yulstring, "linkersymbol"_yulstring,
"datasize"_yulstring, "datasize"_yulstring,
"dataoffset"_yulstring, "dataoffset"_yulstring,
@ -146,19 +146,19 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
return reserved; return reserved;
} }
map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) std::map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess)
{ {
// Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris.
auto prevRandaoException = [&](string const& _instrName) -> bool auto prevRandaoException = [&](std::string const& _instrName) -> bool
{ {
return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris());
}; };
map<YulString, BuiltinFunctionForEVM> builtins; std::map<YulString, BuiltinFunctionForEVM> builtins;
for (auto const& instr: evmasm::c_instructions) for (auto const& instr: evmasm::c_instructions)
{ {
string name = toLower(instr.first); std::string name = toLower(instr.first);
auto const opcode = instr.second; auto const opcode = instr.second;
if ( if (
@ -198,7 +198,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
BuiltinContext& BuiltinContext&
) { ) {
yulAssert(_call.arguments.size() == 1, ""); yulAssert(_call.arguments.size() == 1, "");
Literal const* literal = get_if<Literal>(&_call.arguments.front()); Literal const* literal = std::get_if<Literal>(&_call.arguments.front());
yulAssert(literal, ""); yulAssert(literal, "");
_assembly.appendConstant(valueOfLiteral(*literal)); _assembly.appendConstant(valueOfLiteral(*literal));
}) })
@ -217,10 +217,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
_assembly.appendAssemblySize(); _assembly.appendAssemblySize();
else else
{ {
vector<size_t> subIdPath = std::vector<size_t> subIdPath =
_context.subIDs.count(dataName) == 0 ? _context.subIDs.count(dataName) == 0 ?
_context.currentObject->pathToSubObject(dataName) : _context.currentObject->pathToSubObject(dataName) :
vector<size_t>{_context.subIDs.at(dataName)}; std::vector<size_t>{_context.subIDs.at(dataName)};
yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">.");
_assembly.appendDataSize(subIdPath); _assembly.appendDataSize(subIdPath);
} }
@ -238,10 +238,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
_assembly.appendConstant(0); _assembly.appendConstant(0);
else else
{ {
vector<size_t> subIdPath = std::vector<size_t> subIdPath =
_context.subIDs.count(dataName) == 0 ? _context.subIDs.count(dataName) == 0 ?
_context.currentObject->pathToSubObject(dataName) : _context.currentObject->pathToSubObject(dataName) :
vector<size_t>{_context.subIDs.at(dataName)}; std::vector<size_t>{_context.subIDs.at(dataName)};
yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">.");
_assembly.appendDataOffset(subIdPath); _assembly.appendDataOffset(subIdPath);
} }
@ -295,9 +295,9 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
return builtins; return builtins;
} }
regex const& verbatimPattern() std::regex const& verbatimPattern()
{ {
regex static const pattern{"verbatim_([1-9]?[0-9])i_([1-9]?[0-9])o"}; std::regex static const pattern{"verbatim_([1-9]?[0-9])i_([1-9]?[0-9])o"};
return pattern; return pattern;
} }
@ -316,7 +316,7 @@ BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const
{ {
if (m_objectAccess) if (m_objectAccess)
{ {
smatch match; std::smatch match;
if (regex_match(_name.str(), match, verbatimPattern())) if (regex_match(_name.str(), match, verbatimPattern()))
return verbatimFunction(stoul(match[1]), stoul(match[2])); return verbatimFunction(stoul(match[1]), stoul(match[2]));
} }
@ -337,19 +337,19 @@ bool EVMDialect::reservedIdentifier(YulString _name) const
EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _version) EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _version)
{ {
static map<langutil::EVMVersion, unique_ptr<EVMDialect const>> dialects; static std::map<langutil::EVMVersion, std::unique_ptr<EVMDialect const>> dialects;
static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }};
if (!dialects[_version]) if (!dialects[_version])
dialects[_version] = make_unique<EVMDialect>(_version, false); dialects[_version] = std::make_unique<EVMDialect>(_version, false);
return *dialects[_version]; return *dialects[_version];
} }
EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _version) EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _version)
{ {
static map<langutil::EVMVersion, unique_ptr<EVMDialect const>> dialects; static std::map<langutil::EVMVersion, std::unique_ptr<EVMDialect const>> dialects;
static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }};
if (!dialects[_version]) if (!dialects[_version])
dialects[_version] = make_unique<EVMDialect>(_version, true); dialects[_version] = std::make_unique<EVMDialect>(_version, true);
return *dialects[_version]; return *dialects[_version];
} }
@ -374,16 +374,16 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio
BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const
{ {
pair<size_t, size_t> key{_arguments, _returnVariables}; std::pair<size_t, size_t> key{_arguments, _returnVariables};
shared_ptr<BuiltinFunctionForEVM const>& function = m_verbatimFunctions[key]; std::shared_ptr<BuiltinFunctionForEVM const>& function = m_verbatimFunctions[key];
if (!function) if (!function)
{ {
BuiltinFunctionForEVM builtinFunction = createFunction( BuiltinFunctionForEVM builtinFunction = createFunction(
"verbatim_" + to_string(_arguments) + "i_" + to_string(_returnVariables) + "o", "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o",
1 + _arguments, 1 + _arguments,
_returnVariables, _returnVariables,
SideEffects::worst(), SideEffects::worst(),
vector<optional<LiteralKind>>{LiteralKind::String} + vector<optional<LiteralKind>>(_arguments), std::vector<std::optional<LiteralKind>>{LiteralKind::String} + std::vector<std::optional<LiteralKind>>(_arguments),
[=]( [=](
FunctionCall const& _call, FunctionCall const& _call,
AbstractAssembly& _assembly, AbstractAssembly& _assembly,
@ -400,7 +400,7 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz
} }
).second; ).second;
builtinFunction.isMSize = true; builtinFunction.isMSize = true;
function = make_shared<BuiltinFunctionForEVM const>(std::move(builtinFunction)); function = std::make_shared<BuiltinFunctionForEVM const>(std::move(builtinFunction));
} }
return function.get(); return function.get();
} }
@ -501,9 +501,9 @@ BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(YulString _type)
EVMDialectTyped const& EVMDialectTyped::instance(langutil::EVMVersion _version) EVMDialectTyped const& EVMDialectTyped::instance(langutil::EVMVersion _version)
{ {
static map<langutil::EVMVersion, unique_ptr<EVMDialectTyped const>> dialects; static std::map<langutil::EVMVersion, std::unique_ptr<EVMDialectTyped const>> dialects;
static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }};
if (!dialects[_version]) if (!dialects[_version])
dialects[_version] = make_unique<EVMDialectTyped>(_version, true); dialects[_version] = std::make_unique<EVMDialectTyped>(_version, true);
return *dialects[_version]; return *dialects[_version];
} }

View File

@ -31,7 +31,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -52,7 +51,7 @@ bigint GasMeter::combineCosts(std::pair<bigint, bigint> _costs) const
} }
pair<bigint, bigint> GasMeterVisitor::costs( std::pair<bigint, bigint> GasMeterVisitor::costs(
Expression const& _expression, Expression const& _expression,
EVMDialect const& _dialect, EVMDialect const& _dialect,
bool _isCreation bool _isCreation
@ -63,7 +62,7 @@ pair<bigint, bigint> GasMeterVisitor::costs(
return {gmv.m_runGas, gmv.m_dataGas}; return {gmv.m_runGas, gmv.m_dataGas};
} }
pair<bigint, bigint> GasMeterVisitor::instructionCosts( std::pair<bigint, bigint> GasMeterVisitor::instructionCosts(
evmasm::Instruction _instruction, evmasm::Instruction _instruction,
EVMDialect const& _dialect, EVMDialect const& _dialect,
bool _isCreation bool _isCreation

View File

@ -33,7 +33,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
using namespace solidity::yul; using namespace solidity::yul;
using namespace std;
void EVMObjectCompiler::compile( void EVMObjectCompiler::compile(
Object& _object, Object& _object,
@ -91,12 +90,12 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
); );
if (!stackErrors.empty()) if (!stackErrors.empty())
{ {
vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run( std::vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run(
*_object.code, *_object.code,
"memoryguard"_yulstring "memoryguard"_yulstring
); );
auto stackError = stackErrors.front(); auto stackError = stackErrors.front();
string msg = stackError.comment() ? *stackError.comment() : ""; std::string msg = stackError.comment() ? *stackError.comment() : "";
if (memoryGuardCalls.empty()) if (memoryGuardCalls.empty())
msg += "\nNo memoryguard was present. " msg += "\nNo memoryguard was present. "
"Consider using memory-safe assembly only and annotating it via " "Consider using memory-safe assembly only and annotating it via "

View File

@ -33,7 +33,6 @@
#include <memory> #include <memory>
#include <functional> #include <functional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -122,14 +121,14 @@ void EthAssemblyAdapter::appendAssemblySize()
m_assembly.appendProgramSize(); m_assembly.appendProgramSize();
} }
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name) std::pair<std::shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, std::string _name)
{ {
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(m_assembly.evmVersion(), _creation, std::move(_name))}; std::shared_ptr<evmasm::Assembly> assembly{std::make_shared<evmasm::Assembly>(m_assembly.evmVersion(), _creation, std::move(_name))};
auto sub = m_assembly.newSub(assembly); auto sub = m_assembly.newSub(assembly);
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())}; return {std::make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
} }
void EthAssemblyAdapter::appendDataOffset(vector<AbstractAssembly::SubID> const& _subPath) void EthAssemblyAdapter::appendDataOffset(std::vector<AbstractAssembly::SubID> const& _subPath)
{ {
if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end()) if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end())
{ {
@ -141,7 +140,7 @@ void EthAssemblyAdapter::appendDataOffset(vector<AbstractAssembly::SubID> const&
m_assembly.pushSubroutineOffset(m_assembly.encodeSubPath(_subPath)); m_assembly.pushSubroutineOffset(m_assembly.encodeSubPath(_subPath));
} }
void EthAssemblyAdapter::appendDataSize(vector<AbstractAssembly::SubID> const& _subPath) void EthAssemblyAdapter::appendDataSize(std::vector<AbstractAssembly::SubID> const& _subPath)
{ {
if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end()) if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end())
{ {

View File

@ -28,7 +28,6 @@
#include <range/v3/view/iota.hpp> #include <range/v3/view/iota.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -60,12 +59,12 @@ NoOutputAssembly::LabelID NoOutputAssembly::newLabelId()
return 1; return 1;
} }
AbstractAssembly::LabelID NoOutputAssembly::namedLabel(string const&, size_t, size_t, optional<size_t>) AbstractAssembly::LabelID NoOutputAssembly::namedLabel(std::string const&, size_t, size_t, std::optional<size_t>)
{ {
return 1; return 1;
} }
void NoOutputAssembly::appendLinkerSymbol(string const&) void NoOutputAssembly::appendLinkerSymbol(std::string const&)
{ {
yulAssert(false, "Linker symbols not yet implemented."); yulAssert(false, "Linker symbols not yet implemented.");
} }
@ -98,7 +97,7 @@ void NoOutputAssembly::appendAssemblySize()
appendInstruction(evmasm::Instruction::PUSH1); appendInstruction(evmasm::Instruction::PUSH1);
} }
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string) std::pair<std::shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string)
{ {
yulAssert(false, "Sub assemblies not implemented."); yulAssert(false, "Sub assemblies not implemented.");
return {}; return {};

View File

@ -38,9 +38,8 @@
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace std;
vector<StackTooDeepError> OptimizedEVMCodeTransform::run( std::vector<StackTooDeepError> OptimizedEVMCodeTransform::run(
AbstractAssembly& _assembly, AbstractAssembly& _assembly,
AsmAnalysisInfo& _analysisInfo, AsmAnalysisInfo& _analysisInfo,
Block const& _block, Block const& _block,
@ -81,7 +80,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call)
// Assert that we got the correct return label on stack. // Assert that we got the correct return label on stack.
if (_call.canContinue) if (_call.canContinue)
{ {
auto const* returnLabelSlot = get_if<FunctionCallReturnLabelSlot>( auto const* returnLabelSlot = std::get_if<FunctionCallReturnLabelSlot>(
&m_stack.at(m_stack.size() - _call.functionCall.get().arguments.size() - 1) &m_stack.at(m_stack.size() - _call.functionCall.get().arguments.size() - 1)
); );
yulAssert(returnLabelSlot && &returnLabelSlot->call.get() == &_call.functionCall.get(), ""); yulAssert(returnLabelSlot && &returnLabelSlot->call.get() == &_call.functionCall.get(), "");
@ -160,7 +159,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::Assignment const& _assignment)
// Invalidate occurrences of the assigned variables. // Invalidate occurrences of the assigned variables.
for (auto& currentSlot: m_stack) for (auto& currentSlot: m_stack)
if (VariableSlot const* varSlot = get_if<VariableSlot>(&currentSlot)) if (VariableSlot const* varSlot = std::get_if<VariableSlot>(&currentSlot))
if (util::contains(_assignment.variables, *varSlot)) if (util::contains(_assignment.variables, *varSlot))
currentSlot = JunkSlot{}; currentSlot = JunkSlot{};
@ -185,8 +184,8 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform(
m_dfg(_dfg), m_dfg(_dfg),
m_stackLayout(_stackLayout), m_stackLayout(_stackLayout),
m_functionLabels([&](){ m_functionLabels([&](){
map<CFG::FunctionInfo const*, AbstractAssembly::LabelID> functionLabels; std::map<CFG::FunctionInfo const*, AbstractAssembly::LabelID> functionLabels;
set<YulString> assignedFunctionNames; std::set<YulString> assignedFunctionNames;
for (Scope::Function const* function: m_dfg.functions) for (Scope::Function const* function: m_dfg.functions)
{ {
CFG::FunctionInfo const& functionInfo = m_dfg.functionInfo.at(function); CFG::FunctionInfo const& functionInfo = m_dfg.functionInfo.at(function);
@ -199,7 +198,7 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform(
function->name.str(), function->name.str(),
function->arguments.size(), function->arguments.size(),
function->returns.size(), function->returns.size(),
functionInfo.debugData ? functionInfo.debugData->astID : nullopt functionInfo.debugData ? functionInfo.debugData->astID : std::nullopt
) : ) :
m_assembly.newLabelId(); m_assembly.newLabelId();
} }
@ -212,7 +211,7 @@ void OptimizedEVMCodeTransform::assertLayoutCompatibility(Stack const& _currentS
{ {
yulAssert(_currentStack.size() == _desiredStack.size(), ""); yulAssert(_currentStack.size() == _desiredStack.size(), "");
for (auto&& [currentSlot, desiredSlot]: ranges::zip_view(_currentStack, _desiredStack)) for (auto&& [currentSlot, desiredSlot]: ranges::zip_view(_currentStack, _desiredStack))
yulAssert(holds_alternative<JunkSlot>(desiredSlot) || currentSlot == desiredSlot, ""); yulAssert(std::holds_alternative<JunkSlot>(desiredSlot) || currentSlot == desiredSlot, "");
} }
AbstractAssembly::LabelID OptimizedEVMCodeTransform::getFunctionLabel(Scope::Function const& _function) AbstractAssembly::LabelID OptimizedEVMCodeTransform::getFunctionLabel(Scope::Function const& _function)
@ -224,15 +223,15 @@ void OptimizedEVMCodeTransform::validateSlot(StackSlot const& _slot, Expression
{ {
std::visit(util::GenericVisitor{ std::visit(util::GenericVisitor{
[&](yul::Literal const& _literal) { [&](yul::Literal const& _literal) {
auto* literalSlot = get_if<LiteralSlot>(&_slot); auto* literalSlot = std::get_if<LiteralSlot>(&_slot);
yulAssert(literalSlot && valueOfLiteral(_literal) == literalSlot->value, ""); yulAssert(literalSlot && valueOfLiteral(_literal) == literalSlot->value, "");
}, },
[&](yul::Identifier const& _identifier) { [&](yul::Identifier const& _identifier) {
auto* variableSlot = get_if<VariableSlot>(&_slot); auto* variableSlot = std::get_if<VariableSlot>(&_slot);
yulAssert(variableSlot && variableSlot->variable.get().name == _identifier.name, ""); yulAssert(variableSlot && variableSlot->variable.get().name == _identifier.name, "");
}, },
[&](yul::FunctionCall const& _call) { [&](yul::FunctionCall const& _call) {
auto* temporarySlot = get_if<TemporarySlot>(&_slot); auto* temporarySlot = std::get_if<TemporarySlot>(&_slot);
yulAssert(temporarySlot && &temporarySlot->call.get() == &_call && temporarySlot->index == 0, ""); yulAssert(temporarySlot && &temporarySlot->call.get() == &_call && temporarySlot->index == 0, "");
} }
}, _expression); }, _expression);
@ -267,10 +266,10 @@ void OptimizedEVMCodeTransform::createStackLayout(std::shared_ptr<DebugData cons
StackSlot const& deepSlot = m_stack.at(m_stack.size() - _i - 1); StackSlot const& deepSlot = m_stack.at(m_stack.size() - _i - 1);
YulString varNameDeep = slotVariableName(deepSlot); YulString varNameDeep = slotVariableName(deepSlot);
YulString varNameTop = slotVariableName(m_stack.back()); YulString varNameTop = slotVariableName(m_stack.back());
string msg = std::string msg =
"Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot) : "Variable " + varNameDeep.str()) + "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot) : "Variable " + varNameDeep.str()) +
" with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back()) : "Variable " + varNameTop.str()) + " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back()) : "Variable " + varNameTop.str()) +
": too deep in the stack by " + to_string(deficit) + " slots in " + stackToString(m_stack); ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack);
m_stackErrors.emplace_back(StackTooDeepError( m_stackErrors.emplace_back(StackTooDeepError(
m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{}, m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{},
varNameDeep.empty() ? varNameTop : varNameDeep, varNameDeep.empty() ? varNameTop : varNameDeep,
@ -297,9 +296,9 @@ void OptimizedEVMCodeTransform::createStackLayout(std::shared_ptr<DebugData cons
{ {
int deficit = static_cast<int>(*depth - 15); int deficit = static_cast<int>(*depth - 15);
YulString varName = slotVariableName(_slot); YulString varName = slotVariableName(_slot);
string msg = std::string msg =
(varName.empty() ? "Slot " + stackSlotToString(_slot) : "Variable " + varName.str()) (varName.empty() ? "Slot " + stackSlotToString(_slot) : "Variable " + varName.str())
+ " is " + to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack); + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack);
m_stackErrors.emplace_back(StackTooDeepError( m_stackErrors.emplace_back(StackTooDeepError(
m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{}, m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{},
varName, varName,
@ -503,9 +502,9 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block)
[&](CFG::BasicBlock::Terminated const&) [&](CFG::BasicBlock::Terminated const&)
{ {
yulAssert(!_block.operations.empty()); yulAssert(!_block.operations.empty());
if (CFG::BuiltinCall const* builtinCall = get_if<CFG::BuiltinCall>(&_block.operations.back().operation)) if (CFG::BuiltinCall const* builtinCall = std::get_if<CFG::BuiltinCall>(&_block.operations.back().operation))
yulAssert(builtinCall->builtin.get().controlFlowSideEffects.terminatesOrReverts(), ""); yulAssert(builtinCall->builtin.get().controlFlowSideEffects.terminatesOrReverts(), "");
else if (CFG::FunctionCall const* functionCall = get_if<CFG::FunctionCall>(&_block.operations.back().operation)) else if (CFG::FunctionCall const* functionCall = std::get_if<CFG::FunctionCall>(&_block.operations.back().operation))
yulAssert(!functionCall->canContinue); yulAssert(!functionCall->canContinue);
else else
yulAssert(false); yulAssert(false);

View File

@ -46,7 +46,6 @@
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace std;
StackLayout StackLayoutGenerator::run(CFG const& _cfg) StackLayout StackLayoutGenerator::run(CFG const& _cfg)
{ {
@ -59,9 +58,9 @@ StackLayout StackLayoutGenerator::run(CFG const& _cfg)
return stackLayout; return stackLayout;
} }
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) std::map<YulString, std::vector<StackLayoutGenerator::StackTooDeep>> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg)
{ {
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> stackTooDeepErrors; std::map<YulString, std::vector<StackLayoutGenerator::StackTooDeep>> stackTooDeepErrors;
stackTooDeepErrors[YulString{}] = reportStackTooDeep(_cfg, YulString{}); stackTooDeepErrors[YulString{}] = reportStackTooDeep(_cfg, YulString{});
for (auto const& function: _cfg.functions) for (auto const& function: _cfg.functions)
if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty()) if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty())
@ -69,7 +68,7 @@ map<YulString, vector<StackLayoutGenerator::StackTooDeep>> StackLayoutGenerator:
return stackTooDeepErrors; return stackTooDeepErrors;
} }
vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName) std::vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName)
{ {
StackLayout stackLayout; StackLayout stackLayout;
CFG::FunctionInfo const* functionInfo = nullptr; CFG::FunctionInfo const* functionInfo = nullptr;
@ -98,14 +97,14 @@ StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout, CFG::FunctionIn
namespace namespace
{ {
/// @returns all stack too deep errors that would occur when shuffling @a _source to @a _target. /// @returns all stack too deep errors that would occur when shuffling @a _source to @a _target.
vector<StackLayoutGenerator::StackTooDeep> findStackTooDeep(Stack const& _source, Stack const& _target) std::vector<StackLayoutGenerator::StackTooDeep> findStackTooDeep(Stack const& _source, Stack const& _target)
{ {
Stack currentStack = _source; Stack currentStack = _source;
vector<StackLayoutGenerator::StackTooDeep> stackTooDeepErrors; std::vector<StackLayoutGenerator::StackTooDeep> stackTooDeepErrors;
auto getVariableChoices = [](auto&& _range) { auto getVariableChoices = [](auto&& _range) {
vector<YulString> result; std::vector<YulString> result;
for (auto const& slot: _range) for (auto const& slot: _range)
if (auto const* variableSlot = get_if<VariableSlot>(&slot)) if (auto const* variableSlot = std::get_if<VariableSlot>(&slot))
if (!util::contains(result, variableSlot->variable.get().name)) if (!util::contains(result, variableSlot->variable.get().name))
result.push_back(variableSlot->variable.get().name); result.push_back(variableSlot->variable.get().name);
return result; return result;
@ -160,7 +159,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla
// PreviousSlot{0}, ..., PreviousSlot{n}, [output<0>], ..., [output<m>] // PreviousSlot{0}, ..., PreviousSlot{n}, [output<0>], ..., [output<m>]
auto layout = ranges::views::iota(0u, preOperationLayoutSize) | auto layout = ranges::views::iota(0u, preOperationLayoutSize) |
ranges::views::transform([](size_t _index) { return PreviousSlot{_index}; }) | ranges::views::transform([](size_t _index) { return PreviousSlot{_index}; }) |
ranges::to<vector<variant<PreviousSlot, StackSlot>>>; ranges::to<std::vector<std::variant<PreviousSlot, StackSlot>>>;
layout += _operationOutput; layout += _operationOutput;
// Shortcut for trivial case. // Shortcut for trivial case.
@ -171,23 +170,23 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla
// that are aware of PreviousSlot's. // that are aware of PreviousSlot's.
struct ShuffleOperations struct ShuffleOperations
{ {
vector<variant<PreviousSlot, StackSlot>>& layout; std::vector<std::variant<PreviousSlot, StackSlot>>& layout;
Stack const& post; Stack const& post;
std::set<StackSlot> outputs; std::set<StackSlot> outputs;
Multiplicity multiplicity; Multiplicity multiplicity;
Callable generateSlotOnTheFly; Callable generateSlotOnTheFly;
ShuffleOperations( ShuffleOperations(
vector<variant<PreviousSlot, StackSlot>>& _layout, std::vector<std::variant<PreviousSlot, StackSlot>>& _layout,
Stack const& _post, Stack const& _post,
Callable _generateSlotOnTheFly Callable _generateSlotOnTheFly
): layout(_layout), post(_post), generateSlotOnTheFly(_generateSlotOnTheFly) ): layout(_layout), post(_post), generateSlotOnTheFly(_generateSlotOnTheFly)
{ {
for (auto const& layoutSlot: layout) for (auto const& layoutSlot: layout)
if (StackSlot const* slot = get_if<StackSlot>(&layoutSlot)) if (StackSlot const* slot = std::get_if<StackSlot>(&layoutSlot))
outputs.insert(*slot); outputs.insert(*slot);
for (auto const& layoutSlot: layout) for (auto const& layoutSlot: layout)
if (StackSlot const* slot = get_if<StackSlot>(&layoutSlot)) if (StackSlot const* slot = std::get_if<StackSlot>(&layoutSlot))
--multiplicity[*slot]; --multiplicity[*slot];
for (auto&& slot: post) for (auto&& slot: post)
if (outputs.count(slot) || generateSlotOnTheFly(slot)) if (outputs.count(slot) || generateSlotOnTheFly(slot))
@ -235,7 +234,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla
} }
void swap(size_t _i) void swap(size_t _i)
{ {
yulAssert(!holds_alternative<PreviousSlot>(layout.at(layout.size() - _i - 1)) || !holds_alternative<PreviousSlot>(layout.back()), ""); yulAssert(!std::holds_alternative<PreviousSlot>(layout.at(layout.size() - _i - 1)) || !std::holds_alternative<PreviousSlot>(layout.back()), "");
std::swap(layout.at(layout.size() - _i - 1), layout.back()); std::swap(layout.at(layout.size() - _i - 1), layout.back());
} }
size_t sourceSize() { return layout.size(); } size_t sourceSize() { return layout.size(); }
@ -250,7 +249,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla
// output in place. The resulting permutation of the PreviousSlot yields the ideal positions of slots // output in place. The resulting permutation of the PreviousSlot yields the ideal positions of slots
// before the operation, i.e. if PreviousSlot{2} is at a position at which _post contains VariableSlot{"tmp"}, // before the operation, i.e. if PreviousSlot{2} is at a position at which _post contains VariableSlot{"tmp"},
// then we want the variable tmp in the slot at offset 2 in the layout before the operation. // then we want the variable tmp in the slot at offset 2 in the layout before the operation.
vector<optional<StackSlot>> idealLayout(_post.size(), nullopt); std::vector<std::optional<StackSlot>> idealLayout(_post.size(), std::nullopt);
for (auto&& [slot, idealPosition]: ranges::zip_view(_post, layout)) for (auto&& [slot, idealPosition]: ranges::zip_view(_post, layout))
if (PreviousSlot* previousSlot = std::get_if<PreviousSlot>(&idealPosition)) if (PreviousSlot* previousSlot = std::get_if<PreviousSlot>(&idealPosition))
idealLayout.at(previousSlot->slot) = slot; idealLayout.at(previousSlot->slot) = slot;
@ -261,7 +260,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla
yulAssert(idealLayout.size() == preOperationLayoutSize, ""); yulAssert(idealLayout.size() == preOperationLayoutSize, "");
return idealLayout | ranges::views::transform([](optional<StackSlot> s) { return idealLayout | ranges::views::transform([](std::optional<StackSlot> s) {
yulAssert(s, ""); yulAssert(s, "");
return *s; return *s;
}) | ranges::to<Stack>; }) | ranges::to<Stack>;
@ -271,7 +270,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla
Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG::Operation const& _operation, bool _aggressiveStackCompression) Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG::Operation const& _operation, bool _aggressiveStackCompression)
{ {
// Enable aggressive stack compression for recursive calls. // Enable aggressive stack compression for recursive calls.
if (auto const* functionCall = get_if<CFG::FunctionCall>(&_operation.operation)) if (auto const* functionCall = std::get_if<CFG::FunctionCall>(&_operation.operation))
if (functionCall->recursive) if (functionCall->recursive)
_aggressiveStackCompression = true; _aggressiveStackCompression = true;
@ -285,9 +284,9 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG
Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly); Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly);
// Make sure the resulting previous slots do not overlap with any assignmed variables. // Make sure the resulting previous slots do not overlap with any assignmed variables.
if (auto const* assignment = get_if<CFG::Assignment>(&_operation.operation)) if (auto const* assignment = std::get_if<CFG::Assignment>(&_operation.operation))
for (auto& stackSlot: stack) for (auto& stackSlot: stack)
if (auto const* varSlot = get_if<VariableSlot>(&stackSlot)) if (auto const* varSlot = std::get_if<VariableSlot>(&stackSlot))
yulAssert(!util::contains(assignment->variables, *varSlot), ""); yulAssert(!util::contains(assignment->variables, *varSlot), "");
// Since stack+_operation.output can be easily shuffled to _exitLayout, the desired layout before the operation // Since stack+_operation.output can be easily shuffled to _exitLayout, the desired layout before the operation
@ -335,11 +334,11 @@ Stack StackLayoutGenerator::propagateStackThroughBlock(Stack _exitStack, CFG::Ba
void StackLayoutGenerator::processEntryPoint(CFG::BasicBlock const& _entry, CFG::FunctionInfo const* _functionInfo) void StackLayoutGenerator::processEntryPoint(CFG::BasicBlock const& _entry, CFG::FunctionInfo const* _functionInfo)
{ {
list<CFG::BasicBlock const*> toVisit{&_entry}; std::list<CFG::BasicBlock const*> toVisit{&_entry};
set<CFG::BasicBlock const*> visited; std::set<CFG::BasicBlock const*> visited;
// TODO: check whether visiting only a subset of these in the outer iteration below is enough. // TODO: check whether visiting only a subset of these in the outer iteration below is enough.
list<pair<CFG::BasicBlock const*, CFG::BasicBlock const*>> backwardsJumps = collectBackwardsJumps(_entry); std::list<std::pair<CFG::BasicBlock const*, CFG::BasicBlock const*>> backwardsJumps = collectBackwardsJumps(_entry);
while (!toVisit.empty()) while (!toVisit.empty())
{ {
@ -407,10 +406,10 @@ void StackLayoutGenerator::processEntryPoint(CFG::BasicBlock const& _entry, CFG:
fillInJunk(_entry, _functionInfo); fillInJunk(_entry, _functionInfo);
} }
optional<Stack> StackLayoutGenerator::getExitLayoutOrStageDependencies( std::optional<Stack> StackLayoutGenerator::getExitLayoutOrStageDependencies(
CFG::BasicBlock const& _block, CFG::BasicBlock const& _block,
set<CFG::BasicBlock const*> const& _visited, std::set<CFG::BasicBlock const*> const& _visited,
list<CFG::BasicBlock const*>& _toVisit std::list<CFG::BasicBlock const*>& _toVisit
) const ) const
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
@ -434,7 +433,7 @@ optional<Stack> StackLayoutGenerator::getExitLayoutOrStageDependencies(
return m_layout.blockInfos.at(_jump.target).entryLayout; return m_layout.blockInfos.at(_jump.target).entryLayout;
// Otherwise stage the jump target for visit and defer the current block. // Otherwise stage the jump target for visit and defer the current block.
_toVisit.emplace_front(_jump.target); _toVisit.emplace_front(_jump.target);
return nullopt; return std::nullopt;
}, },
[&](CFG::BasicBlock::ConditionalJump const& _conditionalJump) -> std::optional<Stack> [&](CFG::BasicBlock::ConditionalJump const& _conditionalJump) -> std::optional<Stack>
{ {
@ -456,7 +455,7 @@ optional<Stack> StackLayoutGenerator::getExitLayoutOrStageDependencies(
_toVisit.emplace_front(_conditionalJump.zero); _toVisit.emplace_front(_conditionalJump.zero);
if (!nonZeroVisited) if (!nonZeroVisited)
_toVisit.emplace_front(_conditionalJump.nonZero); _toVisit.emplace_front(_conditionalJump.nonZero);
return nullopt; return std::nullopt;
}, },
[&](CFG::BasicBlock::FunctionReturn const& _functionReturn) -> std::optional<Stack> [&](CFG::BasicBlock::FunctionReturn const& _functionReturn) -> std::optional<Stack>
{ {
@ -476,9 +475,9 @@ optional<Stack> StackLayoutGenerator::getExitLayoutOrStageDependencies(
}, _block.exit); }, _block.exit);
} }
list<pair<CFG::BasicBlock const*, CFG::BasicBlock const*>> StackLayoutGenerator::collectBackwardsJumps(CFG::BasicBlock const& _entry) const std::list<std::pair<CFG::BasicBlock const*, CFG::BasicBlock const*>> StackLayoutGenerator::collectBackwardsJumps(CFG::BasicBlock const& _entry) const
{ {
list<pair<CFG::BasicBlock const*, CFG::BasicBlock const*>> backwardsJumps; std::list<std::pair<CFG::BasicBlock const*, CFG::BasicBlock const*>> backwardsJumps;
util::BreadthFirstSearch<CFG::BasicBlock const*>{{&_entry}}.run([&](CFG::BasicBlock const* _block, auto _addChild) { util::BreadthFirstSearch<CFG::BasicBlock const*>{{&_entry}}.run([&](CFG::BasicBlock const* _block, auto _addChild) {
std::visit(util::GenericVisitor{ std::visit(util::GenericVisitor{
[&](CFG::BasicBlock::MainExit const&) {}, [&](CFG::BasicBlock::MainExit const&) {},
@ -576,7 +575,7 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta
if (!util::contains(candidate, slot)) if (!util::contains(candidate, slot))
candidate.emplace_back(slot); candidate.emplace_back(slot);
cxx20::erase_if(candidate, [](StackSlot const& slot) { cxx20::erase_if(candidate, [](StackSlot const& slot) {
return holds_alternative<LiteralSlot>(slot) || holds_alternative<FunctionCallReturnLabelSlot>(slot); return std::holds_alternative<LiteralSlot>(slot) || std::holds_alternative<FunctionCallReturnLabelSlot>(slot);
}); });
auto evaluate = [&](Stack const& _candidate) -> size_t { auto evaluate = [&](Stack const& _candidate) -> size_t {
@ -633,9 +632,9 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta
return commonPrefix + bestCandidate; return commonPrefix + bestCandidate;
} }
vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG::BasicBlock const& _entry) const std::vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG::BasicBlock const& _entry) const
{ {
vector<StackTooDeep> stackTooDeepErrors; std::vector<StackTooDeep> stackTooDeepErrors;
util::BreadthFirstSearch<CFG::BasicBlock const*> breadthFirstSearch{{&_entry}}; util::BreadthFirstSearch<CFG::BasicBlock const*> breadthFirstSearch{{&_entry}};
breadthFirstSearch.run([&](CFG::BasicBlock const* _block, auto _addChild) { breadthFirstSearch.run([&](CFG::BasicBlock const* _block, auto _addChild) {
Stack currentStack = m_layout.blockInfos.at(_block).entryLayout; Stack currentStack = m_layout.blockInfos.at(_block).entryLayout;
@ -683,7 +682,7 @@ vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooD
Stack StackLayoutGenerator::compressStack(Stack _stack) Stack StackLayoutGenerator::compressStack(Stack _stack)
{ {
optional<size_t> firstDupOffset; std::optional<size_t> firstDupOffset;
do do
{ {
if (firstDupOffset) if (firstDupOffset)
@ -768,8 +767,8 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi
{ {
// This has to be a previously unassigned return variable. // This has to be a previously unassigned return variable.
// We at least sanity-check that it is among the return variables at all. // We at least sanity-check that it is among the return variables at all.
yulAssert(m_currentFunctionInfo && holds_alternative<VariableSlot>(_slot)); yulAssert(m_currentFunctionInfo && std::holds_alternative<VariableSlot>(_slot));
yulAssert(util::contains(m_currentFunctionInfo->returnVariables, get<VariableSlot>(_slot))); yulAssert(util::contains(m_currentFunctionInfo->returnVariables, std::get<VariableSlot>(_slot)));
// Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference
// will not matter here. // will not matter here.
opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion());; opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion());;

View File

@ -25,7 +25,6 @@
#include <libsolutil/Common.h> #include <libsolutil/Common.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;

View File

@ -25,7 +25,6 @@
#include <range/v3/view/reverse.hpp> #include <range/v3/view/reverse.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;

View File

@ -23,7 +23,6 @@
#include <functional> #include <functional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -34,9 +33,9 @@ void BlockFlattener::operator()(Block& _block)
iterateReplacing( iterateReplacing(
_block.statements, _block.statements,
[](Statement& _s) -> std::optional<vector<Statement>> [](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
if (holds_alternative<Block>(_s)) if (std::holds_alternative<Block>(_s))
return std::move(std::get<Block>(_s).statements); return std::move(std::get<Block>(_s).statements);
else else
return {}; return {};
@ -48,9 +47,9 @@ void BlockFlattener::run(OptimiserStepContext&, Block& _ast)
{ {
BlockFlattener flattener; BlockFlattener flattener;
for (auto& statement: _ast.statements) for (auto& statement: _ast.statements)
if (auto* block = get_if<Block>(&statement)) if (auto* block = std::get_if<Block>(&statement))
flattener(*block); flattener(*block);
else if (auto* function = get_if<FunctionDefinition>(&statement)) else if (auto* function = std::get_if<FunctionDefinition>(&statement))
flattener(function->body); flattener(function->body);
else else
yulAssert(false, "BlockFlattener requires the FunctionGrouper."); yulAssert(false, "BlockFlattener requires the FunctionGrouper.");

View File

@ -23,7 +23,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
#include <libyul/Utilities.h> #include <libyul/Utilities.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;

View File

@ -25,7 +25,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <stack> #include <stack>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -36,9 +35,9 @@ namespace
struct CallGraphCycleFinder struct CallGraphCycleFinder
{ {
CallGraph const& callGraph; CallGraph const& callGraph;
set<YulString> containedInCycle{}; std::set<YulString> containedInCycle{};
set<YulString> visited{}; std::set<YulString> visited{};
vector<YulString> currentPath{}; std::vector<YulString> currentPath{};
void visit(YulString _function) void visit(YulString _function)
{ {
@ -62,7 +61,7 @@ struct CallGraphCycleFinder
}; };
} }
set<YulString> CallGraph::recursiveFunctions() const std::set<YulString> CallGraph::recursiveFunctions() const
{ {
CallGraphCycleFinder cycleFinder{*this}; CallGraphCycleFinder cycleFinder{*this};
// Visiting the root only is not enough, since there may be disconnected recursive functions. // Visiting the root only is not enough, since there may be disconnected recursive functions.

View File

@ -24,7 +24,6 @@
#include <libsolutil/Algorithms.h> #include <libsolutil/Algorithms.h>
using namespace std;
using namespace solidity::yul; using namespace solidity::yul;
void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast) void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast)
@ -35,11 +34,11 @@ void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast)
void CircularReferencesPruner::operator()(Block& _block) void CircularReferencesPruner::operator()(Block& _block)
{ {
set<YulString> functionsToKeep = std::set<YulString> functionsToKeep =
functionsCalledFromOutermostContext(CallGraphGenerator::callGraph(_block)); functionsCalledFromOutermostContext(CallGraphGenerator::callGraph(_block));
for (auto&& statement: _block.statements) for (auto&& statement: _block.statements)
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
{ {
FunctionDefinition const& funDef = std::get<FunctionDefinition>(statement); FunctionDefinition const& funDef = std::get<FunctionDefinition>(statement);
if (!functionsToKeep.count(funDef.name)) if (!functionsToKeep.count(funDef.name))
@ -49,9 +48,9 @@ void CircularReferencesPruner::operator()(Block& _block)
removeEmptyBlocks(_block); removeEmptyBlocks(_block);
} }
set<YulString> CircularReferencesPruner::functionsCalledFromOutermostContext(CallGraph const& _callGraph) std::set<YulString> CircularReferencesPruner::functionsCalledFromOutermostContext(CallGraph const& _callGraph)
{ {
set<YulString> verticesToTraverse = m_reservedIdentifiers; std::set<YulString> verticesToTraverse = m_reservedIdentifiers;
verticesToTraverse.insert(YulString("")); verticesToTraverse.insert(YulString(""));
return util::BreadthFirstSearch<YulString>{{verticesToTraverse.begin(), verticesToTraverse.end()}}.run( return util::BreadthFirstSearch<YulString>{{verticesToTraverse.begin(), verticesToTraverse.end()}}.run(

View File

@ -31,7 +31,6 @@
#include <libyul/Dialect.h> #include <libyul/Dialect.h>
#include <libyul/Utilities.h> #include <libyul/Utilities.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -47,7 +46,7 @@ void CommonSubexpressionEliminator::run(OptimiserStepContext& _context, Block& _
CommonSubexpressionEliminator::CommonSubexpressionEliminator( CommonSubexpressionEliminator::CommonSubexpressionEliminator(
Dialect const& _dialect, Dialect const& _dialect,
map<YulString, SideEffects> _functionSideEffects std::map<YulString, SideEffects> _functionSideEffects
): ):
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects)) DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects))
{ {
@ -69,7 +68,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
bool descend = true; bool descend = true;
// If this is a function call to a function that requires literal arguments, // If this is a function call to a function that requires literal arguments,
// do not try to simplify there. // do not try to simplify there.
if (holds_alternative<FunctionCall>(_e)) if (std::holds_alternative<FunctionCall>(_e))
{ {
FunctionCall& funCall = std::get<FunctionCall>(_e); FunctionCall& funCall = std::get<FunctionCall>(_e);
@ -94,13 +93,13 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
if (descend) if (descend)
DataFlowAnalyzer::visit(_e); DataFlowAnalyzer::visit(_e);
if (Identifier const* identifier = get_if<Identifier>(&_e)) if (Identifier const* identifier = std::get_if<Identifier>(&_e))
{ {
YulString identifierName = identifier->name; YulString identifierName = identifier->name;
if (AssignedValue const* assignedValue = variableValue(identifierName)) if (AssignedValue const* assignedValue = variableValue(identifierName))
{ {
assertThrow(assignedValue->value, OptimizerException, ""); assertThrow(assignedValue->value, OptimizerException, "");
if (Identifier const* value = get_if<Identifier>(assignedValue->value)) if (Identifier const* value = std::get_if<Identifier>(assignedValue->value))
if (inScope(value->name)) if (inScope(value->name))
_e = Identifier{debugDataOf(_e), value->name}; _e = Identifier{debugDataOf(_e), value->name};
} }
@ -114,8 +113,8 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
// instead of literal zeros. // instead of literal zeros.
if ( if (
m_returnVariables.count(variable) && m_returnVariables.count(variable) &&
holds_alternative<Literal>(*value->value) && std::holds_alternative<Literal>(*value->value) &&
valueOfLiteral(get<Literal>(*value->value)) == 0 valueOfLiteral(std::get<Literal>(*value->value)) == 0
) )
continue; continue;
// We check for syntactic equality again because the value might have changed. // We check for syntactic equality again because the value might have changed.

View File

@ -22,7 +22,6 @@
#include <libyul/ControlFlowSideEffectsCollector.h> #include <libyul/ControlFlowSideEffectsCollector.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -38,7 +37,7 @@ void ConditionalSimplifier::run(OptimiserStepContext& _context, Block& _ast)
void ConditionalSimplifier::operator()(Switch& _switch) void ConditionalSimplifier::operator()(Switch& _switch)
{ {
visit(*_switch.expression); visit(*_switch.expression);
if (!holds_alternative<Identifier>(*_switch.expression)) if (!std::holds_alternative<Identifier>(*_switch.expression))
{ {
ASTModifier::operator()(_switch); ASTModifier::operator()(_switch);
return; return;
@ -53,7 +52,7 @@ void ConditionalSimplifier::operator()(Switch& _switch)
Assignment{ Assignment{
_case.body.debugData, _case.body.debugData,
{Identifier{_case.body.debugData, expr}}, {Identifier{_case.body.debugData, expr}},
make_unique<Expression>(*_case.value) std::make_unique<Expression>(*_case.value)
} }
); );
} }
@ -65,14 +64,14 @@ void ConditionalSimplifier::operator()(Block& _block)
{ {
iterateReplacing( iterateReplacing(
_block.statements, _block.statements,
[&](Statement& _s) -> std::optional<vector<Statement>> [&](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
visit(_s); visit(_s);
if (holds_alternative<If>(_s)) if (std::holds_alternative<If>(_s))
{ {
If& _if = std::get<If>(_s); If& _if = std::get<If>(_s);
if ( if (
holds_alternative<Identifier>(*_if.condition) && std::holds_alternative<Identifier>(*_if.condition) &&
!_if.body.statements.empty() && !_if.body.statements.empty() &&
TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) !=
TerminationFinder::ControlFlow::FlowOut TerminationFinder::ControlFlow::FlowOut
@ -85,7 +84,7 @@ void ConditionalSimplifier::operator()(Block& _block)
Assignment{ Assignment{
debugData, debugData,
{Identifier{debugData, condition}}, {Identifier{debugData, condition}},
make_unique<Expression>(m_dialect.zeroLiteralForType(m_dialect.boolType)) std::make_unique<Expression>(m_dialect.zeroLiteralForType(m_dialect.boolType))
} }
); );
} }

View File

@ -23,7 +23,6 @@
#include <libyul/ControlFlowSideEffectsCollector.h> #include <libyul/ControlFlowSideEffectsCollector.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -39,7 +38,7 @@ void ConditionalUnsimplifier::run(OptimiserStepContext& _context, Block& _ast)
void ConditionalUnsimplifier::operator()(Switch& _switch) void ConditionalUnsimplifier::operator()(Switch& _switch)
{ {
visit(*_switch.expression); visit(*_switch.expression);
if (!holds_alternative<Identifier>(*_switch.expression)) if (!std::holds_alternative<Identifier>(*_switch.expression))
{ {
ASTModifier::operator()(_switch); ASTModifier::operator()(_switch);
return; return;
@ -52,14 +51,14 @@ void ConditionalUnsimplifier::operator()(Switch& _switch)
(*this)(*_case.value); (*this)(*_case.value);
if ( if (
!_case.body.statements.empty() && !_case.body.statements.empty() &&
holds_alternative<Assignment>(_case.body.statements.front()) std::holds_alternative<Assignment>(_case.body.statements.front())
) )
{ {
Assignment const& assignment = std::get<Assignment>(_case.body.statements.front()); Assignment const& assignment = std::get<Assignment>(_case.body.statements.front());
if ( if (
assignment.variableNames.size() == 1 && assignment.variableNames.size() == 1 &&
assignment.variableNames.front().name == expr && assignment.variableNames.front().name == expr &&
holds_alternative<Literal>(*assignment.value) && std::holds_alternative<Literal>(*assignment.value) &&
valueOfLiteral(std::get<Literal>(*assignment.value)) == valueOfLiteral(*_case.value) valueOfLiteral(std::get<Literal>(*assignment.value)) == valueOfLiteral(*_case.value)
) )
_case.body.statements.erase(_case.body.statements.begin()); _case.body.statements.erase(_case.body.statements.begin());
@ -74,19 +73,19 @@ void ConditionalUnsimplifier::operator()(Block& _block)
walkVector(_block.statements); walkVector(_block.statements);
iterateReplacingWindow<2>( iterateReplacingWindow<2>(
_block.statements, _block.statements,
[&](Statement& _stmt1, Statement& _stmt2) -> std::optional<vector<Statement>> [&](Statement& _stmt1, Statement& _stmt2) -> std::optional<std::vector<Statement>>
{ {
if (holds_alternative<If>(_stmt1)) if (std::holds_alternative<If>(_stmt1))
{ {
If& _if = std::get<If>(_stmt1); If& _if = std::get<If>(_stmt1);
if ( if (
holds_alternative<Identifier>(*_if.condition) && std::holds_alternative<Identifier>(*_if.condition) &&
!_if.body.statements.empty() !_if.body.statements.empty()
) )
{ {
YulString condition = std::get<Identifier>(*_if.condition).name; YulString condition = std::get<Identifier>(*_if.condition).name;
if ( if (
holds_alternative<Assignment>(_stmt2) && std::holds_alternative<Assignment>(_stmt2) &&
TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) !=
TerminationFinder::ControlFlow::FlowOut TerminationFinder::ControlFlow::FlowOut
) )
@ -95,7 +94,7 @@ void ConditionalUnsimplifier::operator()(Block& _block)
if ( if (
assignment.variableNames.size() == 1 && assignment.variableNames.size() == 1 &&
assignment.variableNames.front().name == condition && assignment.variableNames.front().name == condition &&
holds_alternative<Literal>(*assignment.value) && std::holds_alternative<Literal>(*assignment.value) &&
valueOfLiteral(std::get<Literal>(*assignment.value)) == 0 valueOfLiteral(std::get<Literal>(*assignment.value)) == 0
) )
return {make_vector<Statement>(std::move(_stmt1))}; return {make_vector<Statement>(std::move(_stmt1))};

View File

@ -27,12 +27,11 @@
#include <range/v3/action/remove_if.hpp> #include <range/v3/action/remove_if.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::yul; using namespace solidity::yul;
using OptionalStatements = std::optional<vector<Statement>>; using OptionalStatements = std::optional<std::vector<Statement>>;
namespace namespace
{ {
@ -85,13 +84,13 @@ void ControlFlowSimplifier::operator()(Block& _block)
void ControlFlowSimplifier::operator()(FunctionDefinition& _funDef) void ControlFlowSimplifier::operator()(FunctionDefinition& _funDef)
{ {
ASTModifier::operator()(_funDef); ASTModifier::operator()(_funDef);
if (!_funDef.body.statements.empty() && holds_alternative<Leave>(_funDef.body.statements.back())) if (!_funDef.body.statements.empty() && std::holds_alternative<Leave>(_funDef.body.statements.back()))
_funDef.body.statements.pop_back(); _funDef.body.statements.pop_back();
} }
void ControlFlowSimplifier::visit(Statement& _st) void ControlFlowSimplifier::visit(Statement& _st)
{ {
if (holds_alternative<ForLoop>(_st)) if (std::holds_alternative<ForLoop>(_st))
{ {
ForLoop& forLoop = std::get<ForLoop>(_st); ForLoop& forLoop = std::get<ForLoop>(_st);
yulAssert(forLoop.pre.statements.empty(), ""); yulAssert(forLoop.pre.statements.empty(), "");
@ -141,7 +140,7 @@ void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
[&](If& _ifStmt) -> OptionalStatements { [&](If& _ifStmt) -> OptionalStatements {
if (_ifStmt.body.statements.empty() && m_dialect.discardFunction(m_dialect.boolType)) if (_ifStmt.body.statements.empty() && m_dialect.discardFunction(m_dialect.boolType))
{ {
OptionalStatements s = vector<Statement>{}; OptionalStatements s = std::vector<Statement>{};
s->emplace_back(makeDiscardCall( s->emplace_back(makeDiscardCall(
_ifStmt.debugData, _ifStmt.debugData,
*m_dialect.discardFunction(m_dialect.boolType), *m_dialect.discardFunction(m_dialect.boolType),
@ -197,7 +196,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!"); yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!");
auto& switchCase = _switchStmt.cases.front(); auto& switchCase = _switchStmt.cases.front();
shared_ptr<DebugData const> debugData = debugDataOf(*_switchStmt.expression); std::shared_ptr<DebugData const> debugData = debugDataOf(*_switchStmt.expression);
YulString type = m_typeInfo.typeOf(*_switchStmt.expression); YulString type = m_typeInfo.typeOf(*_switchStmt.expression);
if (switchCase.value) if (switchCase.value)
{ {
@ -205,7 +204,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch
return {}; return {};
return make_vector<Statement>(If{ return make_vector<Statement>(If{
std::move(_switchStmt.debugData), std::move(_switchStmt.debugData),
make_unique<Expression>(FunctionCall{ std::make_unique<Expression>(FunctionCall{
debugData, debugData,
Identifier{debugData, m_dialect.equalityFunction(type)->name}, Identifier{debugData, m_dialect.equalityFunction(type)->name},
{std::move(*switchCase.value), std::move(*_switchStmt.expression)} {std::move(*switchCase.value), std::move(*_switchStmt.expression)}

View File

@ -38,7 +38,6 @@
#include <range/v3/view/reverse.hpp> #include <range/v3/view/reverse.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::yul; using namespace solidity::yul;
@ -46,7 +45,7 @@ using namespace solidity::yul;
DataFlowAnalyzer::DataFlowAnalyzer( DataFlowAnalyzer::DataFlowAnalyzer(
Dialect const& _dialect, Dialect const& _dialect,
MemoryAndStorage _analyzeStores, MemoryAndStorage _analyzeStores,
map<YulString, SideEffects> _functionSideEffects std::map<YulString, SideEffects> _functionSideEffects
): ):
m_dialect(_dialect), m_dialect(_dialect),
m_functionSideEffects(std::move(_functionSideEffects)), m_functionSideEffects(std::move(_functionSideEffects)),
@ -99,7 +98,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement)
void DataFlowAnalyzer::operator()(Assignment& _assignment) void DataFlowAnalyzer::operator()(Assignment& _assignment)
{ {
set<YulString> names; std::set<YulString> names;
for (auto const& var: _assignment.variableNames) for (auto const& var: _assignment.variableNames)
names.emplace(var.name); names.emplace(var.name);
assertThrow(_assignment.value, OptimizerException, ""); assertThrow(_assignment.value, OptimizerException, "");
@ -110,7 +109,7 @@ void DataFlowAnalyzer::operator()(Assignment& _assignment)
void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl) void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl)
{ {
set<YulString> names; std::set<YulString> names;
for (auto const& var: _varDecl.variables) for (auto const& var: _varDecl.variables)
names.emplace(var.name); names.emplace(var.name);
m_variableScopes.back().variables += names; m_variableScopes.back().variables += names;
@ -139,14 +138,14 @@ void DataFlowAnalyzer::operator()(Switch& _switch)
{ {
clearKnowledgeIfInvalidated(*_switch.expression); clearKnowledgeIfInvalidated(*_switch.expression);
visit(*_switch.expression); visit(*_switch.expression);
set<YulString> assignedVariables; std::set<YulString> assignedVariables;
for (auto& _case: _switch.cases) for (auto& _case: _switch.cases)
{ {
Environment preEnvironment = m_state.environment; Environment preEnvironment = m_state.environment;
(*this)(_case.body); (*this)(_case.body);
joinKnowledge(preEnvironment); joinKnowledge(preEnvironment);
set<YulString> variables = assignedVariableNames(_case.body); std::set<YulString> variables = assignedVariableNames(_case.body);
assignedVariables += variables; assignedVariables += variables;
// This is a little too destructive, we could retain the old values. // This is a little too destructive, we could retain the old values.
clearValues(variables); clearValues(variables);
@ -192,7 +191,7 @@ void DataFlowAnalyzer::operator()(ForLoop& _for)
AssignmentsSinceContinue assignmentsSinceCont; AssignmentsSinceContinue assignmentsSinceCont;
assignmentsSinceCont(_for.body); assignmentsSinceCont(_for.body);
set<YulString> assignedVariables = std::set<YulString> assignedVariables =
assignedVariableNames(_for.body) + assignedVariableNames(_for.post); assignedVariableNames(_for.body) + assignedVariableNames(_for.post);
clearValues(assignedVariables); clearValues(assignedVariables);
@ -223,31 +222,31 @@ void DataFlowAnalyzer::operator()(Block& _block)
assertThrow(numScopes == m_variableScopes.size(), OptimizerException, ""); assertThrow(numScopes == m_variableScopes.size(), OptimizerException, "");
} }
optional<YulString> DataFlowAnalyzer::storageValue(YulString _key) const std::optional<YulString> DataFlowAnalyzer::storageValue(YulString _key) const
{ {
if (YulString const* value = valueOrNullptr(m_state.environment.storage, _key)) if (YulString const* value = valueOrNullptr(m_state.environment.storage, _key))
return *value; return *value;
else else
return nullopt; return std::nullopt;
} }
optional<YulString> DataFlowAnalyzer::memoryValue(YulString _key) const std::optional<YulString> DataFlowAnalyzer::memoryValue(YulString _key) const
{ {
if (YulString const* value = valueOrNullptr(m_state.environment.memory, _key)) if (YulString const* value = valueOrNullptr(m_state.environment.memory, _key))
return *value; return *value;
else else
return nullopt; return std::nullopt;
} }
optional<YulString> DataFlowAnalyzer::keccakValue(YulString _start, YulString _length) const std::optional<YulString> DataFlowAnalyzer::keccakValue(YulString _start, YulString _length) const
{ {
if (YulString const* value = valueOrNullptr(m_state.environment.keccak, make_pair(_start, _length))) if (YulString const* value = valueOrNullptr(m_state.environment.keccak, std::make_pair(_start, _length)))
return *value; return *value;
else else
return nullopt; return std::nullopt;
} }
void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expression* _value, bool _isDeclaration) void DataFlowAnalyzer::handleAssignment(std::set<YulString> const& _variables, Expression* _value, bool _isDeclaration)
{ {
if (!_isDeclaration) if (!_isDeclaration)
clearValues(_variables); clearValues(_variables);
@ -321,7 +320,7 @@ void DataFlowAnalyzer::popScope()
m_variableScopes.pop_back(); m_variableScopes.pop_back();
} }
void DataFlowAnalyzer::clearValues(set<YulString> _variables) void DataFlowAnalyzer::clearValues(std::set<YulString> _variables)
{ {
// All variables that reference variables to be cleared also have to be // All variables that reference variables to be cleared also have to be
// cleared, but not recursively, since only the value of the original // cleared, but not recursively, since only the value of the original
@ -410,24 +409,24 @@ bool DataFlowAnalyzer::inScope(YulString _variableName) const
return false; return false;
} }
optional<u256> DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) const std::optional<u256> DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) const
{ {
if (AssignedValue const* value = variableValue(_name)) if (AssignedValue const* value = variableValue(_name))
if (Literal const* literal = get_if<Literal>(value->value)) if (Literal const* literal = std::get_if<Literal>(value->value))
return valueOfLiteral(*literal); return valueOfLiteral(*literal);
return nullopt; return std::nullopt;
} }
std::optional<pair<YulString, YulString>> DataFlowAnalyzer::isSimpleStore( std::optional<std::pair<YulString, YulString>> DataFlowAnalyzer::isSimpleStore(
StoreLoadLocation _location, StoreLoadLocation _location,
ExpressionStatement const& _statement ExpressionStatement const& _statement
) const ) const
{ {
if (FunctionCall const* funCall = get_if<FunctionCall>(&_statement.expression)) if (FunctionCall const* funCall = std::get_if<FunctionCall>(&_statement.expression))
if (funCall->functionName.name == m_storeFunctionName[static_cast<unsigned>(_location)]) if (funCall->functionName.name == m_storeFunctionName[static_cast<unsigned>(_location)])
if (Identifier const* key = std::get_if<Identifier>(&funCall->arguments.front())) if (Identifier const* key = std::get_if<Identifier>(&funCall->arguments.front()))
if (Identifier const* value = std::get_if<Identifier>(&funCall->arguments.back())) if (Identifier const* value = std::get_if<Identifier>(&funCall->arguments.back()))
return make_pair(key->name, value->name); return std::make_pair(key->name, value->name);
return {}; return {};
} }
@ -436,21 +435,21 @@ std::optional<YulString> DataFlowAnalyzer::isSimpleLoad(
Expression const& _expression Expression const& _expression
) const ) const
{ {
if (FunctionCall const* funCall = get_if<FunctionCall>(&_expression)) if (FunctionCall const* funCall = std::get_if<FunctionCall>(&_expression))
if (funCall->functionName.name == m_loadFunctionName[static_cast<unsigned>(_location)]) if (funCall->functionName.name == m_loadFunctionName[static_cast<unsigned>(_location)])
if (Identifier const* key = std::get_if<Identifier>(&funCall->arguments.front())) if (Identifier const* key = std::get_if<Identifier>(&funCall->arguments.front()))
return key->name; return key->name;
return {}; return {};
} }
optional<pair<YulString, YulString>> DataFlowAnalyzer::isKeccak(Expression const& _expression) const std::optional<std::pair<YulString, YulString>> DataFlowAnalyzer::isKeccak(Expression const& _expression) const
{ {
if (FunctionCall const* funCall = get_if<FunctionCall>(&_expression)) if (FunctionCall const* funCall = std::get_if<FunctionCall>(&_expression))
if (funCall->functionName.name == m_dialect.hashFunction({})) if (funCall->functionName.name == m_dialect.hashFunction({}))
if (Identifier const* start = std::get_if<Identifier>(&funCall->arguments.at(0))) if (Identifier const* start = std::get_if<Identifier>(&funCall->arguments.at(0)))
if (Identifier const* length = std::get_if<Identifier>(&funCall->arguments.at(1))) if (Identifier const* length = std::get_if<Identifier>(&funCall->arguments.at(1)))
return make_pair(start->name, length->name); return std::make_pair(start->name, length->name);
return nullopt; return std::nullopt;
} }
void DataFlowAnalyzer::joinKnowledge(Environment const& _olderEnvironment) void DataFlowAnalyzer::joinKnowledge(Environment const& _olderEnvironment)

View File

@ -30,7 +30,6 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::yul; using namespace solidity::yul;
@ -54,7 +53,7 @@ void DeadCodeEliminator::operator()(Block& _block)
{ {
TerminationFinder::ControlFlow controlFlowChange; TerminationFinder::ControlFlow controlFlowChange;
size_t index; size_t index;
tie(controlFlowChange, index) = TerminationFinder{m_dialect, &m_functionSideEffects}.firstUnconditionalControlFlowChange(_block.statements); std::tie(controlFlowChange, index) = TerminationFinder{m_dialect, &m_functionSideEffects}.firstUnconditionalControlFlowChange(_block.statements);
// Erase everything after the terminating statement that is not a function definition. // Erase everything after the terminating statement that is not a function definition.
if (controlFlowChange != TerminationFinder::ControlFlow::FlowOut && index != std::numeric_limits<size_t>::max()) if (controlFlowChange != TerminationFinder::ControlFlow::FlowOut && index != std::numeric_limits<size_t>::max())
@ -62,7 +61,7 @@ void DeadCodeEliminator::operator()(Block& _block)
remove_if( remove_if(
_block.statements.begin() + static_cast<ptrdiff_t>(index) + 1, _block.statements.begin() + static_cast<ptrdiff_t>(index) + 1,
_block.statements.end(), _block.statements.end(),
[] (Statement const& _s) { return !holds_alternative<yul::FunctionDefinition>(_s); } [] (Statement const& _s) { return !std::holds_alternative<yul::FunctionDefinition>(_s); }
), ),
_block.statements.end() _block.statements.end()
); );

View File

@ -26,7 +26,6 @@
#include <libyul/Exceptions.h> #include <libyul/Exceptions.h>
#include <libyul/Scope.h> #include <libyul/Scope.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;

View File

@ -28,7 +28,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
#include <libyul/Utilities.h> #include <libyul/Utilities.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -50,17 +49,17 @@ void EqualStoreEliminator::visit(Statement& _statement)
{ {
// No need to consider potential changes through complex arguments since // No need to consider potential changes through complex arguments since
// isSimpleStore only returns something if the arguments are identifiers. // isSimpleStore only returns something if the arguments are identifiers.
if (ExpressionStatement const* expression = get_if<ExpressionStatement>(&_statement)) if (ExpressionStatement const* expression = std::get_if<ExpressionStatement>(&_statement))
{ {
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, *expression)) if (auto vars = isSimpleStore(StoreLoadLocation::Storage, *expression))
{ {
if (optional<YulString> currentValue = storageValue(vars->first)) if (std::optional<YulString> currentValue = storageValue(vars->first))
if (*currentValue == vars->second) if (*currentValue == vars->second)
m_pendingRemovals.insert(&_statement); m_pendingRemovals.insert(&_statement);
} }
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, *expression)) else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, *expression))
{ {
if (optional<YulString> currentValue = memoryValue(vars->first)) if (std::optional<YulString> currentValue = memoryValue(vars->first))
if (*currentValue == vars->second) if (*currentValue == vars->second)
m_pendingRemovals.insert(&_statement); m_pendingRemovals.insert(&_statement);
} }

View File

@ -23,7 +23,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;

View File

@ -25,7 +25,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
#include <libyul/optimiser/Metrics.h> #include <libyul/optimiser/Metrics.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;

View File

@ -30,7 +30,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -50,14 +49,14 @@ void ExpressionInliner::operator()(FunctionDefinition& _fun)
void ExpressionInliner::visit(Expression& _expression) void ExpressionInliner::visit(Expression& _expression)
{ {
ASTModifier::visit(_expression); ASTModifier::visit(_expression);
if (holds_alternative<FunctionCall>(_expression)) if (std::holds_alternative<FunctionCall>(_expression))
{ {
FunctionCall& funCall = std::get<FunctionCall>(_expression); FunctionCall& funCall = std::get<FunctionCall>(_expression);
if (!m_inlinableFunctions.count(funCall.functionName.name)) if (!m_inlinableFunctions.count(funCall.functionName.name))
return; return;
FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name); FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name);
map<YulString, Expression const*> substitutions; std::map<YulString, Expression const*> substitutions;
for (size_t i = 0; i < funCall.arguments.size(); i++) for (size_t i = 0; i < funCall.arguments.size(); i++)
{ {
Expression const& arg = funCall.arguments[i]; Expression const& arg = funCall.arguments[i];

View File

@ -34,7 +34,6 @@
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -66,7 +65,7 @@ void ExpressionJoiner::operator()(Block& _block)
void ExpressionJoiner::visit(Expression& _e) void ExpressionJoiner::visit(Expression& _e)
{ {
if (holds_alternative<Identifier>(_e)) if (std::holds_alternative<Identifier>(_e))
{ {
Identifier const& identifier = std::get<Identifier>(_e); Identifier const& identifier = std::get<Identifier>(_e);
if (isLatestStatementVarDeclJoinable(identifier)) if (isLatestStatementVarDeclJoinable(identifier))
@ -89,7 +88,7 @@ ExpressionJoiner::ExpressionJoiner(Block& _ast)
m_references = VariableReferencesCounter::countReferences(_ast); m_references = VariableReferencesCounter::countReferences(_ast);
} }
void ExpressionJoiner::handleArguments(vector<Expression>& _arguments) void ExpressionJoiner::handleArguments(std::vector<Expression>& _arguments)
{ {
// We have to fill from left to right, but we can only // We have to fill from left to right, but we can only
// fill if everything to the right is just an identifier // fill if everything to the right is just an identifier
@ -101,7 +100,7 @@ void ExpressionJoiner::handleArguments(vector<Expression>& _arguments)
for (Expression const& arg: _arguments | ranges::views::reverse) for (Expression const& arg: _arguments | ranges::views::reverse)
{ {
--i; --i;
if (!holds_alternative<Identifier>(arg) && !holds_alternative<Literal>(arg)) if (!std::holds_alternative<Identifier>(arg) && !std::holds_alternative<Literal>(arg))
break; break;
} }
// i points to the last element that is neither an identifier nor a literal, // i points to the last element that is neither an identifier nor a literal,
@ -124,7 +123,7 @@ void ExpressionJoiner::decrementLatestStatementPointer()
void ExpressionJoiner::resetLatestStatementPointer() void ExpressionJoiner::resetLatestStatementPointer()
{ {
m_currentBlock = nullptr; m_currentBlock = nullptr;
m_latestStatementInBlock = numeric_limits<size_t>::max(); m_latestStatementInBlock = std::numeric_limits<size_t>::max();
} }
Statement* ExpressionJoiner::latestStatement() Statement* ExpressionJoiner::latestStatement()
@ -138,7 +137,7 @@ Statement* ExpressionJoiner::latestStatement()
bool ExpressionJoiner::isLatestStatementVarDeclJoinable(Identifier const& _identifier) bool ExpressionJoiner::isLatestStatementVarDeclJoinable(Identifier const& _identifier)
{ {
Statement const* statement = latestStatement(); Statement const* statement = latestStatement();
if (!statement || !holds_alternative<VariableDeclaration>(*statement)) if (!statement || !std::holds_alternative<VariableDeclaration>(*statement))
return false; return false;
VariableDeclaration const& varDecl = std::get<VariableDeclaration>(*statement); VariableDeclaration const& varDecl = std::get<VariableDeclaration>(*statement);
if (varDecl.variables.size() != 1 || !varDecl.value) if (varDecl.variables.size() != 1 || !varDecl.value)

View File

@ -29,7 +29,6 @@
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -49,8 +48,8 @@ void ExpressionSimplifier::visit(Expression& _expression)
)) ))
_expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect)); _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect));
if (auto* functionCall = get_if<FunctionCall>(&_expression)) if (auto* functionCall = std::get_if<FunctionCall>(&_expression))
if (optional<evmasm::Instruction> instruction = toEVMInstruction(m_dialect, functionCall->functionName.name)) if (std::optional<evmasm::Instruction> instruction = toEVMInstruction(m_dialect, functionCall->functionName.name))
for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction)) for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction))
if (op.startParameter && op.lengthParameter) if (op.startParameter && op.lengthParameter)
{ {
@ -59,7 +58,7 @@ void ExpressionSimplifier::visit(Expression& _expression)
if ( if (
knownToBeZero(lengthArgument) && knownToBeZero(lengthArgument) &&
!knownToBeZero(startArgument) && !knownToBeZero(startArgument) &&
!holds_alternative<FunctionCall>(startArgument) !std::holds_alternative<FunctionCall>(startArgument)
) )
startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, "0"_yulstring, {}}; startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, "0"_yulstring, {}};
} }
@ -67,9 +66,9 @@ void ExpressionSimplifier::visit(Expression& _expression)
bool ExpressionSimplifier::knownToBeZero(Expression const& _expression) const bool ExpressionSimplifier::knownToBeZero(Expression const& _expression) const
{ {
if (auto const* literal = get_if<Literal>(&_expression)) if (auto const* literal = std::get_if<Literal>(&_expression))
return valueOfLiteral(*literal) == 0; return valueOfLiteral(*literal) == 0;
else if (auto const* identifier = get_if<Identifier>(&_expression)) else if (auto const* identifier = std::get_if<Identifier>(&_expression))
return valueOfIdentifier(identifier->name) == 0; return valueOfIdentifier(identifier->name) == 0;
else else
return false; return false;

View File

@ -30,7 +30,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -75,11 +74,11 @@ void ExpressionSplitter::operator()(ForLoop& _loop)
void ExpressionSplitter::operator()(Block& _block) void ExpressionSplitter::operator()(Block& _block)
{ {
vector<Statement> saved; std::vector<Statement> saved;
swap(saved, m_statementsToPrefix); swap(saved, m_statementsToPrefix);
function<std::optional<vector<Statement>>(Statement&)> f = std::function<std::optional<std::vector<Statement>>(Statement&)> f =
[&](Statement& _statement) -> std::optional<vector<Statement>> { [&](Statement& _statement) -> std::optional<std::vector<Statement>> {
m_statementsToPrefix.clear(); m_statementsToPrefix.clear();
visit(_statement); visit(_statement);
if (m_statementsToPrefix.empty()) if (m_statementsToPrefix.empty())
@ -94,18 +93,18 @@ void ExpressionSplitter::operator()(Block& _block)
void ExpressionSplitter::outlineExpression(Expression& _expr) void ExpressionSplitter::outlineExpression(Expression& _expr)
{ {
if (holds_alternative<Identifier>(_expr)) if (std::holds_alternative<Identifier>(_expr))
return; return;
visit(_expr); visit(_expr);
shared_ptr<DebugData const> debugData = debugDataOf(_expr); std::shared_ptr<DebugData const> debugData = debugDataOf(_expr);
YulString var = m_nameDispenser.newName({}); YulString var = m_nameDispenser.newName({});
YulString type = m_typeInfo.typeOf(_expr); YulString type = m_typeInfo.typeOf(_expr);
m_statementsToPrefix.emplace_back(VariableDeclaration{ m_statementsToPrefix.emplace_back(VariableDeclaration{
debugData, debugData,
{{TypedName{debugData, var, type}}}, {{TypedName{debugData, var, type}}},
make_unique<Expression>(std::move(_expr)) std::make_unique<Expression>(std::move(_expr))
}); });
_expr = Identifier{debugData, var}; _expr = Identifier{debugData, var};
m_typeInfo.setVariableType(var, type); m_typeInfo.setVariableType(var, type);

View File

@ -22,7 +22,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -35,17 +34,17 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop)
{ {
if ( if (
m_dialect.booleanNegationFunction() && m_dialect.booleanNegationFunction() &&
!holds_alternative<Literal>(*_forLoop.condition) && !std::holds_alternative<Literal>(*_forLoop.condition) &&
!holds_alternative<Identifier>(*_forLoop.condition) !std::holds_alternative<Identifier>(*_forLoop.condition)
) )
{ {
shared_ptr<DebugData const> debugData = debugDataOf(*_forLoop.condition); std::shared_ptr<DebugData const> debugData = debugDataOf(*_forLoop.condition);
_forLoop.body.statements.emplace( _forLoop.body.statements.emplace(
begin(_forLoop.body.statements), begin(_forLoop.body.statements),
If { If {
debugData, debugData,
make_unique<Expression>( std::make_unique<Expression>(
FunctionCall { FunctionCall {
debugData, debugData,
{debugData, m_dialect.booleanNegationFunction()->name}, {debugData, m_dialect.booleanNegationFunction()->name},
@ -55,7 +54,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop)
Block {debugData, util::make_vector<Statement>(Break{{}})} Block {debugData, util::make_vector<Statement>(Break{{}})}
} }
); );
_forLoop.condition = make_unique<Expression>( _forLoop.condition = std::make_unique<Expression>(
Literal { Literal {
debugData, debugData,
LiteralKind::Boolean, LiteralKind::Boolean,

View File

@ -23,7 +23,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -38,32 +37,32 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
if ( if (
!m_dialect.booleanNegationFunction() || !m_dialect.booleanNegationFunction() ||
!holds_alternative<Literal>(*_forLoop.condition) || !std::holds_alternative<Literal>(*_forLoop.condition) ||
valueOfLiteral(std::get<Literal>(*_forLoop.condition)) == u256(0) || valueOfLiteral(std::get<Literal>(*_forLoop.condition)) == u256(0) ||
_forLoop.body.statements.empty() || _forLoop.body.statements.empty() ||
!holds_alternative<If>(_forLoop.body.statements.front()) !std::holds_alternative<If>(_forLoop.body.statements.front())
) )
return; return;
If& firstStatement = std::get<If>(_forLoop.body.statements.front()); If& firstStatement = std::get<If>(_forLoop.body.statements.front());
if ( if (
firstStatement.body.statements.empty() || firstStatement.body.statements.empty() ||
!holds_alternative<Break>(firstStatement.body.statements.front()) !std::holds_alternative<Break>(firstStatement.body.statements.front())
) )
return; return;
if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable())
return; return;
YulString iszero = m_dialect.booleanNegationFunction()->name; YulString iszero = m_dialect.booleanNegationFunction()->name;
shared_ptr<DebugData const> debugData = debugDataOf(*firstStatement.condition); std::shared_ptr<DebugData const> debugData = debugDataOf(*firstStatement.condition);
if ( if (
holds_alternative<FunctionCall>(*firstStatement.condition) && std::holds_alternative<FunctionCall>(*firstStatement.condition) &&
std::get<FunctionCall>(*firstStatement.condition).functionName.name == iszero std::get<FunctionCall>(*firstStatement.condition).functionName.name == iszero
) )
_forLoop.condition = make_unique<Expression>(std::move(std::get<FunctionCall>(*firstStatement.condition).arguments.front())); _forLoop.condition = std::make_unique<Expression>(std::move(std::get<FunctionCall>(*firstStatement.condition).arguments.front()));
else else
_forLoop.condition = make_unique<Expression>(FunctionCall{ _forLoop.condition = std::make_unique<Expression>(FunctionCall{
debugData, debugData,
Identifier{debugData, iszero}, Identifier{debugData, iszero},
util::make_vector<Expression>( util::make_vector<Expression>(

View File

@ -22,7 +22,6 @@
#include <functional> #include <functional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -30,15 +29,15 @@ void ForLoopInitRewriter::operator()(Block& _block)
{ {
util::iterateReplacing( util::iterateReplacing(
_block.statements, _block.statements,
[&](Statement& _stmt) -> std::optional<vector<Statement>> [&](Statement& _stmt) -> std::optional<std::vector<Statement>>
{ {
if (holds_alternative<ForLoop>(_stmt)) if (std::holds_alternative<ForLoop>(_stmt))
{ {
auto& forLoop = std::get<ForLoop>(_stmt); auto& forLoop = std::get<ForLoop>(_stmt);
(*this)(forLoop.pre); (*this)(forLoop.pre);
(*this)(forLoop.body); (*this)(forLoop.body);
(*this)(forLoop.post); (*this)(forLoop.post);
vector<Statement> rewrite; std::vector<Statement> rewrite;
swap(rewrite, forLoop.pre.statements); swap(rewrite, forLoop.pre.statements);
rewrite.emplace_back(std::move(forLoop)); rewrite.emplace_back(std::move(forLoop));
return { std::move(rewrite) }; return { std::move(rewrite) };

View File

@ -41,7 +41,6 @@
#include <range/v3/view/reverse.hpp> #include <range/v3/view/reverse.hpp>
#include <range/v3/view/zip.hpp> #include <range/v3/view/zip.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -63,15 +62,15 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const&
SSAValueTracker tracker; SSAValueTracker tracker;
tracker(m_ast); tracker(m_ast);
for (auto const& ssaValue: tracker.values()) for (auto const& ssaValue: tracker.values())
if (ssaValue.second && holds_alternative<Literal>(*ssaValue.second)) if (ssaValue.second && std::holds_alternative<Literal>(*ssaValue.second))
m_constants.emplace(ssaValue.first); m_constants.emplace(ssaValue.first);
// Store size of global statements. // Store size of global statements.
m_functionSizes[YulString{}] = CodeSize::codeSize(_ast); m_functionSizes[YulString{}] = CodeSize::codeSize(_ast);
map<YulString, size_t> references = ReferencesCounter::countReferences(m_ast); std::map<YulString, size_t> references = ReferencesCounter::countReferences(m_ast);
for (auto& statement: m_ast.statements) for (auto& statement: m_ast.statements)
{ {
if (!holds_alternative<FunctionDefinition>(statement)) if (!std::holds_alternative<FunctionDefinition>(statement))
continue; continue;
FunctionDefinition& fun = std::get<FunctionDefinition>(statement); FunctionDefinition& fun = std::get<FunctionDefinition>(statement);
m_functions[fun.name] = &fun; m_functions[fun.name] = &fun;
@ -84,7 +83,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const&
} }
// Check for memory guard. // Check for memory guard.
vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run( std::vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run(
_ast, _ast,
"memoryguard"_yulstring "memoryguard"_yulstring
); );
@ -105,10 +104,10 @@ void FullInliner::run(Pass _pass)
// function name) order. // function name) order.
// We use stable_sort below to keep the inlining order of two functions // We use stable_sort below to keep the inlining order of two functions
// with the same depth. // with the same depth.
map<YulString, size_t> depths = callDepths(); std::map<YulString, size_t> depths = callDepths();
vector<FunctionDefinition*> functions; std::vector<FunctionDefinition*> functions;
for (auto& statement: m_ast.statements) for (auto& statement: m_ast.statements)
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
functions.emplace_back(&std::get<FunctionDefinition>(statement)); functions.emplace_back(&std::get<FunctionDefinition>(statement));
std::stable_sort(functions.begin(), functions.end(), [depths]( std::stable_sort(functions.begin(), functions.end(), [depths](
FunctionDefinition const* _a, FunctionDefinition const* _a,
@ -123,11 +122,11 @@ void FullInliner::run(Pass _pass)
} }
for (auto& statement: m_ast.statements) for (auto& statement: m_ast.statements)
if (holds_alternative<Block>(statement)) if (std::holds_alternative<Block>(statement))
handleBlock({}, std::get<Block>(statement)); handleBlock({}, std::get<Block>(statement));
} }
map<YulString, size_t> FullInliner::callDepths() const std::map<YulString, size_t> FullInliner::callDepths() const
{ {
CallGraph cg = CallGraphGenerator::callGraph(m_ast); CallGraph cg = CallGraphGenerator::callGraph(m_ast);
cg.functionCalls.erase(""_yulstring); cg.functionCalls.erase(""_yulstring);
@ -140,12 +139,12 @@ map<YulString, size_t> FullInliner::callDepths() const
else else
++it; ++it;
map<YulString, size_t> depths; std::map<YulString, size_t> depths;
size_t currentDepth = 0; size_t currentDepth = 0;
while (true) while (true)
{ {
vector<YulString> removed; std::vector<YulString> removed;
for (auto it = cg.functionCalls.begin(); it != cg.functionCalls.end();) for (auto it = cg.functionCalls.begin(); it != cg.functionCalls.end();)
{ {
auto const& [fun, callees] = *it; auto const& [fun, callees] = *it;
@ -192,7 +191,7 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
// No inlining of calls where argument expressions may have side-effects. // No inlining of calls where argument expressions may have side-effects.
// To avoid running into this, make sure that ExpressionSplitter runs before FullInliner. // To avoid running into this, make sure that ExpressionSplitter runs before FullInliner.
for (auto const& argument: _funCall.arguments) for (auto const& argument: _funCall.arguments)
if (!holds_alternative<Literal>(argument) && !holds_alternative<Identifier>(argument)) if (!std::holds_alternative<Literal>(argument) && !std::holds_alternative<Identifier>(argument))
return false; return false;
// Inline really, really tiny functions // Inline really, really tiny functions
@ -226,8 +225,8 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
// Constant arguments might provide a means for further optimization, so they cause a bonus. // Constant arguments might provide a means for further optimization, so they cause a bonus.
bool constantArg = false; bool constantArg = false;
for (auto const& argument: _funCall.arguments) for (auto const& argument: _funCall.arguments)
if (holds_alternative<Literal>(argument) || ( if (std::holds_alternative<Literal>(argument) || (
holds_alternative<Identifier>(argument) && std::holds_alternative<Identifier>(argument) &&
m_constants.count(std::get<Identifier>(argument).name) m_constants.count(std::get<Identifier>(argument).name)
)) ))
{ {
@ -255,20 +254,20 @@ void FullInliner::handleBlock(YulString _currentFunctionName, Block& _block)
bool FullInliner::recursive(FunctionDefinition const& _fun) const bool FullInliner::recursive(FunctionDefinition const& _fun) const
{ {
map<YulString, size_t> references = ReferencesCounter::countReferences(_fun); std::map<YulString, size_t> references = ReferencesCounter::countReferences(_fun);
return references[_fun.name] > 0; return references[_fun.name] > 0;
} }
void InlineModifier::operator()(Block& _block) void InlineModifier::operator()(Block& _block)
{ {
function<std::optional<vector<Statement>>(Statement&)> f = [&](Statement& _statement) -> std::optional<vector<Statement>> { std::function<std::optional<std::vector<Statement>>(Statement&)> f = [&](Statement& _statement) -> std::optional<std::vector<Statement>> {
visit(_statement); visit(_statement);
return tryInlineStatement(_statement); return tryInlineStatement(_statement);
}; };
util::iterateReplacing(_block.statements, f); util::iterateReplacing(_block.statements, f);
} }
std::optional<vector<Statement>> InlineModifier::tryInlineStatement(Statement& _statement) std::optional<std::vector<Statement>> InlineModifier::tryInlineStatement(Statement& _statement)
{ {
// Only inline for expression statements, assignments and variable declarations. // Only inline for expression statements, assignments and variable declarations.
Expression* e = std::visit(util::GenericVisitor{ Expression* e = std::visit(util::GenericVisitor{
@ -290,10 +289,10 @@ std::optional<vector<Statement>> InlineModifier::tryInlineStatement(Statement& _
return {}; return {};
} }
vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall) std::vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall)
{ {
vector<Statement> newStatements; std::vector<Statement> newStatements;
map<YulString, YulString> variableReplacements; std::map<YulString, YulString> variableReplacements;
FunctionDefinition* function = m_driver.function(_funCall.functionName.name); FunctionDefinition* function = m_driver.function(_funCall.functionName.name);
assertThrow(!!function, OptimizerException, "Attempt to inline invalid function."); assertThrow(!!function, OptimizerException, "Attempt to inline invalid function.");
@ -307,9 +306,9 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
variableReplacements[_existingVariable.name] = newName; variableReplacements[_existingVariable.name] = newName;
VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName, _existingVariable.type}}, {}}; VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName, _existingVariable.type}}, {}};
if (_value) if (_value)
varDecl.value = make_unique<Expression>(std::move(*_value)); varDecl.value = std::make_unique<Expression>(std::move(*_value));
else else
varDecl.value = make_unique<Expression>(m_dialect.zeroLiteralForType(varDecl.variables.front().type)); varDecl.value = std::make_unique<Expression>(m_dialect.zeroLiteralForType(varDecl.variables.front().type));
newStatements.emplace_back(std::move(varDecl)); newStatements.emplace_back(std::move(varDecl));
}; };
@ -329,7 +328,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
newStatements.emplace_back(Assignment{ newStatements.emplace_back(Assignment{
_assignment.debugData, _assignment.debugData,
{_assignment.variableNames[i]}, {_assignment.variableNames[i]},
make_unique<Expression>(Identifier{ std::make_unique<Expression>(Identifier{
_assignment.debugData, _assignment.debugData,
variableReplacements.at(function->returnVariables[i].name) variableReplacements.at(function->returnVariables[i].name)
}) })
@ -341,7 +340,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
newStatements.emplace_back(VariableDeclaration{ newStatements.emplace_back(VariableDeclaration{
_varDecl.debugData, _varDecl.debugData,
{std::move(_varDecl.variables[i])}, {std::move(_varDecl.variables[i])},
make_unique<Expression>(Identifier{ std::make_unique<Expression>(Identifier{
_varDecl.debugData, _varDecl.debugData,
variableReplacements.at(function->returnVariables[i].name) variableReplacements.at(function->returnVariables[i].name)
}) })

View File

@ -18,11 +18,10 @@
#include <libyul/optimiser/FunctionCallFinder.h> #include <libyul/optimiser/FunctionCallFinder.h>
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
vector<FunctionCall*> FunctionCallFinder::run(Block& _block, YulString _functionName) std::vector<FunctionCall*> FunctionCallFinder::run(Block& _block, YulString _functionName)
{ {
FunctionCallFinder functionCallFinder(_functionName); FunctionCallFinder functionCallFinder(_functionName);
functionCallFinder(_block); functionCallFinder(_block);

View File

@ -24,7 +24,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -34,12 +33,12 @@ void FunctionGrouper::operator()(Block& _block)
if (alreadyGrouped(_block)) if (alreadyGrouped(_block))
return; return;
vector<Statement> reordered; std::vector<Statement> reordered;
reordered.emplace_back(Block{_block.debugData, {}}); reordered.emplace_back(Block{_block.debugData, {}});
for (auto&& statement: _block.statements) for (auto&& statement: _block.statements)
{ {
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
reordered.emplace_back(std::move(statement)); reordered.emplace_back(std::move(statement));
else else
std::get<Block>(reordered.front()).statements.emplace_back(std::move(statement)); std::get<Block>(reordered.front()).statements.emplace_back(std::move(statement));
@ -51,10 +50,10 @@ bool FunctionGrouper::alreadyGrouped(Block const& _block)
{ {
if (_block.statements.empty()) if (_block.statements.empty())
return false; return false;
if (!holds_alternative<Block>(_block.statements.front())) if (!std::holds_alternative<Block>(_block.statements.front()))
return false; return false;
for (size_t i = 1; i < _block.statements.size(); ++i) for (size_t i = 1; i < _block.statements.size(); ++i)
if (!holds_alternative<FunctionDefinition>(_block.statements.at(i))) if (!std::holds_alternative<FunctionDefinition>(_block.statements.at(i)))
return false; return false;
return true; return true;
} }

View File

@ -27,7 +27,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -38,7 +37,7 @@ void FunctionHoister::operator()(Block& _block)
for (auto&& statement: _block.statements) for (auto&& statement: _block.statements)
{ {
std::visit(*this, statement); std::visit(*this, statement);
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
{ {
m_functions.emplace_back(std::move(statement)); m_functions.emplace_back(std::move(statement));
statement = Block{_block.debugData, {}}; statement = Block{_block.debugData, {}};

View File

@ -32,7 +32,6 @@
#include <variant> #include <variant>
using namespace std;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::yul; using namespace solidity::yul;
@ -40,11 +39,11 @@ FunctionSpecializer::LiteralArguments FunctionSpecializer::specializableArgument
FunctionCall const& _f FunctionCall const& _f
) )
{ {
auto heuristic = [&](Expression const& _e) -> optional<Expression> auto heuristic = [&](Expression const& _e) -> std::optional<Expression>
{ {
if (holds_alternative<Literal>(_e)) if (std::holds_alternative<Literal>(_e))
return ASTCopier{}.translate(_e); return ASTCopier{}.translate(_e);
return nullopt; return std::nullopt;
}; };
return applyMap(_f.arguments, heuristic); return applyMap(_f.arguments, heuristic);
@ -68,7 +67,7 @@ void FunctionSpecializer::operator()(FunctionCall& _f)
YulString oldName = std::move(_f.functionName.name); YulString oldName = std::move(_f.functionName.name);
auto newName = m_nameDispenser.newName(oldName); auto newName = m_nameDispenser.newName(oldName);
m_oldToNewMap[oldName].emplace_back(make_pair(newName, arguments)); m_oldToNewMap[oldName].emplace_back(std::make_pair(newName, arguments));
_f.functionName.name = newName; _f.functionName.name = newName;
_f.arguments = util::filter( _f.arguments = util::filter(
@ -86,27 +85,27 @@ FunctionDefinition FunctionSpecializer::specialize(
{ {
yulAssert(_arguments.size() == _f.parameters.size(), ""); yulAssert(_arguments.size() == _f.parameters.size(), "");
map<YulString, YulString> translatedNames = applyMap( std::map<YulString, YulString> translatedNames = applyMap(
NameCollector{_f, NameCollector::OnlyVariables}.names(), NameCollector{_f, NameCollector::OnlyVariables}.names(),
[&](auto& _name) -> pair<YulString, YulString> [&](auto& _name) -> std::pair<YulString, YulString>
{ {
return make_pair(_name, m_nameDispenser.newName(_name)); return std::make_pair(_name, m_nameDispenser.newName(_name));
}, },
map<YulString, YulString>{} std::map<YulString, YulString>{}
); );
FunctionDefinition newFunction = get<FunctionDefinition>(FunctionCopier{translatedNames}(_f)); FunctionDefinition newFunction = std::get<FunctionDefinition>(FunctionCopier{translatedNames}(_f));
// Function parameters that will be specialized inside the body are converted into variable // Function parameters that will be specialized inside the body are converted into variable
// declarations. // declarations.
vector<Statement> missingVariableDeclarations; std::vector<Statement> missingVariableDeclarations;
for (auto&& [index, argument]: _arguments | ranges::views::enumerate) for (auto&& [index, argument]: _arguments | ranges::views::enumerate)
if (argument) if (argument)
missingVariableDeclarations.emplace_back( missingVariableDeclarations.emplace_back(
VariableDeclaration{ VariableDeclaration{
_f.debugData, _f.debugData,
vector<TypedName>{newFunction.parameters[index]}, std::vector<TypedName>{newFunction.parameters[index]},
make_unique<Expression>(std::move(*argument)) std::make_unique<Expression>(std::move(*argument))
} }
); );
@ -134,15 +133,15 @@ void FunctionSpecializer::run(OptimiserStepContext& _context, Block& _ast)
}; };
f(_ast); f(_ast);
iterateReplacing(_ast.statements, [&](Statement& _s) -> optional<vector<Statement>> iterateReplacing(_ast.statements, [&](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
if (holds_alternative<FunctionDefinition>(_s)) if (std::holds_alternative<FunctionDefinition>(_s))
{ {
auto& functionDefinition = get<FunctionDefinition>(_s); auto& functionDefinition = std::get<FunctionDefinition>(_s);
if (f.m_oldToNewMap.count(functionDefinition.name)) if (f.m_oldToNewMap.count(functionDefinition.name))
{ {
vector<Statement> out = applyMap( std::vector<Statement> out = applyMap(
f.m_oldToNewMap.at(functionDefinition.name), f.m_oldToNewMap.at(functionDefinition.name),
[&](auto& _p) -> Statement [&](auto& _p) -> Statement
{ {
@ -153,6 +152,6 @@ void FunctionSpecializer::run(OptimiserStepContext& _context, Block& _ast)
} }
} }
return nullopt; return std::nullopt;
}); });
} }

View File

@ -24,7 +24,6 @@
#include <libyul/optimiser/OptimizerUtilities.h> #include <libyul/optimiser/OptimizerUtilities.h>
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -46,7 +45,7 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu
{ {
YulString retVariable = _function.returnVariables.front().name; YulString retVariable = _function.returnVariables.front().name;
Statement const& bodyStatement = _function.body.statements.front(); Statement const& bodyStatement = _function.body.statements.front();
if (holds_alternative<Assignment>(bodyStatement)) if (std::holds_alternative<Assignment>(bodyStatement))
{ {
Assignment const& assignment = std::get<Assignment>(bodyStatement); Assignment const& assignment = std::get<Assignment>(bodyStatement);
if (assignment.variableNames.size() == 1 && assignment.variableNames.front().name == retVariable) if (assignment.variableNames.size() == 1 && assignment.variableNames.front().name == retVariable)
@ -57,7 +56,7 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu
// would not be valid here if we were searching inside a functionally inlinable // would not be valid here if we were searching inside a functionally inlinable
// function body. // function body.
assertThrow(m_disallowedIdentifiers.empty() && !m_foundDisallowedIdentifier, OptimizerException, ""); assertThrow(m_disallowedIdentifiers.empty() && !m_foundDisallowedIdentifier, OptimizerException, "");
m_disallowedIdentifiers = set<YulString>{retVariable, _function.name}; m_disallowedIdentifiers = std::set<YulString>{retVariable, _function.name};
std::visit(*this, *assignment.value); std::visit(*this, *assignment.value);
if (!m_foundDisallowedIdentifier) if (!m_foundDisallowedIdentifier)
m_inlinableFunctions[_function.name] = &_function; m_inlinableFunctions[_function.name] = &_function;

View File

@ -29,36 +29,35 @@
#include <variant> #include <variant>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
KnowledgeBase::KnowledgeBase(map<YulString, AssignedValue> const& _ssaValues): KnowledgeBase::KnowledgeBase(std::map<YulString, AssignedValue> const& _ssaValues):
m_valuesAreSSA(true), m_valuesAreSSA(true),
m_variableValues([_ssaValues](YulString _var) { return util::valueOrNullptr(_ssaValues, _var); }) m_variableValues([_ssaValues](YulString _var) { return util::valueOrNullptr(_ssaValues, _var); })
{} {}
bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b) bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b)
{ {
if (optional<u256> difference = differenceIfKnownConstant(_a, _b)) if (std::optional<u256> difference = differenceIfKnownConstant(_a, _b))
return difference != 0; return difference != 0;
return false; return false;
} }
optional<u256> KnowledgeBase::differenceIfKnownConstant(YulString _a, YulString _b) std::optional<u256> KnowledgeBase::differenceIfKnownConstant(YulString _a, YulString _b)
{ {
VariableOffset offA = explore(_a); VariableOffset offA = explore(_a);
VariableOffset offB = explore(_b); VariableOffset offB = explore(_b);
if (offA.reference == offB.reference) if (offA.reference == offB.reference)
return offA.offset - offB.offset; return offA.offset - offB.offset;
else else
return nullopt; return std::nullopt;
} }
bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b)
{ {
if (optional<u256> difference = differenceIfKnownConstant(_a, _b)) if (std::optional<u256> difference = differenceIfKnownConstant(_a, _b))
return difference >= 32 && difference <= u256(0) - 32; return difference >= 32 && difference <= u256(0) - 32;
return false; return false;
@ -69,19 +68,19 @@ bool KnowledgeBase::knownToBeZero(YulString _a)
return valueIfKnownConstant(_a) == 0; return valueIfKnownConstant(_a) == 0;
} }
optional<u256> KnowledgeBase::valueIfKnownConstant(YulString _a) std::optional<u256> KnowledgeBase::valueIfKnownConstant(YulString _a)
{ {
return explore(_a).absoluteValue(); return explore(_a).absoluteValue();
} }
optional<u256> KnowledgeBase::valueIfKnownConstant(Expression const& _expression) std::optional<u256> KnowledgeBase::valueIfKnownConstant(Expression const& _expression)
{ {
if (Identifier const* ident = get_if<Identifier>(&_expression)) if (Identifier const* ident = std::get_if<Identifier>(&_expression))
return valueIfKnownConstant(ident->name); return valueIfKnownConstant(ident->name);
else if (Literal const* lit = get_if<Literal>(&_expression)) else if (Literal const* lit = std::get_if<Literal>(&_expression))
return valueOfLiteral(*lit); return valueOfLiteral(*lit);
else else
return nullopt; return std::nullopt;
} }
KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var)
@ -105,24 +104,24 @@ KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var)
} }
if (value) if (value)
if (optional<VariableOffset> offset = explore(*value)) if (std::optional<VariableOffset> offset = explore(*value))
return setOffset(_var, *offset); return setOffset(_var, *offset);
return setOffset(_var, VariableOffset{_var, 0}); return setOffset(_var, VariableOffset{_var, 0});
} }
optional<KnowledgeBase::VariableOffset> KnowledgeBase::explore(Expression const& _value) std::optional<KnowledgeBase::VariableOffset> KnowledgeBase::explore(Expression const& _value)
{ {
if (Literal const* literal = get_if<Literal>(&_value)) if (Literal const* literal = std::get_if<Literal>(&_value))
return VariableOffset{YulString{}, valueOfLiteral(*literal)}; return VariableOffset{YulString{}, valueOfLiteral(*literal)};
else if (Identifier const* identifier = get_if<Identifier>(&_value)) else if (Identifier const* identifier = std::get_if<Identifier>(&_value))
return explore(identifier->name); return explore(identifier->name);
else if (FunctionCall const* f = get_if<FunctionCall>(&_value)) else if (FunctionCall const* f = std::get_if<FunctionCall>(&_value))
{ {
if (f->functionName.name == "add"_yulstring) if (f->functionName.name == "add"_yulstring)
{ {
if (optional<VariableOffset> a = explore(f->arguments[0])) if (std::optional<VariableOffset> a = explore(f->arguments[0]))
if (optional<VariableOffset> b = explore(f->arguments[1])) if (std::optional<VariableOffset> b = explore(f->arguments[1]))
{ {
u256 offset = a->offset + b->offset; u256 offset = a->offset + b->offset;
if (a->isAbsolute()) if (a->isAbsolute())
@ -134,8 +133,8 @@ optional<KnowledgeBase::VariableOffset> KnowledgeBase::explore(Expression const&
} }
} }
else if (f->functionName.name == "sub"_yulstring) else if (f->functionName.name == "sub"_yulstring)
if (optional<VariableOffset> a = explore(f->arguments[0])) if (std::optional<VariableOffset> a = explore(f->arguments[0]))
if (optional<VariableOffset> b = explore(f->arguments[1])) if (std::optional<VariableOffset> b = explore(f->arguments[1]))
{ {
u256 offset = a->offset - b->offset; u256 offset = a->offset - b->offset;
if (a->reference == b->reference) if (a->reference == b->reference)
@ -146,7 +145,7 @@ optional<KnowledgeBase::VariableOffset> KnowledgeBase::explore(Expression const&
} }
} }
return nullopt; return std::nullopt;
} }
Expression const* KnowledgeBase::valueOf(YulString _var) Expression const* KnowledgeBase::valueOf(YulString _var)
@ -175,7 +174,7 @@ void KnowledgeBase::reset(YulString _var)
m_groupMembers[offset->reference].erase(_var); m_groupMembers[offset->reference].erase(_var);
m_offsets.erase(_var); m_offsets.erase(_var);
} }
if (set<YulString>* group = util::valueOrNullptr(m_groupMembers, _var)) if (std::set<YulString>* group = util::valueOrNullptr(m_groupMembers, _var))
{ {
// _var was a representative, we might have to find a new one. // _var was a representative, we might have to find a new one.
if (!group->empty()) if (!group->empty())

View File

@ -36,7 +36,6 @@
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -65,8 +64,8 @@ void LoadResolver::visit(Expression& _e)
tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments);
else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction({})) else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction({}))
{ {
Identifier const* start = get_if<Identifier>(&funCall->arguments.at(0)); Identifier const* start = std::get_if<Identifier>(&funCall->arguments.at(0));
Identifier const* length = get_if<Identifier>(&funCall->arguments.at(1)); Identifier const* length = std::get_if<Identifier>(&funCall->arguments.at(1));
if (start && length) if (start && length)
if (auto const& value = keccakValue(start->name, length->name)) if (auto const& value = keccakValue(start->name, length->name))
if (inScope(*value)) if (inScope(*value))
@ -82,10 +81,10 @@ void LoadResolver::visit(Expression& _e)
void LoadResolver::tryResolve( void LoadResolver::tryResolve(
Expression& _e, Expression& _e,
StoreLoadLocation _location, StoreLoadLocation _location,
vector<Expression> const& _arguments std::vector<Expression> const& _arguments
) )
{ {
if (_arguments.empty() || !holds_alternative<Identifier>(_arguments.at(0))) if (_arguments.empty() || !std::holds_alternative<Identifier>(_arguments.at(0)))
return; return;
YulString key = std::get<Identifier>(_arguments.at(0)).name; YulString key = std::get<Identifier>(_arguments.at(0)).name;
@ -126,7 +125,7 @@ void LoadResolver::tryEvaluateKeccak(
{}, {},
LiteralKind::Number, LiteralKind::Number,
// a dummy 256-bit number to represent the Keccak256 hash. // a dummy 256-bit number to represent the Keccak256 hash.
YulString{numeric_limits<u256>::max().str()}, YulString{std::numeric_limits<u256>::max().str()},
{} {}
} }
); );
@ -138,11 +137,11 @@ void LoadResolver::tryEvaluateKeccak(
if (costOfLiteral > costOfKeccak) if (costOfLiteral > costOfKeccak)
return; return;
optional<YulString> value = memoryValue(memoryKey->name); std::optional<YulString> value = memoryValue(memoryKey->name);
if (value && inScope(*value)) if (value && inScope(*value))
{ {
optional<u256> memoryContent = valueOfIdentifier(*value); std::optional<u256> memoryContent = valueOfIdentifier(*value);
optional<u256> byteLength = valueOfIdentifier(length->name); std::optional<u256> byteLength = valueOfIdentifier(length->name);
if (memoryContent && byteLength && *byteLength <= 32) if (memoryContent && byteLength && *byteLength <= 32)
{ {
bytes contentAsBytes = toBigEndian(*memoryContent); bytes contentAsBytes = toBigEndian(*memoryContent);

View File

@ -27,16 +27,15 @@
#include <utility> #include <utility>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
void LoopInvariantCodeMotion::run(OptimiserStepContext& _context, Block& _ast) void LoopInvariantCodeMotion::run(OptimiserStepContext& _context, Block& _ast)
{ {
map<YulString, SideEffects> functionSideEffects = std::map<YulString, SideEffects> functionSideEffects =
SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)); SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast));
bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast); bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast);
set<YulString> ssaVars = SSAValueTracker::ssaVariables(_ast); std::set<YulString> ssaVars = SSAValueTracker::ssaVariables(_ast);
LoopInvariantCodeMotion{_context.dialect, ssaVars, functionSideEffects, containsMSize}(_ast); LoopInvariantCodeMotion{_context.dialect, ssaVars, functionSideEffects, containsMSize}(_ast);
} }
@ -44,11 +43,11 @@ void LoopInvariantCodeMotion::operator()(Block& _block)
{ {
util::iterateReplacing( util::iterateReplacing(
_block.statements, _block.statements,
[&](Statement& _s) -> optional<vector<Statement>> [&](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
visit(_s); visit(_s);
if (holds_alternative<ForLoop>(_s)) if (std::holds_alternative<ForLoop>(_s))
return rewriteLoop(get<ForLoop>(_s)); return rewriteLoop(std::get<ForLoop>(_s));
else else
return {}; return {};
} }
@ -57,7 +56,7 @@ void LoopInvariantCodeMotion::operator()(Block& _block)
bool LoopInvariantCodeMotion::canBePromoted( bool LoopInvariantCodeMotion::canBePromoted(
VariableDeclaration const& _varDecl, VariableDeclaration const& _varDecl,
set<YulString> const& _varsDefinedInCurrentScope, std::set<YulString> const& _varsDefinedInCurrentScope,
SideEffects const& _forLoopSideEffects SideEffects const& _forLoopSideEffects
) const ) const
{ {
@ -81,29 +80,29 @@ bool LoopInvariantCodeMotion::canBePromoted(
return true; return true;
} }
optional<vector<Statement>> LoopInvariantCodeMotion::rewriteLoop(ForLoop& _for) std::optional<std::vector<Statement>> LoopInvariantCodeMotion::rewriteLoop(ForLoop& _for)
{ {
assertThrow(_for.pre.statements.empty(), OptimizerException, ""); assertThrow(_for.pre.statements.empty(), OptimizerException, "");
auto forLoopSideEffects = auto forLoopSideEffects =
SideEffectsCollector{m_dialect, _for, &m_functionSideEffects}.sideEffects(); SideEffectsCollector{m_dialect, _for, &m_functionSideEffects}.sideEffects();
vector<Statement> replacement; std::vector<Statement> replacement;
for (Block* block: {&_for.post, &_for.body}) for (Block* block: {&_for.post, &_for.body})
{ {
set<YulString> varsDefinedInScope; std::set<YulString> varsDefinedInScope;
util::iterateReplacing( util::iterateReplacing(
block->statements, block->statements,
[&](Statement& _s) -> optional<vector<Statement>> [&](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
if (holds_alternative<VariableDeclaration>(_s)) if (std::holds_alternative<VariableDeclaration>(_s))
{ {
VariableDeclaration const& varDecl = std::get<VariableDeclaration>(_s); VariableDeclaration const& varDecl = std::get<VariableDeclaration>(_s);
if (canBePromoted(varDecl, varsDefinedInScope, forLoopSideEffects)) if (canBePromoted(varDecl, varsDefinedInScope, forLoopSideEffects))
{ {
replacement.emplace_back(std::move(_s)); replacement.emplace_back(std::move(_s));
// Do not add the variables declared here to varsDefinedInScope because we are moving them. // Do not add the variables declared here to varsDefinedInScope because we are moving them.
return vector<Statement>{}; return std::vector<Statement>{};
} }
for (auto const& var: varDecl.variables) for (auto const& var: varDecl.variables)
varsDefinedInScope.insert(var.name); varsDefinedInScope.insert(var.name);

View File

@ -30,34 +30,33 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
size_t CodeWeights::costOf(Statement const& _statement) const size_t CodeWeights::costOf(Statement const& _statement) const
{ {
if (holds_alternative<ExpressionStatement>(_statement)) if (std::holds_alternative<ExpressionStatement>(_statement))
return expressionStatementCost; return expressionStatementCost;
else if (holds_alternative<Assignment>(_statement)) else if (std::holds_alternative<Assignment>(_statement))
return assignmentCost; return assignmentCost;
else if (holds_alternative<VariableDeclaration>(_statement)) else if (std::holds_alternative<VariableDeclaration>(_statement))
return variableDeclarationCost; return variableDeclarationCost;
else if (holds_alternative<FunctionDefinition>(_statement)) else if (std::holds_alternative<FunctionDefinition>(_statement))
return functionDefinitionCost; return functionDefinitionCost;
else if (holds_alternative<If>(_statement)) else if (std::holds_alternative<If>(_statement))
return ifCost; return ifCost;
else if (holds_alternative<Switch>(_statement)) else if (std::holds_alternative<Switch>(_statement))
return switchCost + caseCost * std::get<Switch>(_statement).cases.size(); return switchCost + caseCost * std::get<Switch>(_statement).cases.size();
else if (holds_alternative<ForLoop>(_statement)) else if (std::holds_alternative<ForLoop>(_statement))
return forLoopCost; return forLoopCost;
else if (holds_alternative<Break>(_statement)) else if (std::holds_alternative<Break>(_statement))
return breakCost; return breakCost;
else if (holds_alternative<Continue>(_statement)) else if (std::holds_alternative<Continue>(_statement))
return continueCost; return continueCost;
else if (holds_alternative<Leave>(_statement)) else if (std::holds_alternative<Leave>(_statement))
return leaveCost; return leaveCost;
else if (holds_alternative<Block>(_statement)) else if (std::holds_alternative<Block>(_statement))
return blockCost; return blockCost;
else else
yulAssert(false, "If you add a new statement type, you must update CodeWeights."); yulAssert(false, "If you add a new statement type, you must update CodeWeights.");
@ -65,11 +64,11 @@ size_t CodeWeights::costOf(Statement const& _statement) const
size_t CodeWeights::costOf(Expression const& _expression) const size_t CodeWeights::costOf(Expression const& _expression) const
{ {
if (holds_alternative<FunctionCall>(_expression)) if (std::holds_alternative<FunctionCall>(_expression))
return functionCallCost; return functionCallCost;
else if (holds_alternative<Identifier>(_expression)) else if (std::holds_alternative<Identifier>(_expression))
return identifierCost; return identifierCost;
else if (Literal const* literal = get_if<Literal>(&_expression)) else if (Literal const* literal = std::get_if<Literal>(&_expression))
{ {
// Avoid strings because they could be longer than 32 bytes. // Avoid strings because they could be longer than 32 bytes.
if (literal->kind != LiteralKind::String && valueOfLiteral(*literal) == 0) if (literal->kind != LiteralKind::String && valueOfLiteral(*literal) == 0)
@ -112,7 +111,7 @@ size_t CodeSize::codeSizeIncludingFunctions(Block const& _block, CodeWeights con
void CodeSize::visit(Statement const& _statement) void CodeSize::visit(Statement const& _statement)
{ {
if (holds_alternative<FunctionDefinition>(_statement) && m_ignoreFunctions) if (std::holds_alternative<FunctionDefinition>(_statement) && m_ignoreFunctions)
return; return;
m_size += m_weights.costOf(_statement); m_size += m_weights.costOf(_statement);

View File

@ -23,7 +23,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -60,21 +59,21 @@ void ReferencesCounter::operator()(FunctionCall const& _funCall)
ASTWalker::operator()(_funCall); ASTWalker::operator()(_funCall);
} }
map<YulString, size_t> ReferencesCounter::countReferences(Block const& _block) std::map<YulString, size_t> ReferencesCounter::countReferences(Block const& _block)
{ {
ReferencesCounter counter; ReferencesCounter counter;
counter(_block); counter(_block);
return std::move(counter.m_references); return std::move(counter.m_references);
} }
map<YulString, size_t> ReferencesCounter::countReferences(FunctionDefinition const& _function) std::map<YulString, size_t> ReferencesCounter::countReferences(FunctionDefinition const& _function)
{ {
ReferencesCounter counter; ReferencesCounter counter;
counter(_function); counter(_function);
return std::move(counter.m_references); return std::move(counter.m_references);
} }
map<YulString, size_t> ReferencesCounter::countReferences(Expression const& _expression) std::map<YulString, size_t> ReferencesCounter::countReferences(Expression const& _expression)
{ {
ReferencesCounter counter; ReferencesCounter counter;
counter.visit(_expression); counter.visit(_expression);
@ -86,28 +85,28 @@ void VariableReferencesCounter::operator()(Identifier const& _identifier)
++m_references[_identifier.name]; ++m_references[_identifier.name];
} }
map<YulString, size_t> VariableReferencesCounter::countReferences(Block const& _block) std::map<YulString, size_t> VariableReferencesCounter::countReferences(Block const& _block)
{ {
VariableReferencesCounter counter; VariableReferencesCounter counter;
counter(_block); counter(_block);
return std::move(counter.m_references); return std::move(counter.m_references);
} }
map<YulString, size_t> VariableReferencesCounter::countReferences(FunctionDefinition const& _function) std::map<YulString, size_t> VariableReferencesCounter::countReferences(FunctionDefinition const& _function)
{ {
VariableReferencesCounter counter; VariableReferencesCounter counter;
counter(_function); counter(_function);
return std::move(counter.m_references); return std::move(counter.m_references);
} }
map<YulString, size_t> VariableReferencesCounter::countReferences(Expression const& _expression) std::map<YulString, size_t> VariableReferencesCounter::countReferences(Expression const& _expression)
{ {
VariableReferencesCounter counter; VariableReferencesCounter counter;
counter.visit(_expression); counter.visit(_expression);
return std::move(counter.m_references); return std::move(counter.m_references);
} }
map<YulString, size_t> VariableReferencesCounter::countReferences(Statement const& _statement) std::map<YulString, size_t> VariableReferencesCounter::countReferences(Statement const& _statement)
{ {
VariableReferencesCounter counter; VariableReferencesCounter counter;
counter.visit(_statement); counter.visit(_statement);
@ -149,7 +148,7 @@ std::set<YulString> solidity::yul::assignedVariableNames(Block const& _code)
return names; return names;
} }
map<YulString, FunctionDefinition const*> solidity::yul::allFunctionDefinitions(Block const& _block) std::map<YulString, FunctionDefinition const*> solidity::yul::allFunctionDefinitions(Block const& _block)
{ {
std::map<YulString, FunctionDefinition const*> result; std::map<YulString, FunctionDefinition const*> result;
forEach<FunctionDefinition const>(_block, [&](FunctionDefinition const& _function) { forEach<FunctionDefinition const>(_block, [&](FunctionDefinition const& _function) {

View File

@ -29,18 +29,17 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast, set<YulString> _reservedNames): NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast, std::set<YulString> _reservedNames):
NameDispenser(_dialect, NameCollector(_ast).names() + _reservedNames) NameDispenser(_dialect, NameCollector(_ast).names() + _reservedNames)
{ {
m_reservedNames = std::move(_reservedNames); m_reservedNames = std::move(_reservedNames);
} }
NameDispenser::NameDispenser(Dialect const& _dialect, set<YulString> _usedNames): NameDispenser::NameDispenser(Dialect const& _dialect, std::set<YulString> _usedNames):
m_dialect(_dialect), m_dialect(_dialect),
m_usedNames(std::move(_usedNames)) m_usedNames(std::move(_usedNames))
{ {
@ -52,7 +51,7 @@ YulString NameDispenser::newName(YulString _nameHint)
while (illegalName(name)) while (illegalName(name))
{ {
m_counter++; m_counter++;
name = YulString(_nameHint.str() + "_" + to_string(m_counter)); name = YulString(_nameHint.str() + "_" + std::to_string(m_counter));
} }
m_usedNames.emplace(name); m_usedNames.emplace(name);
return name; return name;

View File

@ -23,7 +23,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -64,7 +63,7 @@ void NameDisplacer::operator()(Block& _block)
// First replace all the names of function definitions // First replace all the names of function definitions
// because of scoping. // because of scoping.
for (auto& st: _block.statements) for (auto& st: _block.statements)
if (holds_alternative<FunctionDefinition>(st)) if (std::holds_alternative<FunctionDefinition>(st))
checkAndReplaceNew(std::get<FunctionDefinition>(st).name); checkAndReplaceNew(std::get<FunctionDefinition>(st).name);
ASTModifier::operator()(_block); ASTModifier::operator()(_block);

View File

@ -28,7 +28,6 @@
#include <regex> #include <regex>
using namespace solidity::yul; using namespace solidity::yul;
using namespace std;
NameSimplifier::NameSimplifier(OptimiserStepContext& _context, Block const& _ast): NameSimplifier::NameSimplifier(OptimiserStepContext& _context, Block const& _ast):
m_context(_context) m_context(_context)
@ -54,7 +53,7 @@ void NameSimplifier::operator()(VariableDeclaration& _varDecl)
ASTModifier::operator()(_varDecl); ASTModifier::operator()(_varDecl);
} }
void NameSimplifier::renameVariables(vector<TypedName>& _variables) void NameSimplifier::renameVariables(std::vector<TypedName>& _variables)
{ {
for (TypedName& typedName: _variables) for (TypedName& typedName: _variables)
translate(typedName.name); translate(typedName.name);
@ -78,31 +77,31 @@ void NameSimplifier::findSimplification(YulString const& _name)
if (m_translations.count(_name)) if (m_translations.count(_name))
return; return;
string name = _name.str(); std::string name = _name.str();
static auto replacements = vector<pair<regex, string>>{ static auto replacements = std::vector<std::pair<std::regex, std::string>>{
{regex("_\\$|\\$_"), "_"}, // remove type mangling delimiters {std::regex("_\\$|\\$_"), "_"}, // remove type mangling delimiters
{regex("_[0-9]+([^0-9a-fA-Fx])"), "$1"}, // removes AST IDs that are not hex. {std::regex("_[0-9]+([^0-9a-fA-Fx])"), "$1"}, // removes AST IDs that are not hex.
{regex("_[0-9]+$"), ""}, // removes AST IDs that are not hex. {std::regex("_[0-9]+$"), ""}, // removes AST IDs that are not hex.
{regex("_t_"), "_"}, // remove type prefixes {std::regex("_t_"), "_"}, // remove type prefixes
{regex("__"), "_"}, {std::regex("__"), "_"},
{regex("(abi_..code.*)_to_.*"), "$1"}, // removes _to... for abi functions {std::regex("(abi_..code.*)_to_.*"), "$1"}, // removes _to... for abi functions
{regex("(stringliteral_?[0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]*"), "$1"}, // shorten string literal {std::regex("(stringliteral_?[0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]*"), "$1"}, // shorten string literal
{regex("tuple_"), ""}, {std::regex("tuple_"), ""},
{regex("_memory_ptr"), ""}, {std::regex("_memory_ptr"), ""},
{regex("_calldata_ptr"), "_calldata"}, {std::regex("_calldata_ptr"), "_calldata"},
{regex("_fromStack"), ""}, {std::regex("_fromStack"), ""},
{regex("_storage_storage"), "_storage"}, {std::regex("_storage_storage"), "_storage"},
{regex("(storage.*)_?storage"), "$1"}, {std::regex("(storage.*)_?storage"), "$1"},
{regex("_memory_memory"), "_memory"}, {std::regex("_memory_memory"), "_memory"},
{regex("_contract\\$_([^_]*)_?"), "$1_"}, {std::regex("_contract\\$_([^_]*)_?"), "$1_"},
{regex("index_access_(t_)?array"), "index_access"}, {std::regex("index_access_(t_)?array"), "index_access"},
{regex("[0-9]*_$"), ""} {std::regex("[0-9]*_$"), ""}
}; };
for (auto const& [pattern, substitute]: replacements) for (auto const& [pattern, substitute]: replacements)
{ {
string candidate = regex_replace(name, pattern, substitute); std::string candidate = regex_replace(name, pattern, substitute);
if (!candidate.empty() && !m_context.dispenser.illegalName(YulString(candidate))) if (!candidate.empty() && !m_context.dispenser.illegalName(YulString(candidate)))
name = candidate; name = candidate;
} }

View File

@ -31,7 +31,6 @@
#include <range/v3/action/remove_if.hpp> #include <range/v3/action/remove_if.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::util; using namespace solidity::util;
@ -40,7 +39,7 @@ using namespace solidity::yul;
void yul::removeEmptyBlocks(Block& _block) void yul::removeEmptyBlocks(Block& _block)
{ {
auto isEmptyBlock = [](Statement const& _st) -> bool { auto isEmptyBlock = [](Statement const& _st) -> bool {
return holds_alternative<Block>(_st) && std::get<Block>(_st).statements.empty(); return std::holds_alternative<Block>(_st) && std::get<Block>(_st).statements.empty();
}; };
ranges::actions::remove_if(_block.statements, isEmptyBlock); ranges::actions::remove_if(_block.statements, isEmptyBlock);
} }
@ -50,12 +49,12 @@ bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulString const& _iden
return _identifier.empty() || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); return _identifier.empty() || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier);
} }
optional<evmasm::Instruction> yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name) std::optional<evmasm::Instruction> yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name)
{ {
if (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect)) if (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect))
if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name)) if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name))
return builtin->instruction; return builtin->instruction;
return nullopt; return std::nullopt;
} }
langutil::EVMVersion const yul::evmVersionFromDialect(Dialect const& _dialect) langutil::EVMVersion const yul::evmVersionFromDialect(Dialect const& _dialect)
@ -69,12 +68,12 @@ void StatementRemover::operator()(Block& _block)
{ {
util::iterateReplacing( util::iterateReplacing(
_block.statements, _block.statements,
[&](Statement& _statement) -> std::optional<vector<Statement>> [&](Statement& _statement) -> std::optional<std::vector<Statement>>
{ {
if (m_toRemove.count(&_statement)) if (m_toRemove.count(&_statement))
return {vector<Statement>{}}; return {std::vector<Statement>{}};
else else
return nullopt; return std::nullopt;
} }
); );
ASTModifier::operator()(_block); ASTModifier::operator()(_block);

View File

@ -28,11 +28,10 @@
#include <range/v3/algorithm/all_of.hpp> #include <range/v3/algorithm/all_of.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
void Rematerialiser::run(Dialect const& _dialect, Block& _ast, set<YulString> _varsToAlwaysRematerialize, bool _onlySelectedVariables) void Rematerialiser::run(Dialect const& _dialect, Block& _ast, std::set<YulString> _varsToAlwaysRematerialize, bool _onlySelectedVariables)
{ {
Rematerialiser{_dialect, _ast, std::move(_varsToAlwaysRematerialize), _onlySelectedVariables}(_ast); Rematerialiser{_dialect, _ast, std::move(_varsToAlwaysRematerialize), _onlySelectedVariables}(_ast);
} }
@ -40,7 +39,7 @@ void Rematerialiser::run(Dialect const& _dialect, Block& _ast, set<YulString> _v
Rematerialiser::Rematerialiser( Rematerialiser::Rematerialiser(
Dialect const& _dialect, Dialect const& _dialect,
Block& _ast, Block& _ast,
set<YulString> _varsToAlwaysRematerialize, std::set<YulString> _varsToAlwaysRematerialize,
bool _onlySelectedVariables bool _onlySelectedVariables
): ):
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore), DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore),
@ -52,7 +51,7 @@ Rematerialiser::Rematerialiser(
void Rematerialiser::visit(Expression& _e) void Rematerialiser::visit(Expression& _e)
{ {
if (holds_alternative<Identifier>(_e)) if (std::holds_alternative<Identifier>(_e))
{ {
Identifier& identifier = std::get<Identifier>(_e); Identifier& identifier = std::get<Identifier>(_e);
YulString name = identifier.name; YulString name = identifier.name;
@ -91,14 +90,14 @@ void Rematerialiser::visit(Expression& _e)
void LiteralRematerialiser::visit(Expression& _e) void LiteralRematerialiser::visit(Expression& _e)
{ {
if (holds_alternative<Identifier>(_e)) if (std::holds_alternative<Identifier>(_e))
{ {
Identifier& identifier = std::get<Identifier>(_e); Identifier& identifier = std::get<Identifier>(_e);
YulString name = identifier.name; YulString name = identifier.name;
if (AssignedValue const* value = variableValue(name)) if (AssignedValue const* value = variableValue(name))
{ {
assertThrow(value->value, OptimizerException, ""); assertThrow(value->value, OptimizerException, "");
if (holds_alternative<Literal>(*value->value)) if (std::holds_alternative<Literal>(*value->value))
_e = *value->value; _e = *value->value;
} }
} }

View File

@ -22,7 +22,6 @@
#include <variant> #include <variant>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -38,7 +37,7 @@ void SSAReverser::operator()(Block& _block)
walkVector(_block.statements); walkVector(_block.statements);
util::iterateReplacingWindow<2>( util::iterateReplacingWindow<2>(
_block.statements, _block.statements,
[&](Statement& _stmt1, Statement& _stmt2) -> std::optional<vector<Statement>> [&](Statement& _stmt1, Statement& _stmt2) -> std::optional<std::vector<Statement>>
{ {
auto* varDecl = std::get_if<VariableDeclaration>(&_stmt1); auto* varDecl = std::get_if<VariableDeclaration>(&_stmt1);

View File

@ -30,7 +30,6 @@
#include <libyul/optimiser/TypeInfo.h> #include <libyul/optimiser/TypeInfo.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -47,7 +46,7 @@ class IntroduceSSA: public ASTModifier
public: public:
explicit IntroduceSSA( explicit IntroduceSSA(
NameDispenser& _nameDispenser, NameDispenser& _nameDispenser,
set<YulString> const& _variablesToReplace, std::set<YulString> const& _variablesToReplace,
TypeInfo& _typeInfo TypeInfo& _typeInfo
): ):
m_nameDispenser(_nameDispenser), m_nameDispenser(_nameDispenser),
@ -59,7 +58,7 @@ public:
private: private:
NameDispenser& m_nameDispenser; NameDispenser& m_nameDispenser;
set<YulString> const& m_variablesToReplace; std::set<YulString> const& m_variablesToReplace;
TypeInfo const& m_typeInfo; TypeInfo const& m_typeInfo;
}; };
@ -68,9 +67,9 @@ void IntroduceSSA::operator()(Block& _block)
{ {
util::iterateReplacing( util::iterateReplacing(
_block.statements, _block.statements,
[&](Statement& _s) -> std::optional<vector<Statement>> [&](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
if (holds_alternative<VariableDeclaration>(_s)) if (std::holds_alternative<VariableDeclaration>(_s))
{ {
VariableDeclaration& varDecl = std::get<VariableDeclaration>(_s); VariableDeclaration& varDecl = std::get<VariableDeclaration>(_s);
if (varDecl.value) if (varDecl.value)
@ -85,8 +84,8 @@ void IntroduceSSA::operator()(Block& _block)
// Replace "let a := v" by "let a_1 := v let a := a_1" // Replace "let a := v" by "let a_1 := v let a := a_1"
// Replace "let a, b := v" by "let a_1, b_1 := v let a := a_1 let b := b_2" // Replace "let a, b := v" by "let a_1, b_1 := v let a := a_1 let b := b_2"
shared_ptr<DebugData const> debugData = varDecl.debugData; std::shared_ptr<DebugData const> debugData = varDecl.debugData;
vector<Statement> statements; std::vector<Statement> statements;
statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)}); statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)});
TypedNameList newVariables; TypedNameList newVariables;
for (auto const& var: varDecl.variables) for (auto const& var: varDecl.variables)
@ -97,13 +96,13 @@ void IntroduceSSA::operator()(Block& _block)
statements.emplace_back(VariableDeclaration{ statements.emplace_back(VariableDeclaration{
debugData, debugData,
{TypedName{debugData, oldName, var.type}}, {TypedName{debugData, oldName, var.type}},
make_unique<Expression>(Identifier{debugData, newName}) std::make_unique<Expression>(Identifier{debugData, newName})
}); });
} }
std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables); std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables);
return { std::move(statements) }; return { std::move(statements) };
} }
else if (holds_alternative<Assignment>(_s)) else if (std::holds_alternative<Assignment>(_s))
{ {
Assignment& assignment = std::get<Assignment>(_s); Assignment& assignment = std::get<Assignment>(_s);
visit(*assignment.value); visit(*assignment.value);
@ -113,7 +112,7 @@ void IntroduceSSA::operator()(Block& _block)
// Replace "a := v" by "let a_1 := v a := v" // Replace "a := v" by "let a_1 := v a := v"
// Replace "a, b := v" by "let a_1, b_1 := v a := a_1 b := b_2" // Replace "a, b := v" by "let a_1, b_1 := v a := a_1 b := b_2"
std::shared_ptr<DebugData const> debugData = assignment.debugData; std::shared_ptr<DebugData const> debugData = assignment.debugData;
vector<Statement> statements; std::vector<Statement> statements;
statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)}); statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)});
TypedNameList newVariables; TypedNameList newVariables;
for (auto const& var: assignment.variableNames) for (auto const& var: assignment.variableNames)
@ -127,7 +126,7 @@ void IntroduceSSA::operator()(Block& _block)
statements.emplace_back(Assignment{ statements.emplace_back(Assignment{
debugData, debugData,
{Identifier{debugData, oldName}}, {Identifier{debugData, oldName}},
make_unique<Expression>(Identifier{debugData, newName}) std::make_unique<Expression>(Identifier{debugData, newName})
}); });
} }
std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables); std::get<VariableDeclaration>(statements.front()).variables = std::move(newVariables);
@ -149,7 +148,7 @@ class IntroduceControlFlowSSA: public ASTModifier
public: public:
explicit IntroduceControlFlowSSA( explicit IntroduceControlFlowSSA(
NameDispenser& _nameDispenser, NameDispenser& _nameDispenser,
set<YulString> const& _variablesToReplace, std::set<YulString> const& _variablesToReplace,
TypeInfo const& _typeInfo TypeInfo const& _typeInfo
): ):
m_nameDispenser(_nameDispenser), m_nameDispenser(_nameDispenser),
@ -164,19 +163,19 @@ public:
private: private:
NameDispenser& m_nameDispenser; NameDispenser& m_nameDispenser;
set<YulString> const& m_variablesToReplace; std::set<YulString> const& m_variablesToReplace;
/// Variables (that are to be replaced) currently in scope. /// Variables (that are to be replaced) currently in scope.
set<YulString> m_variablesInScope; std::set<YulString> m_variablesInScope;
/// Set of variables that do not have a specific value. /// Set of variables that do not have a specific value.
set<YulString> m_variablesToReassign; std::set<YulString> m_variablesToReassign;
TypeInfo const& m_typeInfo; TypeInfo const& m_typeInfo;
}; };
void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function)
{ {
set<YulString> varsInScope; std::set<YulString> varsInScope;
std::swap(varsInScope, m_variablesInScope); std::swap(varsInScope, m_variablesInScope);
set<YulString> toReassign; std::set<YulString> toReassign;
std::swap(toReassign, m_variablesToReassign); std::swap(toReassign, m_variablesToReassign);
for (auto const& param: _function.parameters) for (auto const& param: _function.parameters)
@ -208,7 +207,7 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch)
{ {
yulAssert(m_variablesToReassign.empty(), ""); yulAssert(m_variablesToReassign.empty(), "");
set<YulString> toReassign; std::set<YulString> toReassign;
for (auto& c: _switch.cases) for (auto& c: _switch.cases)
{ {
(*this)(c.body); (*this)(c.body);
@ -220,27 +219,27 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch)
void IntroduceControlFlowSSA::operator()(Block& _block) void IntroduceControlFlowSSA::operator()(Block& _block)
{ {
set<YulString> variablesDeclaredHere; std::set<YulString> variablesDeclaredHere;
set<YulString> assignedVariables; std::set<YulString> assignedVariables;
util::iterateReplacing( util::iterateReplacing(
_block.statements, _block.statements,
[&](Statement& _s) -> std::optional<vector<Statement>> [&](Statement& _s) -> std::optional<std::vector<Statement>>
{ {
vector<Statement> toPrepend; std::vector<Statement> toPrepend;
for (YulString toReassign: m_variablesToReassign) for (YulString toReassign: m_variablesToReassign)
{ {
YulString newName = m_nameDispenser.newName(toReassign); YulString newName = m_nameDispenser.newName(toReassign);
toPrepend.emplace_back(VariableDeclaration{ toPrepend.emplace_back(VariableDeclaration{
debugDataOf(_s), debugDataOf(_s),
{TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}}, {TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}},
make_unique<Expression>(Identifier{debugDataOf(_s), toReassign}) std::make_unique<Expression>(Identifier{debugDataOf(_s), toReassign})
}); });
assignedVariables.insert(toReassign); assignedVariables.insert(toReassign);
} }
m_variablesToReassign.clear(); m_variablesToReassign.clear();
if (holds_alternative<VariableDeclaration>(_s)) if (std::holds_alternative<VariableDeclaration>(_s))
{ {
VariableDeclaration& varDecl = std::get<VariableDeclaration>(_s); VariableDeclaration& varDecl = std::get<VariableDeclaration>(_s);
for (auto const& var: varDecl.variables) for (auto const& var: varDecl.variables)
@ -250,7 +249,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
m_variablesInScope.insert(var.name); m_variablesInScope.insert(var.name);
} }
} }
else if (holds_alternative<Assignment>(_s)) else if (std::holds_alternative<Assignment>(_s))
{ {
Assignment& assignment = std::get<Assignment>(_s); Assignment& assignment = std::get<Assignment>(_s);
for (auto const& var: assignment.variableNames) for (auto const& var: assignment.variableNames)
@ -281,7 +280,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
class PropagateValues: public ASTModifier class PropagateValues: public ASTModifier
{ {
public: public:
explicit PropagateValues(set<YulString> const& _variablesToReplace): explicit PropagateValues(std::set<YulString> const& _variablesToReplace):
m_variablesToReplace(_variablesToReplace) m_variablesToReplace(_variablesToReplace)
{ } { }
@ -294,9 +293,9 @@ public:
private: private:
/// This is a set of all variables that are assigned to anywhere in the code. /// This is a set of all variables that are assigned to anywhere in the code.
/// Variables that are only declared but never re-assigned are not touched. /// Variables that are only declared but never re-assigned are not touched.
set<YulString> const& m_variablesToReplace; std::set<YulString> const& m_variablesToReplace;
map<YulString, YulString> m_currentVariableValues; std::map<YulString, YulString> m_currentVariableValues;
set<YulString> m_clearAtEndOfBlock; std::set<YulString> m_clearAtEndOfBlock;
}; };
void PropagateValues::operator()(Identifier& _identifier) void PropagateValues::operator()(Identifier& _identifier)
@ -316,11 +315,11 @@ void PropagateValues::operator()(VariableDeclaration& _varDecl)
if (m_variablesToReplace.count(variable)) if (m_variablesToReplace.count(variable))
{ {
// `let a := a_1` - regular declaration of non-SSA variable // `let a := a_1` - regular declaration of non-SSA variable
yulAssert(holds_alternative<Identifier>(*_varDecl.value), ""); yulAssert(std::holds_alternative<Identifier>(*_varDecl.value), "");
m_currentVariableValues[variable] = std::get<Identifier>(*_varDecl.value).name; m_currentVariableValues[variable] = std::get<Identifier>(*_varDecl.value).name;
m_clearAtEndOfBlock.insert(variable); m_clearAtEndOfBlock.insert(variable);
} }
else if (_varDecl.value && holds_alternative<Identifier>(*_varDecl.value)) else if (_varDecl.value && std::holds_alternative<Identifier>(*_varDecl.value))
{ {
// `let a_1 := a` - assignment to SSA variable after a branch. // `let a_1 := a` - assignment to SSA variable after a branch.
YulString value = std::get<Identifier>(*_varDecl.value).name; YulString value = std::get<Identifier>(*_varDecl.value).name;
@ -345,7 +344,7 @@ void PropagateValues::operator()(Assignment& _assignment)
if (!m_variablesToReplace.count(name)) if (!m_variablesToReplace.count(name))
return; return;
yulAssert(_assignment.value && holds_alternative<Identifier>(*_assignment.value), ""); yulAssert(_assignment.value && std::holds_alternative<Identifier>(*_assignment.value), "");
m_currentVariableValues[name] = std::get<Identifier>(*_assignment.value).name; m_currentVariableValues[name] = std::get<Identifier>(*_assignment.value).name;
m_clearAtEndOfBlock.insert(name); m_clearAtEndOfBlock.insert(name);
} }
@ -364,7 +363,7 @@ void PropagateValues::operator()(ForLoop& _for)
void PropagateValues::operator()(Block& _block) void PropagateValues::operator()(Block& _block)
{ {
set<YulString> clearAtParentBlock = std::move(m_clearAtEndOfBlock); std::set<YulString> clearAtParentBlock = std::move(m_clearAtEndOfBlock);
m_clearAtEndOfBlock.clear(); m_clearAtEndOfBlock.clear();
ASTModifier::operator()(_block); ASTModifier::operator()(_block);
@ -380,7 +379,7 @@ void PropagateValues::operator()(Block& _block)
void SSATransform::run(OptimiserStepContext& _context, Block& _ast) void SSATransform::run(OptimiserStepContext& _context, Block& _ast)
{ {
TypeInfo typeInfo(_context.dialect, _ast); TypeInfo typeInfo(_context.dialect, _ast);
set<YulString> assignedVariables = assignedVariableNames(_ast); std::set<YulString> assignedVariables = assignedVariableNames(_ast);
IntroduceSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); IntroduceSSA{_context.dispenser, assignedVariables, typeInfo}(_ast);
IntroduceControlFlowSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); IntroduceControlFlowSSA{_context.dispenser, assignedVariables, typeInfo}(_ast);
PropagateValues{assignedVariables}(_ast); PropagateValues{assignedVariables}(_ast);

View File

@ -24,7 +24,6 @@
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -50,11 +49,11 @@ void SSAValueTracker::operator()(VariableDeclaration const& _varDecl)
setValue(_varDecl.variables.front().name, _varDecl.value.get()); setValue(_varDecl.variables.front().name, _varDecl.value.get());
} }
set<YulString> SSAValueTracker::ssaVariables(Block const& _ast) std::set<YulString> SSAValueTracker::ssaVariables(Block const& _ast)
{ {
SSAValueTracker t; SSAValueTracker t;
t(_ast); t(_ast);
set<YulString> ssaVars; std::set<YulString> ssaVars;
for (auto const& value: t.values()) for (auto const& value: t.values())
ssaVars.insert(value.first); ssaVars.insert(value.first);
return ssaVars; return ssaVars;

View File

@ -33,7 +33,6 @@
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -41,7 +40,7 @@ using namespace solidity::yul;
SideEffectsCollector::SideEffectsCollector( SideEffectsCollector::SideEffectsCollector(
Dialect const& _dialect, Dialect const& _dialect,
Expression const& _expression, Expression const& _expression,
map<YulString, SideEffects> const* _functionSideEffects std::map<YulString, SideEffects> const* _functionSideEffects
): ):
SideEffectsCollector(_dialect, _functionSideEffects) SideEffectsCollector(_dialect, _functionSideEffects)
{ {
@ -57,7 +56,7 @@ SideEffectsCollector::SideEffectsCollector(Dialect const& _dialect, Statement co
SideEffectsCollector::SideEffectsCollector( SideEffectsCollector::SideEffectsCollector(
Dialect const& _dialect, Dialect const& _dialect,
Block const& _ast, Block const& _ast,
map<YulString, SideEffects> const* _functionSideEffects std::map<YulString, SideEffects> const* _functionSideEffects
): ):
SideEffectsCollector(_dialect, _functionSideEffects) SideEffectsCollector(_dialect, _functionSideEffects)
{ {
@ -67,7 +66,7 @@ SideEffectsCollector::SideEffectsCollector(
SideEffectsCollector::SideEffectsCollector( SideEffectsCollector::SideEffectsCollector(
Dialect const& _dialect, Dialect const& _dialect,
ForLoop const& _ast, ForLoop const& _ast,
map<YulString, SideEffects> const* _functionSideEffects std::map<YulString, SideEffects> const* _functionSideEffects
): ):
SideEffectsCollector(_dialect, _functionSideEffects) SideEffectsCollector(_dialect, _functionSideEffects)
{ {
@ -99,7 +98,7 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object)
if (containsMSize(_dialect, *_object.code)) if (containsMSize(_dialect, *_object.code))
return true; return true;
for (shared_ptr<ObjectNode> const& node: _object.subObjects) for (std::shared_ptr<ObjectNode> const& node: _object.subObjects)
if (auto const* object = dynamic_cast<Object const*>(node.get())) if (auto const* object = dynamic_cast<Object const*>(node.get()))
if (containsMSize(_dialect, *object)) if (containsMSize(_dialect, *object))
return true; return true;
@ -116,7 +115,7 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall)
m_msizeFound = true; m_msizeFound = true;
} }
map<YulString, SideEffects> SideEffectsPropagator::sideEffects( std::map<YulString, SideEffects> SideEffectsPropagator::sideEffects(
Dialect const& _dialect, Dialect const& _dialect,
CallGraph const& _directCallGraph CallGraph const& _directCallGraph
) )
@ -127,7 +126,7 @@ map<YulString, SideEffects> SideEffectsPropagator::sideEffects(
// In the future, we should refine that, because the property // In the future, we should refine that, because the property
// is actually a bit different from "not movable". // is actually a bit different from "not movable".
map<YulString, SideEffects> ret; std::map<YulString, SideEffects> ret;
for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions()) for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions())
{ {
ret[function].movable = false; ret[function].movable = false;
@ -179,8 +178,8 @@ void MovableChecker::visit(Statement const&)
assertThrow(false, OptimizerException, "Movability for statement requested."); assertThrow(false, OptimizerException, "Movability for statement requested.");
} }
pair<TerminationFinder::ControlFlow, size_t> TerminationFinder::firstUnconditionalControlFlowChange( std::pair<TerminationFinder::ControlFlow, size_t> TerminationFinder::firstUnconditionalControlFlowChange(
vector<Statement> const& _statements std::vector<Statement> const& _statements
) )
{ {
for (size_t i = 0; i < _statements.size(); ++i) for (size_t i = 0; i < _statements.size(); ++i)
@ -189,32 +188,32 @@ pair<TerminationFinder::ControlFlow, size_t> TerminationFinder::firstUncondition
if (controlFlow != ControlFlow::FlowOut) if (controlFlow != ControlFlow::FlowOut)
return {controlFlow, i}; return {controlFlow, i};
} }
return {ControlFlow::FlowOut, numeric_limits<size_t>::max()}; return {ControlFlow::FlowOut, std::numeric_limits<size_t>::max()};
} }
TerminationFinder::ControlFlow TerminationFinder::controlFlowKind(Statement const& _statement) TerminationFinder::ControlFlow TerminationFinder::controlFlowKind(Statement const& _statement)
{ {
if ( if (
holds_alternative<VariableDeclaration>(_statement) && std::holds_alternative<VariableDeclaration>(_statement) &&
std::get<VariableDeclaration>(_statement).value && std::get<VariableDeclaration>(_statement).value &&
containsNonContinuingFunctionCall(*std::get<VariableDeclaration>(_statement).value) containsNonContinuingFunctionCall(*std::get<VariableDeclaration>(_statement).value)
) )
return ControlFlow::Terminate; return ControlFlow::Terminate;
else if ( else if (
holds_alternative<Assignment>(_statement) && std::holds_alternative<Assignment>(_statement) &&
containsNonContinuingFunctionCall(*std::get<Assignment>(_statement).value) containsNonContinuingFunctionCall(*std::get<Assignment>(_statement).value)
) )
return ControlFlow::Terminate; return ControlFlow::Terminate;
else if ( else if (
holds_alternative<ExpressionStatement>(_statement) && std::holds_alternative<ExpressionStatement>(_statement) &&
containsNonContinuingFunctionCall(std::get<ExpressionStatement>(_statement).expression) containsNonContinuingFunctionCall(std::get<ExpressionStatement>(_statement).expression)
) )
return ControlFlow::Terminate; return ControlFlow::Terminate;
else if (holds_alternative<Break>(_statement)) else if (std::holds_alternative<Break>(_statement))
return ControlFlow::Break; return ControlFlow::Break;
else if (holds_alternative<Continue>(_statement)) else if (std::holds_alternative<Continue>(_statement))
return ControlFlow::Continue; return ControlFlow::Continue;
else if (holds_alternative<Leave>(_statement)) else if (std::holds_alternative<Leave>(_statement))
return ControlFlow::Leave; return ControlFlow::Leave;
else else
return ControlFlow::FlowOut; return ControlFlow::FlowOut;

View File

@ -32,7 +32,6 @@
#include <libevmasm/RuleList.h> #include <libevmasm/RuleList.h>
#include <libsolutil/StringUtils.h> #include <libsolutil/StringUtils.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -41,7 +40,7 @@ using namespace solidity::yul;
SimplificationRules::Rule const* SimplificationRules::findFirstMatch( SimplificationRules::Rule const* SimplificationRules::findFirstMatch(
Expression const& _expr, Expression const& _expr,
Dialect const& _dialect, Dialect const& _dialect,
function<AssignedValue const*(YulString)> const& _ssaValues std::function<AssignedValue const*(YulString)> const& _ssaValues
) )
{ {
auto instruction = instructionAndArguments(_dialect, _expr); auto instruction = instructionAndArguments(_dialect, _expr);
@ -75,14 +74,14 @@ bool SimplificationRules::isInitialized() const
return !m_rules[uint8_t(evmasm::Instruction::ADD)].empty(); return !m_rules[uint8_t(evmasm::Instruction::ADD)].empty();
} }
std::optional<std::pair<evmasm::Instruction, vector<Expression> const*>> std::optional<std::pair<evmasm::Instruction, std::vector<Expression> const*>>
SimplificationRules::instructionAndArguments(Dialect const& _dialect, Expression const& _expr) SimplificationRules::instructionAndArguments(Dialect const& _dialect, Expression const& _expr)
{ {
if (holds_alternative<FunctionCall>(_expr)) if (std::holds_alternative<FunctionCall>(_expr))
if (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect)) if (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect))
if (auto const* builtin = dialect->builtin(std::get<FunctionCall>(_expr).functionName.name)) if (auto const* builtin = dialect->builtin(std::get<FunctionCall>(_expr).functionName.name))
if (builtin->instruction) if (builtin->instruction)
return make_pair(*builtin->instruction, &std::get<FunctionCall>(_expr).arguments); return std::make_pair(*builtin->instruction, &std::get<FunctionCall>(_expr).arguments);
return {}; return {};
} }
@ -122,14 +121,14 @@ SimplificationRules::SimplificationRules(std::optional<langutil::EVMVersion> _ev
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
} }
yul::Pattern::Pattern(evmasm::Instruction _instruction, initializer_list<Pattern> _arguments): yul::Pattern::Pattern(evmasm::Instruction _instruction, std::initializer_list<Pattern> _arguments):
m_kind(PatternKind::Operation), m_kind(PatternKind::Operation),
m_instruction(_instruction), m_instruction(_instruction),
m_arguments(_arguments) m_arguments(_arguments)
{ {
} }
void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _matchGroups) void Pattern::setMatchGroup(unsigned _group, std::map<unsigned, Expression const*>& _matchGroups)
{ {
m_matchGroup = _group; m_matchGroup = _group;
m_matchGroups = &_matchGroups; m_matchGroups = &_matchGroups;
@ -138,14 +137,14 @@ void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _
bool Pattern::matches( bool Pattern::matches(
Expression const& _expr, Expression const& _expr,
Dialect const& _dialect, Dialect const& _dialect,
function<AssignedValue const*(YulString)> const& _ssaValues std::function<AssignedValue const*(YulString)> const& _ssaValues
) const ) const
{ {
Expression const* expr = &_expr; Expression const* expr = &_expr;
// Resolve the variable if possible. // Resolve the variable if possible.
// Do not do it for "Any" because we can check identity better for variables. // Do not do it for "Any" because we can check identity better for variables.
if (m_kind != PatternKind::Any && holds_alternative<Identifier>(_expr)) if (m_kind != PatternKind::Any && std::holds_alternative<Identifier>(_expr))
{ {
YulString varName = std::get<Identifier>(_expr).name; YulString varName = std::get<Identifier>(_expr).name;
if (AssignedValue const* value = _ssaValues(varName)) if (AssignedValue const* value = _ssaValues(varName))
@ -156,7 +155,7 @@ bool Pattern::matches(
if (m_kind == PatternKind::Constant) if (m_kind == PatternKind::Constant)
{ {
if (!holds_alternative<Literal>(*expr)) if (!std::holds_alternative<Literal>(*expr))
return false; return false;
Literal const& literal = std::get<Literal>(*expr); Literal const& literal = std::get<Literal>(*expr);
if (literal.kind != LiteralKind::Number) if (literal.kind != LiteralKind::Number)
@ -178,7 +177,7 @@ bool Pattern::matches(
// we reject the match because side-effects could prevent us from // we reject the match because side-effects could prevent us from
// arbitrarily modifying the code. // arbitrarily modifying the code.
if ( if (
holds_alternative<FunctionCall>(arg) || std::holds_alternative<FunctionCall>(arg) ||
!m_arguments[i].matches(arg, _dialect, _ssaValues) !m_arguments[i].matches(arg, _dialect, _ssaValues)
) )
return false; return false;
@ -187,7 +186,7 @@ bool Pattern::matches(
else else
{ {
assertThrow(m_arguments.empty(), OptimizerException, "\"Any\" should not have arguments."); assertThrow(m_arguments.empty(), OptimizerException, "\"Any\" should not have arguments.");
assertThrow(!holds_alternative<FunctionCall>(*expr), OptimizerException, "\"Any\" at top-level."); assertThrow(!std::holds_alternative<FunctionCall>(*expr), OptimizerException, "\"Any\" at top-level.");
} }
if (m_matchGroup) if (m_matchGroup)
@ -209,8 +208,8 @@ bool Pattern::matches(
Expression const* firstMatch = (*m_matchGroups)[m_matchGroup]; Expression const* firstMatch = (*m_matchGroups)[m_matchGroup];
assertThrow(firstMatch, OptimizerException, "Match set but to null."); assertThrow(firstMatch, OptimizerException, "Match set but to null.");
assertThrow( assertThrow(
!holds_alternative<FunctionCall>(_expr) && !std::holds_alternative<FunctionCall>(_expr) &&
!holds_alternative<FunctionCall>(*firstMatch), !std::holds_alternative<FunctionCall>(*firstMatch),
OptimizerException, OptimizerException,
"Group matches have to be literals or variables." "Group matches have to be literals or variables."
); );
@ -235,7 +234,7 @@ evmasm::Instruction Pattern::instruction() const
return m_instruction; return m_instruction;
} }
Expression Pattern::toExpression(shared_ptr<DebugData const> const& _debugData, langutil::EVMVersion _evmVersion) const Expression Pattern::toExpression(std::shared_ptr<DebugData const> const& _debugData, langutil::EVMVersion _evmVersion) const
{ {
if (matchGroup()) if (matchGroup())
return ASTCopier().translate(matchGroupValue()); return ASTCopier().translate(matchGroupValue());
@ -246,11 +245,11 @@ Expression Pattern::toExpression(shared_ptr<DebugData const> const& _debugData,
} }
else if (m_kind == PatternKind::Operation) else if (m_kind == PatternKind::Operation)
{ {
vector<Expression> arguments; std::vector<Expression> arguments;
for (auto const& arg: m_arguments) for (auto const& arg: m_arguments)
arguments.emplace_back(arg.toExpression(_debugData, _evmVersion)); arguments.emplace_back(arg.toExpression(_debugData, _evmVersion));
string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); std::string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name);
return FunctionCall{_debugData, return FunctionCall{_debugData,
Identifier{_debugData, YulString{name}}, Identifier{_debugData, YulString{name}},

View File

@ -40,7 +40,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -61,9 +60,9 @@ public:
/// @returns a map from function name to rematerialisation costs to a vector of variables to rematerialise /// @returns a map from function name to rematerialisation costs to a vector of variables to rematerialise
/// and variables that occur in their expression. /// and variables that occur in their expression.
/// While the map is sorted by cost, the contained vectors are sorted by the order of occurrence. /// While the map is sorted by cost, the contained vectors are sorted by the order of occurrence.
map<YulString, map<size_t, vector<YulString>>> candidates() std::map<YulString, std::map<size_t, std::vector<YulString>>> candidates()
{ {
map<YulString, map<size_t, vector<YulString>>> cand; std::map<YulString, std::map<size_t, std::vector<YulString>>> cand;
for (auto const& [functionName, candidate]: m_candidates) for (auto const& [functionName, candidate]: m_candidates)
{ {
if (size_t const* cost = util::valueOrNullptr(m_expressionCodeCost, candidate)) if (size_t const* cost = util::valueOrNullptr(m_expressionCodeCost, candidate))
@ -110,7 +109,7 @@ public:
// get called on left-hand-sides of assignments. // get called on left-hand-sides of assignments.
void visit(Expression& _e) override void visit(Expression& _e) override
{ {
if (holds_alternative<Identifier>(_e)) if (std::holds_alternative<Identifier>(_e))
{ {
YulString name = std::get<Identifier>(_e).name; YulString name = std::get<Identifier>(_e).name;
if (m_expressionCodeCost.count(name)) if (m_expressionCodeCost.count(name))
@ -134,20 +133,20 @@ public:
YulString m_currentFunctionName = {}; YulString m_currentFunctionName = {};
/// All candidate variables by function name, in order of occurrence. /// All candidate variables by function name, in order of occurrence.
vector<pair<YulString, YulString>> m_candidates; std::vector<std::pair<YulString, YulString>> m_candidates;
/// Candidate variables and the code cost of their value. /// Candidate variables and the code cost of their value.
map<YulString, size_t> m_expressionCodeCost; std::map<YulString, size_t> m_expressionCodeCost;
/// Number of references to each candidate variable. /// Number of references to each candidate variable.
map<YulString, size_t> m_numReferences; std::map<YulString, size_t> m_numReferences;
}; };
/// Selects at most @a _numVariables among @a _candidates. /// Selects at most @a _numVariables among @a _candidates.
set<YulString> chooseVarsToEliminate( std::set<YulString> chooseVarsToEliminate(
map<size_t, vector<YulString>> const& _candidates, std::map<size_t, std::vector<YulString>> const& _candidates,
size_t _numVariables size_t _numVariables
) )
{ {
set<YulString> varsToEliminate; std::set<YulString> varsToEliminate;
for (auto&& [cost, candidates]: _candidates) for (auto&& [cost, candidates]: _candidates)
for (auto&& candidate: candidates) for (auto&& candidate: candidates)
{ {
@ -161,15 +160,15 @@ set<YulString> chooseVarsToEliminate(
void eliminateVariables( void eliminateVariables(
Dialect const& _dialect, Dialect const& _dialect,
Block& _ast, Block& _ast,
map<YulString, int> const& _numVariables, std::map<YulString, int> const& _numVariables,
bool _allowMSizeOptimization bool _allowMSizeOptimization
) )
{ {
RematCandidateSelector selector{_dialect}; RematCandidateSelector selector{_dialect};
selector(_ast); selector(_ast);
map<YulString, map<size_t, vector<YulString>>> candidates = selector.candidates(); std::map<YulString, std::map<size_t, std::vector<YulString>>> candidates = selector.candidates();
set<YulString> varsToEliminate; std::set<YulString> varsToEliminate;
for (auto const& [functionName, numVariables]: _numVariables) for (auto const& [functionName, numVariables]: _numVariables)
{ {
yulAssert(numVariables > 0); yulAssert(numVariables > 0);
@ -178,14 +177,14 @@ void eliminateVariables(
Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate)); Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate));
// Do not remove functions. // Do not remove functions.
set<YulString> allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); std::set<YulString> allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names();
UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions); UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions);
} }
void eliminateVariablesOptimizedCodegen( void eliminateVariablesOptimizedCodegen(
Dialect const& _dialect, Dialect const& _dialect,
Block& _ast, Block& _ast,
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> const& _unreachables, std::map<YulString, std::vector<StackLayoutGenerator::StackTooDeep>> const& _unreachables,
bool _allowMSizeOptimization bool _allowMSizeOptimization
) )
{ {
@ -195,19 +194,19 @@ void eliminateVariablesOptimizedCodegen(
RematCandidateSelector selector{_dialect}; RematCandidateSelector selector{_dialect};
selector(_ast); selector(_ast);
map<YulString, size_t> candidates; std::map<YulString, size_t> candidates;
for (auto const& [functionName, candidatesInFunction]: selector.candidates()) for (auto const& [functionName, candidatesInFunction]: selector.candidates())
for (auto [cost, candidatesWithCost]: candidatesInFunction) for (auto [cost, candidatesWithCost]: candidatesInFunction)
for (auto candidate: candidatesWithCost) for (auto candidate: candidatesWithCost)
candidates[candidate] = cost; candidates[candidate] = cost;
set<YulString> varsToEliminate; std::set<YulString> varsToEliminate;
// TODO: this currently ignores the fact that variables may reference other variables we want to eliminate. // TODO: this currently ignores the fact that variables may reference other variables we want to eliminate.
for (auto const& [functionName, unreachables]: _unreachables) for (auto const& [functionName, unreachables]: _unreachables)
for (auto const& unreachable: unreachables) for (auto const& unreachable: unreachables)
{ {
map<size_t, vector<YulString>> suitableCandidates; std::map<size_t, std::vector<YulString>> suitableCandidates;
size_t neededSlots = unreachable.deficit; size_t neededSlots = unreachable.deficit;
for (auto varName: unreachable.variableChoices) for (auto varName: unreachable.variableChoices)
{ {
@ -230,7 +229,7 @@ void eliminateVariablesOptimizedCodegen(
} }
Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate), true); Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate), true);
// Do not remove functions. // Do not remove functions.
set<YulString> allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); std::set<YulString> allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names();
UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions); UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions);
} }
@ -245,7 +244,7 @@ bool StackCompressor::run(
{ {
yulAssert( yulAssert(
_object.code && _object.code &&
_object.code->statements.size() > 0 && holds_alternative<Block>(_object.code->statements.at(0)), _object.code->statements.size() > 0 && std::holds_alternative<Block>(_object.code->statements.at(0)),
"Need to run the function grouper before the stack compressor." "Need to run the function grouper before the stack compressor."
); );
bool usesOptimizedCodeGenerator = false; bool usesOptimizedCodeGenerator = false;
@ -258,7 +257,7 @@ bool StackCompressor::run(
if (usesOptimizedCodeGenerator) if (usesOptimizedCodeGenerator)
{ {
yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, *_object.code); std::unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, *_object.code);
eliminateVariablesOptimizedCodegen( eliminateVariablesOptimizedCodegen(
_dialect, _dialect,
*_object.code, *_object.code,
@ -269,7 +268,7 @@ bool StackCompressor::run(
else else
for (size_t iterations = 0; iterations < _maxIterations; iterations++) for (size_t iterations = 0; iterations < _maxIterations; iterations++)
{ {
map<YulString, int> stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit; std::map<YulString, int> stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit;
if (stackSurplus.empty()) if (stackSurplus.empty())
return true; return true;
eliminateVariables( eliminateVariables(

View File

@ -36,7 +36,6 @@
#include <range/v3/view/concat.hpp> #include <range/v3/view/concat.hpp>
#include <range/v3/view/take.hpp> #include <range/v3/view/take.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -97,16 +96,16 @@ struct MemoryOffsetAllocator
/// Maps function names to the set of unreachable variables in that function. /// Maps function names to the set of unreachable variables in that function.
/// An empty variable name means that the function has too many arguments or return variables. /// An empty variable name means that the function has too many arguments or return variables.
map<YulString, vector<YulString>> const& unreachableVariables; std::map<YulString, std::vector<YulString>> const& unreachableVariables;
/// The graph of immediate function calls of all functions. /// The graph of immediate function calls of all functions.
map<YulString, vector<YulString>> const& callGraph; std::map<YulString, std::vector<YulString>> const& callGraph;
/// Maps the name of each user-defined function to its definition. /// Maps the name of each user-defined function to its definition.
map<YulString, FunctionDefinition const*> const& functionDefinitions; std::map<YulString, FunctionDefinition const*> const& functionDefinitions;
/// Maps variable names to the memory slot the respective variable is assigned. /// Maps variable names to the memory slot the respective variable is assigned.
map<YulString, uint64_t> slotAllocations{}; std::map<YulString, uint64_t> slotAllocations{};
/// Maps function names to the number of memory slots the respective function requires. /// Maps function names to the number of memory slots the respective function requires.
map<YulString, uint64_t> slotsRequiredForFunction{}; std::map<YulString, uint64_t> slotsRequiredForFunction{};
}; };
u256 literalArgumentValue(FunctionCall const& _call) u256 literalArgumentValue(FunctionCall const& _call)
@ -131,7 +130,7 @@ void StackLimitEvader::run(
if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall())
{ {
yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object); yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code); std::unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code);
run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg)); run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg));
} }
else else
@ -146,10 +145,10 @@ void StackLimitEvader::run(
void StackLimitEvader::run( void StackLimitEvader::run(
OptimiserStepContext& _context, OptimiserStepContext& _context,
Object& _object, Object& _object,
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> const& _stackTooDeepErrors std::map<YulString, std::vector<StackLayoutGenerator::StackTooDeep>> const& _stackTooDeepErrors
) )
{ {
map<YulString, vector<YulString>> unreachableVariables; std::map<YulString, std::vector<YulString>> unreachableVariables;
for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors) for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors)
{ {
auto& unreachables = unreachableVariables[function]; auto& unreachables = unreachableVariables[function];
@ -165,7 +164,7 @@ void StackLimitEvader::run(
void StackLimitEvader::run( void StackLimitEvader::run(
OptimiserStepContext& _context, OptimiserStepContext& _context,
Object& _object, Object& _object,
map<YulString, vector<YulString>> const& _unreachableVariables std::map<YulString, std::vector<YulString>> const& _unreachableVariables
) )
{ {
yulAssert(_object.code, ""); yulAssert(_object.code, "");
@ -175,7 +174,7 @@ void StackLimitEvader::run(
"StackLimitEvader can only be run on objects using the EVMDialect with object access." "StackLimitEvader can only be run on objects using the EVMDialect with object access."
); );
vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run( std::vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run(
*_object.code, *_object.code,
"memoryguard"_yulstring "memoryguard"_yulstring
); );
@ -198,7 +197,7 @@ void StackLimitEvader::run(
if (_unreachableVariables.count(function)) if (_unreachableVariables.count(function))
return; return;
map<YulString, FunctionDefinition const*> functionDefinitions = allFunctionDefinitions(*_object.code); std::map<YulString, FunctionDefinition const*> functionDefinitions = allFunctionDefinitions(*_object.code);
MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions};
uint64_t requiredSlots = memoryOffsetAllocator.run(); uint64_t requiredSlots = memoryOffsetAllocator.run();

View File

@ -29,22 +29,21 @@
#include <range/v3/view/zip.hpp> #include <range/v3/view/zip.hpp>
#include <range/v3/range/conversion.hpp> #include <range/v3/range/conversion.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
namespace namespace
{ {
vector<Statement> generateMemoryStore( std::vector<Statement> generateMemoryStore(
Dialect const& _dialect, Dialect const& _dialect,
shared_ptr<DebugData const> const& _debugData, std::shared_ptr<DebugData const> const& _debugData,
YulString _mpos, YulString _mpos,
Expression _value Expression _value
) )
{ {
BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType); BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType);
yulAssert(memoryStoreFunction, ""); yulAssert(memoryStoreFunction, "");
vector<Statement> result; std::vector<Statement> result;
result.emplace_back(ExpressionStatement{_debugData, FunctionCall{ result.emplace_back(ExpressionStatement{_debugData, FunctionCall{
_debugData, _debugData,
Identifier{_debugData, memoryStoreFunction->name}, Identifier{_debugData, memoryStoreFunction->name},
@ -77,7 +76,7 @@ FunctionCall generateMemoryLoad(Dialect const& _dialect, std::shared_ptr<DebugDa
void StackToMemoryMover::run( void StackToMemoryMover::run(
OptimiserStepContext& _context, OptimiserStepContext& _context,
u256 _reservedMemory, u256 _reservedMemory,
map<YulString, uint64_t> const& _memorySlots, std::map<YulString, uint64_t> const& _memorySlots,
uint64_t _numRequiredSlots, uint64_t _numRequiredSlots,
Block& _block Block& _block
) )
@ -91,7 +90,7 @@ void StackToMemoryMover::run(
util::mapTuple([](YulString _name, FunctionDefinition const* _funDef) { util::mapTuple([](YulString _name, FunctionDefinition const* _funDef) {
return make_pair(_name, _funDef->returnVariables); return make_pair(_name, _funDef->returnVariables);
}), }),
map<YulString, TypedNameList>{} std::map<YulString, TypedNameList>{}
) )
); );
stackToMemoryMover(_block); stackToMemoryMover(_block);
@ -101,7 +100,7 @@ void StackToMemoryMover::run(
StackToMemoryMover::StackToMemoryMover( StackToMemoryMover::StackToMemoryMover(
OptimiserStepContext& _context, OptimiserStepContext& _context,
VariableMemoryOffsetTracker const& _memoryOffsetTracker, VariableMemoryOffsetTracker const& _memoryOffsetTracker,
map<YulString, TypedNameList> _functionReturnVariables std::map<YulString, TypedNameList> _functionReturnVariables
): ):
m_context(_context), m_context(_context),
m_memoryOffsetTracker(_memoryOffsetTracker), m_memoryOffsetTracker(_memoryOffsetTracker),
@ -121,7 +120,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
// variable arguments we might generate below. // variable arguments we might generate below.
ASTModifier::operator()(_functionDefinition); ASTModifier::operator()(_functionDefinition);
vector<Statement> memoryVariableInits; std::vector<Statement> memoryVariableInits;
// All function parameters with a memory slot are moved at the beginning of the function body. // All function parameters with a memory slot are moved at the beginning of the function body.
for (TypedName const& param: _functionDefinition.parameters) for (TypedName const& param: _functionDefinition.parameters)
@ -147,7 +146,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
if (_functionDefinition.returnVariables.size() == 1 && m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name)) if (_functionDefinition.returnVariables.size() == 1 && m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name))
{ {
TypedNameList stackParameters = _functionDefinition.parameters | ranges::views::filter( TypedNameList stackParameters = _functionDefinition.parameters | ranges::views::filter(
not_fn(m_memoryOffsetTracker) std::not_fn(m_memoryOffsetTracker)
) | ranges::to<TypedNameList>; ) | ranges::to<TypedNameList>;
// Generate new function without return variable and with only the non-moved parameters. // Generate new function without return variable and with only the non-moved parameters.
YulString newFunctionName = m_context.dispenser.newName(_functionDefinition.name); YulString newFunctionName = m_context.dispenser.newName(_functionDefinition.name);
@ -173,13 +172,13 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
Identifier{_functionDefinition.debugData, newFunctionName}, Identifier{_functionDefinition.debugData, newFunctionName},
stackParameters | ranges::views::transform([&](TypedName const& _arg) { stackParameters | ranges::views::transform([&](TypedName const& _arg) {
return Expression{Identifier{_arg.debugData, newArgumentNames.at(_arg.name)}}; return Expression{Identifier{_arg.debugData, newArgumentNames.at(_arg.name)}};
}) | ranges::to<vector<Expression>> }) | ranges::to<std::vector<Expression>>
} }
}); });
_functionDefinition.body.statements.emplace_back(Assignment{ _functionDefinition.body.statements.emplace_back(Assignment{
_functionDefinition.debugData, _functionDefinition.debugData,
{Identifier{_functionDefinition.debugData, _functionDefinition.returnVariables.front().name}}, {Identifier{_functionDefinition.debugData, _functionDefinition.returnVariables.front().name}},
make_unique<Expression>(generateMemoryLoad( std::make_unique<Expression>(generateMemoryLoad(
m_context.dialect, m_context.dialect,
_functionDefinition.debugData, _functionDefinition.debugData,
*m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name) *m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name)
@ -192,24 +191,24 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
_functionDefinition.body.statements = std::move(memoryVariableInits) + std::move(_functionDefinition.body.statements); _functionDefinition.body.statements = std::move(memoryVariableInits) + std::move(_functionDefinition.body.statements);
_functionDefinition.returnVariables = _functionDefinition.returnVariables | ranges::views::filter( _functionDefinition.returnVariables = _functionDefinition.returnVariables | ranges::views::filter(
not_fn(m_memoryOffsetTracker) std::not_fn(m_memoryOffsetTracker)
) | ranges::to<TypedNameList>; ) | ranges::to<TypedNameList>;
} }
void StackToMemoryMover::operator()(Block& _block) void StackToMemoryMover::operator()(Block& _block)
{ {
using OptionalStatements = optional<vector<Statement>>; using OptionalStatements = std::optional<std::vector<Statement>>;
auto rewriteAssignmentOrVariableDeclarationLeftHandSide = [this]( auto rewriteAssignmentOrVariableDeclarationLeftHandSide = [this](
auto& _stmt, auto& _stmt,
auto& _lhsVars auto& _lhsVars
) -> OptionalStatements { ) -> OptionalStatements {
using StatementType = decay_t<decltype(_stmt)>; using StatementType = std::decay_t<decltype(_stmt)>;
auto debugData = _stmt.debugData; auto debugData = _stmt.debugData;
if (_lhsVars.size() == 1) if (_lhsVars.size() == 1)
{ {
if (optional<YulString> offset = m_memoryOffsetTracker(_lhsVars.front().name)) if (std::optional<YulString> offset = m_memoryOffsetTracker(_lhsVars.front().name))
return generateMemoryStore( return generateMemoryStore(
m_context.dialect, m_context.dialect,
debugData, debugData,
@ -219,48 +218,48 @@ void StackToMemoryMover::operator()(Block& _block)
else else
return {}; return {};
} }
vector<optional<YulString>> rhsMemorySlots; std::vector<std::optional<YulString>> rhsMemorySlots;
if (_stmt.value) if (_stmt.value)
{ {
FunctionCall const* functionCall = get_if<FunctionCall>(_stmt.value.get()); FunctionCall const* functionCall = std::get_if<FunctionCall>(_stmt.value.get());
yulAssert(functionCall, ""); yulAssert(functionCall, "");
if (m_context.dialect.builtin(functionCall->functionName.name)) if (m_context.dialect.builtin(functionCall->functionName.name))
rhsMemorySlots = vector<optional<YulString>>(_lhsVars.size(), nullopt); rhsMemorySlots = std::vector<std::optional<YulString>>(_lhsVars.size(), std::nullopt);
else else
rhsMemorySlots = rhsMemorySlots =
m_functionReturnVariables.at(functionCall->functionName.name) | m_functionReturnVariables.at(functionCall->functionName.name) |
ranges::views::transform(m_memoryOffsetTracker) | ranges::views::transform(m_memoryOffsetTracker) |
ranges::to<vector<optional<YulString>>>; ranges::to<std::vector<std::optional<YulString>>>;
} }
else else
rhsMemorySlots = vector<optional<YulString>>(_lhsVars.size(), nullopt); rhsMemorySlots = std::vector<std::optional<YulString>>(_lhsVars.size(), std::nullopt);
// Nothing to do, if the right-hand-side remains entirely on the stack and // Nothing to do, if the right-hand-side remains entirely on the stack and
// none of the variables in the left-hand-side are moved. // none of the variables in the left-hand-side are moved.
if ( if (
ranges::none_of(rhsMemorySlots, [](optional<YulString> const& _slot) { return _slot.has_value(); }) && ranges::none_of(rhsMemorySlots, [](std::optional<YulString> const& _slot) { return _slot.has_value(); }) &&
!util::contains_if(_lhsVars, m_memoryOffsetTracker) !util::contains_if(_lhsVars, m_memoryOffsetTracker)
) )
return {}; return {};
vector<Statement> memoryAssignments; std::vector<Statement> memoryAssignments;
vector<Statement> variableAssignments; std::vector<Statement> variableAssignments;
VariableDeclaration tempDecl{debugData, {}, std::move(_stmt.value)}; VariableDeclaration tempDecl{debugData, {}, std::move(_stmt.value)};
yulAssert(rhsMemorySlots.size() == _lhsVars.size(), ""); yulAssert(rhsMemorySlots.size() == _lhsVars.size(), "");
for (auto&& [lhsVar, rhsSlot]: ranges::views::zip(_lhsVars, rhsMemorySlots)) for (auto&& [lhsVar, rhsSlot]: ranges::views::zip(_lhsVars, rhsMemorySlots))
{ {
unique_ptr<Expression> rhs; std::unique_ptr<Expression> rhs;
if (rhsSlot) if (rhsSlot)
rhs = make_unique<Expression>(generateMemoryLoad(m_context.dialect, debugData, *rhsSlot)); rhs = std::make_unique<Expression>(generateMemoryLoad(m_context.dialect, debugData, *rhsSlot));
else else
{ {
YulString tempVarName = m_nameDispenser.newName(lhsVar.name); YulString tempVarName = m_nameDispenser.newName(lhsVar.name);
tempDecl.variables.emplace_back(TypedName{lhsVar.debugData, tempVarName, {}}); tempDecl.variables.emplace_back(TypedName{lhsVar.debugData, tempVarName, {}});
rhs = make_unique<Expression>(Identifier{debugData, tempVarName}); rhs = std::make_unique<Expression>(Identifier{debugData, tempVarName});
} }
if (optional<YulString> offset = m_memoryOffsetTracker(lhsVar.name)) if (std::optional<YulString> offset = m_memoryOffsetTracker(lhsVar.name))
memoryAssignments += generateMemoryStore( memoryAssignments += generateMemoryStore(
m_context.dialect, m_context.dialect,
_stmt.debugData, _stmt.debugData,
@ -275,7 +274,7 @@ void StackToMemoryMover::operator()(Block& _block)
}); });
} }
vector<Statement> result; std::vector<Statement> result;
if (tempDecl.variables.empty()) if (tempDecl.variables.empty())
result.emplace_back(ExpressionStatement{debugData, *std::move(tempDecl.value)}); result.emplace_back(ExpressionStatement{debugData, *std::move(tempDecl.value)});
else else
@ -292,9 +291,9 @@ void StackToMemoryMover::operator()(Block& _block)
[&](Statement& _statement) -> OptionalStatements [&](Statement& _statement) -> OptionalStatements
{ {
visit(_statement); visit(_statement);
if (auto* assignment = get_if<Assignment>(&_statement)) if (auto* assignment = std::get_if<Assignment>(&_statement))
return rewriteAssignmentOrVariableDeclarationLeftHandSide(*assignment, assignment->variableNames); return rewriteAssignmentOrVariableDeclarationLeftHandSide(*assignment, assignment->variableNames);
else if (auto* varDecl = get_if<VariableDeclaration>(&_statement)) else if (auto* varDecl = std::get_if<VariableDeclaration>(&_statement))
return rewriteAssignmentOrVariableDeclarationLeftHandSide(*varDecl, varDecl->variables); return rewriteAssignmentOrVariableDeclarationLeftHandSide(*varDecl, varDecl->variables);
return {}; return {};
} }
@ -304,12 +303,12 @@ void StackToMemoryMover::operator()(Block& _block)
void StackToMemoryMover::visit(Expression& _expression) void StackToMemoryMover::visit(Expression& _expression)
{ {
ASTModifier::visit(_expression); ASTModifier::visit(_expression);
if (Identifier* identifier = get_if<Identifier>(&_expression)) if (Identifier* identifier = std::get_if<Identifier>(&_expression))
if (optional<YulString> offset = m_memoryOffsetTracker(identifier->name)) if (std::optional<YulString> offset = m_memoryOffsetTracker(identifier->name))
_expression = generateMemoryLoad(m_context.dialect, identifier->debugData, *offset); _expression = generateMemoryLoad(m_context.dialect, identifier->debugData, *offset);
} }
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const std::optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const
{ {
if (m_memorySlots.count(_variable)) if (m_memorySlots.count(_variable))
{ {
@ -318,15 +317,15 @@ optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(
return YulString{toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))}; return YulString{toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))};
} }
else else
return nullopt; return std::nullopt;
} }
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(TypedName const& _variable) const std::optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(TypedName const& _variable) const
{ {
return (*this)(_variable.name); return (*this)(_variable.name);
} }
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(Identifier const& _variable) const std::optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(Identifier const& _variable) const
{ {
return (*this)(_variable.name); return (*this)(_variable.name);
} }

View File

@ -21,11 +21,10 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/Visitor.h> #include <libsolutil/Visitor.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using OptionalStatements = std::optional<vector<Statement>>; using OptionalStatements = std::optional<std::vector<Statement>>;
namespace namespace
{ {
@ -52,12 +51,12 @@ OptionalStatements replaceConstArgSwitch(Switch& _switchStmt, u256 const& _const
if (matchingCaseBlock) if (matchingCaseBlock)
return util::make_vector<Statement>(std::move(*matchingCaseBlock)); return util::make_vector<Statement>(std::move(*matchingCaseBlock));
else else
return optional<vector<Statement>>{vector<Statement>{}}; return std::optional<std::vector<Statement>>{std::vector<Statement>{}};
} }
optional<u256> hasLiteralValue(Expression const& _expression) std::optional<u256> hasLiteralValue(Expression const& _expression)
{ {
if (holds_alternative<Literal>(_expression)) if (std::holds_alternative<Literal>(_expression))
return valueOfLiteral(std::get<Literal>(_expression)); return valueOfLiteral(std::get<Literal>(_expression));
else else
return std::optional<u256>(); return std::optional<u256>();
@ -99,7 +98,7 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
if (expressionAlwaysTrue(*_ifStmt.condition)) if (expressionAlwaysTrue(*_ifStmt.condition))
return {std::move(_ifStmt.body.statements)}; return {std::move(_ifStmt.body.statements)};
else if (expressionAlwaysFalse(*_ifStmt.condition)) else if (expressionAlwaysFalse(*_ifStmt.condition))
return {vector<Statement>{}}; return {std::vector<Statement>{}};
return {}; return {};
}, },
[&](Switch& _switchStmt) -> OptionalStatements { [&](Switch& _switchStmt) -> OptionalStatements {

View File

@ -23,13 +23,12 @@
#include <libyul/AST.h> #include <libyul/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
Expression Substitution::translate(Expression const& _expression) Expression Substitution::translate(Expression const& _expression)
{ {
if (holds_alternative<Identifier>(_expression)) if (std::holds_alternative<Identifier>(_expression))
{ {
YulString name = std::get<Identifier>(_expression).name; YulString name = std::get<Identifier>(_expression).name;
if (m_substitutions.count(name)) if (m_substitutions.count(name))

View File

@ -86,12 +86,12 @@
#include <fmt/format.h> #include <fmt/format.h>
#endif #endif
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
#ifdef PROFILE_OPTIMIZER_STEPS #ifdef PROFILE_OPTIMIZER_STEPS
using namespace std::chrono; using namespace std::chrono;
#endif #endif
using namespace std::string_literals;
namespace namespace
{ {
@ -136,10 +136,10 @@ void OptimiserSuite::run(
GasMeter const* _meter, GasMeter const* _meter,
Object& _object, Object& _object,
bool _optimizeStackAllocation, bool _optimizeStackAllocation,
string_view _optimisationSequence, std::string_view _optimisationSequence,
string_view _optimisationCleanupSequence, std::string_view _optimisationCleanupSequence,
optional<size_t> _expectedExecutionsPerDeployment, std::optional<size_t> _expectedExecutionsPerDeployment,
set<YulString> const& _externallyUsedIdentifiers std::set<YulString> const& _externallyUsedIdentifiers
) )
{ {
EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect); EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect);
@ -148,7 +148,7 @@ void OptimiserSuite::run(
evmDialect && evmDialect &&
evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->evmVersion().canOverchargeGasForCall() &&
evmDialect->providesObjectAccess(); evmDialect->providesObjectAccess();
set<YulString> reservedIdentifiers = _externallyUsedIdentifiers; std::set<YulString> reservedIdentifiers = _externallyUsedIdentifiers;
reservedIdentifiers += _dialect.fixedFunctionNames(); reservedIdentifiers += _dialect.fixedFunctionNames();
*_object.code = std::get<Block>(Disambiguator( *_object.code = std::get<Block>(Disambiguator(
@ -226,11 +226,11 @@ namespace
{ {
template <class... Step> template <class... Step>
map<string, unique_ptr<OptimiserStep>> optimiserStepCollection() std::map<std::string, std::unique_ptr<OptimiserStep>> optimiserStepCollection()
{ {
map<string, unique_ptr<OptimiserStep>> ret; std::map<std::string, std::unique_ptr<OptimiserStep>> ret;
for (unique_ptr<OptimiserStep>& s: util::make_vector<unique_ptr<OptimiserStep>>( for (std::unique_ptr<OptimiserStep>& s: util::make_vector<std::unique_ptr<OptimiserStep>>(
(make_unique<OptimiserStepInstance<Step>>())... (std::make_unique<OptimiserStepInstance<Step>>())...
)) ))
{ {
yulAssert(!ret.count(s->name), ""); yulAssert(!ret.count(s->name), "");
@ -241,9 +241,9 @@ map<string, unique_ptr<OptimiserStep>> optimiserStepCollection()
} }
map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps() std::map<std::string, std::unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
{ {
static map<string, unique_ptr<OptimiserStep>> instance; static std::map<std::string, std::unique_ptr<OptimiserStep>> instance;
if (instance.empty()) if (instance.empty())
instance = optimiserStepCollection< instance = optimiserStepCollection<
BlockFlattener, BlockFlattener,
@ -284,9 +284,9 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
return instance; return instance;
} }
map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap() std::map<std::string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
{ {
static map<string, char> lookupTable{ static std::map<std::string, char> lookupTable{
{BlockFlattener::name, 'f'}, {BlockFlattener::name, 'f'},
{CircularReferencesPruner::name, 'l'}, {CircularReferencesPruner::name, 'l'},
{CommonSubexpressionEliminator::name, 'c'}, {CommonSubexpressionEliminator::name, 'c'},
@ -322,23 +322,23 @@ map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
}; };
yulAssert(lookupTable.size() == allSteps().size(), ""); yulAssert(lookupTable.size() == allSteps().size(), "");
yulAssert(( yulAssert((
util::convertContainer<set<char>>(string(NonStepAbbreviations)) - util::convertContainer<std::set<char>>(std::string(NonStepAbbreviations)) -
util::convertContainer<set<char>>(lookupTable | ranges::views::values) util::convertContainer<std::set<char>>(lookupTable | ranges::views::values)
).size() == string(NonStepAbbreviations).size(), ).size() == std::string(NonStepAbbreviations).size(),
"Step abbreviation conflicts with a character reserved for another syntactic element" "Step abbreviation conflicts with a character reserved for another syntactic element"
); );
return lookupTable; return lookupTable;
} }
map<char, string> const& OptimiserSuite::stepAbbreviationToNameMap() std::map<char, std::string> const& OptimiserSuite::stepAbbreviationToNameMap()
{ {
static map<char, string> lookupTable = util::invertMap(stepNameToAbbreviationMap()); static std::map<char, std::string> lookupTable = util::invertMap(stepNameToAbbreviationMap());
return lookupTable; return lookupTable;
} }
void OptimiserSuite::validateSequence(string_view _stepAbbreviations) void OptimiserSuite::validateSequence(std::string_view _stepAbbreviations)
{ {
int8_t nestingLevel = 0; int8_t nestingLevel = 0;
int8_t colonDelimiters = 0; int8_t colonDelimiters = 0;
@ -349,7 +349,7 @@ void OptimiserSuite::validateSequence(string_view _stepAbbreviations)
case '\n': case '\n':
break; break;
case '[': case '[':
assertThrow(nestingLevel < numeric_limits<int8_t>::max(), OptimizerException, "Brackets nested too deep"); assertThrow(nestingLevel < std::numeric_limits<int8_t>::max(), OptimizerException, "Brackets nested too deep");
nestingLevel++; nestingLevel++;
break; break;
case ']': case ']':
@ -364,7 +364,7 @@ void OptimiserSuite::validateSequence(string_view _stepAbbreviations)
default: default:
{ {
yulAssert( yulAssert(
string(NonStepAbbreviations).find(abbreviation) == string::npos, std::string(NonStepAbbreviations).find(abbreviation) == std::string::npos,
"Unhandled syntactic element in the abbreviation sequence" "Unhandled syntactic element in the abbreviation sequence"
); );
assertThrow( assertThrow(
@ -372,7 +372,7 @@ void OptimiserSuite::validateSequence(string_view _stepAbbreviations)
OptimizerException, OptimizerException,
"'"s + abbreviation + "' is not a valid step abbreviation" "'"s + abbreviation + "' is not a valid step abbreviation"
); );
optional<string> invalid = allSteps().at(stepAbbreviationToNameMap().at(abbreviation))->invalidInCurrentEnvironment(); std::optional<std::string> invalid = allSteps().at(stepAbbreviationToNameMap().at(abbreviation))->invalidInCurrentEnvironment();
assertThrow( assertThrow(
!invalid.has_value(), !invalid.has_value(),
OptimizerException, OptimizerException,
@ -383,12 +383,12 @@ void OptimiserSuite::validateSequence(string_view _stepAbbreviations)
assertThrow(nestingLevel == 0, OptimizerException, "Unbalanced brackets"); assertThrow(nestingLevel == 0, OptimizerException, "Unbalanced brackets");
} }
void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable) void OptimiserSuite::runSequence(std::string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable)
{ {
validateSequence(_stepAbbreviations); validateSequence(_stepAbbreviations);
// This splits 'aaa[bbb]ccc...' into 'aaa' and '[bbb]ccc...'. // This splits 'aaa[bbb]ccc...' into 'aaa' and '[bbb]ccc...'.
auto extractNonNestedPrefix = [](string_view _tail) -> tuple<string_view, string_view> auto extractNonNestedPrefix = [](std::string_view _tail) -> std::tuple<std::string_view, std::string_view>
{ {
for (size_t i = 0; i < _tail.size(); ++i) for (size_t i = 0; i < _tail.size(); ++i)
{ {
@ -400,7 +400,7 @@ void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast, bo
}; };
// This splits '[bbb]ccc...' into 'bbb' and 'ccc...'. // This splits '[bbb]ccc...' into 'bbb' and 'ccc...'.
auto extractBracketContent = [](string_view _tail) -> tuple<string_view, string_view> auto extractBracketContent = [](std::string_view _tail) -> std::tuple<std::string_view, std::string_view>
{ {
yulAssert(!_tail.empty() && _tail[0] == '['); yulAssert(!_tail.empty() && _tail[0] == '[');
@ -410,7 +410,7 @@ void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast, bo
{ {
if (abbreviation == '[') if (abbreviation == '[')
{ {
yulAssert(nestingLevel < numeric_limits<int8_t>::max()); yulAssert(nestingLevel < std::numeric_limits<int8_t>::max());
++nestingLevel; ++nestingLevel;
} }
else if (abbreviation == ']') else if (abbreviation == ']')
@ -427,20 +427,20 @@ void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast, bo
return {_tail.substr(1, contentLength), _tail.substr(contentLength + 2)}; return {_tail.substr(1, contentLength), _tail.substr(contentLength + 2)};
}; };
auto abbreviationsToSteps = [](string_view _sequence) -> vector<string> auto abbreviationsToSteps = [](std::string_view _sequence) -> std::vector<std::string>
{ {
vector<string> steps; std::vector<std::string> steps;
for (char abbreviation: _sequence) for (char abbreviation: _sequence)
if (abbreviation != ' ' && abbreviation != '\n') if (abbreviation != ' ' && abbreviation != '\n')
steps.emplace_back(stepAbbreviationToNameMap().at(abbreviation)); steps.emplace_back(stepAbbreviationToNameMap().at(abbreviation));
return steps; return steps;
}; };
vector<tuple<string_view, bool>> subsequences; std::vector<std::tuple<std::string_view, bool>> subsequences;
string_view tail = _stepAbbreviations; std::string_view tail = _stepAbbreviations;
while (!tail.empty()) while (!tail.empty())
{ {
string_view subsequence; std::string_view subsequence;
tie(subsequence, tail) = extractNonNestedPrefix(tail); tie(subsequence, tail) = extractNonNestedPrefix(tail);
if (subsequence.size() > 0) if (subsequence.size() > 0)
subsequences.push_back({subsequence, false}); subsequences.push_back({subsequence, false});
@ -474,15 +474,15 @@ void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast, bo
} }
} }
void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast) void OptimiserSuite::runSequence(std::vector<std::string> const& _steps, Block& _ast)
{ {
unique_ptr<Block> copy; std::unique_ptr<Block> copy;
if (m_debug == Debug::PrintChanges) if (m_debug == Debug::PrintChanges)
copy = make_unique<Block>(std::get<Block>(ASTCopier{}(_ast))); copy = std::make_unique<Block>(std::get<Block>(ASTCopier{}(_ast)));
for (string const& step: _steps) for (std::string const& step: _steps)
{ {
if (m_debug == Debug::PrintStep) if (m_debug == Debug::PrintStep)
cout << "Running " << step << endl; std::cout << "Running " << step << std::endl;
#ifdef PROFILE_OPTIMIZER_STEPS #ifdef PROFILE_OPTIMIZER_STEPS
steady_clock::time_point startTime = steady_clock::now(); steady_clock::time_point startTime = steady_clock::now();
#endif #endif
@ -495,12 +495,12 @@ void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast)
{ {
// TODO should add switch to also compare variable names! // TODO should add switch to also compare variable names!
if (SyntacticallyEqual{}.statementEqual(_ast, *copy)) if (SyntacticallyEqual{}.statementEqual(_ast, *copy))
cout << "== Running " << step << " did not cause changes." << endl; std::cout << "== Running " << step << " did not cause changes." << std::endl;
else else
{ {
cout << "== Running " << step << " changed the AST." << endl; std::cout << "== Running " << step << " changed the AST." << std::endl;
cout << AsmPrinter{}(_ast) << endl; std::cout << AsmPrinter{}(_ast) << std::endl;
copy = make_unique<Block>(std::get<Block>(ASTCopier{}(_ast))); copy = std::make_unique<Block>(std::get<Block>(ASTCopier{}(_ast)));
} }
} }
} }

View File

@ -25,7 +25,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;

View File

@ -28,7 +28,6 @@
#include <libsolutil/Visitor.h> #include <libsolutil/Visitor.h>
using namespace std;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::util; using namespace solidity::util;
@ -81,7 +80,7 @@ YulString TypeInfo::typeOf(Expression const& _expression) const
return std::visit(GenericVisitor{ return std::visit(GenericVisitor{
[&](FunctionCall const& _funCall) { [&](FunctionCall const& _funCall) {
YulString name = _funCall.functionName.name; YulString name = _funCall.functionName.name;
vector<YulString> const* retTypes = nullptr; std::vector<YulString> const* retTypes = nullptr;
if (BuiltinFunction const* fun = m_dialect.builtin(name)) if (BuiltinFunction const* fun = m_dialect.builtin(name))
retTypes = &fun->returns; retTypes = &fun->returns;
else else

View File

@ -34,7 +34,6 @@
#include <iostream> #include <iostream>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -48,7 +47,7 @@ void UnusedAssignEliminator::run(OptimiserStepContext& _context, Block& _ast)
uae.m_storesToRemove += uae.m_allStores - uae.m_usedStores; uae.m_storesToRemove += uae.m_allStores - uae.m_usedStores;
set<Statement const*> toRemove{uae.m_storesToRemove.begin(), uae.m_storesToRemove.end()}; std::set<Statement const*> toRemove{uae.m_storesToRemove.begin(), uae.m_storesToRemove.end()};
StatementRemover remover{toRemove}; StatementRemover remover{toRemove};
remover(_ast); remover(_ast);
} }
@ -103,7 +102,7 @@ void UnusedAssignEliminator::operator()(Block const& _block)
UnusedStoreBase::operator()(_block); UnusedStoreBase::operator()(_block);
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
if (auto const* varDecl = get_if<VariableDeclaration>(&statement)) if (auto const* varDecl = std::get_if<VariableDeclaration>(&statement))
for (auto const& var: varDecl->variables) for (auto const& var: varDecl->variables)
m_activeStores.erase(var.name); m_activeStores.erase(var.name);
} }
@ -112,7 +111,7 @@ void UnusedAssignEliminator::visit(Statement const& _statement)
{ {
UnusedStoreBase::visit(_statement); UnusedStoreBase::visit(_statement);
if (auto const* assignment = get_if<Assignment>(&_statement)) if (auto const* assignment = std::get_if<Assignment>(&_statement))
{ {
// We do not remove assignments whose values might have side-effects, // We do not remove assignments whose values might have side-effects,
// but clear the active stores to the assigned variables in any case. // but clear the active stores to the assigned variables in any case.

View File

@ -36,14 +36,13 @@
#include <optional> #include <optional>
#include <variant> #include <variant>
using namespace std;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::yul::unusedFunctionsCommon; using namespace solidity::yul::unusedFunctionsCommon;
void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast) void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast)
{ {
map<YulString, size_t> references = VariableReferencesCounter::countReferences(_ast); std::map<YulString, size_t> references = VariableReferencesCounter::countReferences(_ast);
auto used = [&](auto v) -> bool { return references.count(v.name); }; auto used = [&](auto v) -> bool { return references.count(v.name); };
// Function name and a pair of boolean masks, the first corresponds to parameters and the second // Function name and a pair of boolean masks, the first corresponds to parameters and the second
@ -55,12 +54,12 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _
// Similarly for the second vector in the pair, a value `false` at index `i` indicates that the // Similarly for the second vector in the pair, a value `false` at index `i` indicates that the
// return parameter at index `i` in `FunctionDefinition::returnVariables` is unused inside // return parameter at index `i` in `FunctionDefinition::returnVariables` is unused inside
// function body. // function body.
map<YulString, pair<vector<bool>, vector<bool>>> usedParametersAndReturnVariables; std::map<YulString, std::pair<std::vector<bool>, std::vector<bool>>> usedParametersAndReturnVariables;
// Step 1 of UnusedFunctionParameterPruner: Find functions whose parameters (both arguments and // Step 1 of UnusedFunctionParameterPruner: Find functions whose parameters (both arguments and
// return-parameters) are not used in its body. // return-parameters) are not used in its body.
for (auto const& statement: _ast.statements) for (auto const& statement: _ast.statements)
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
{ {
FunctionDefinition const& f = std::get<FunctionDefinition>(statement); FunctionDefinition const& f = std::get<FunctionDefinition>(statement);
@ -73,7 +72,7 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _
}; };
} }
set<YulString> functionNamesToFree = util::keys(usedParametersAndReturnVariables); std::set<YulString> functionNamesToFree = util::keys(usedParametersAndReturnVariables);
// Step 2 of UnusedFunctionParameterPruner: Renames the function and replaces all references to // Step 2 of UnusedFunctionParameterPruner: Renames the function and replaces all references to
// the function, say `f`, by its new name, say `f_1`. // the function, say `f`, by its new name, say `f_1`.
@ -91,17 +90,17 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _
// For example: introduce a new 'linking' function `f` with the same the body as `f_1`, but with // For example: introduce a new 'linking' function `f` with the same the body as `f_1`, but with
// reduced parameters, i.e., `function f() -> y { y := 1 }`. Now replace the body of `f_1` with // reduced parameters, i.e., `function f() -> y { y := 1 }`. Now replace the body of `f_1` with
// a call to `f`, i.e., `f_1(x) -> y { y := f() }`. // a call to `f`, i.e., `f_1(x) -> y { y := f() }`.
iterateReplacing(_ast.statements, [&](Statement& _s) -> optional<vector<Statement>> { iterateReplacing(_ast.statements, [&](Statement& _s) -> std::optional<std::vector<Statement>> {
if (holds_alternative<FunctionDefinition>(_s)) if (std::holds_alternative<FunctionDefinition>(_s))
{ {
// The original function except that it has a new name (e.g., `f_1`) // The original function except that it has a new name (e.g., `f_1`)
FunctionDefinition& originalFunction = get<FunctionDefinition>(_s); FunctionDefinition& originalFunction = std::get<FunctionDefinition>(_s);
if (newToOriginalNames.count(originalFunction.name)) if (newToOriginalNames.count(originalFunction.name))
{ {
YulString linkingFunctionName = originalFunction.name; YulString linkingFunctionName = originalFunction.name;
YulString originalFunctionName = newToOriginalNames.at(linkingFunctionName); YulString originalFunctionName = newToOriginalNames.at(linkingFunctionName);
pair<vector<bool>, vector<bool>> used = std::pair<std::vector<bool>, std::vector<bool>> used =
usedParametersAndReturnVariables.at(originalFunctionName); usedParametersAndReturnVariables.at(originalFunctionName);
FunctionDefinition linkingFunction = createLinkingFunction( FunctionDefinition linkingFunction = createLinkingFunction(
@ -122,6 +121,6 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _
} }
} }
return nullopt; return std::nullopt;
}); });
} }

View File

@ -30,7 +30,6 @@
#include <libyul/Dialect.h> #include <libyul/Dialect.h>
#include <libyul/SideEffects.h> #include <libyul/SideEffects.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -44,8 +43,8 @@ UnusedPruner::UnusedPruner(
Dialect const& _dialect, Dialect const& _dialect,
Block& _ast, Block& _ast,
bool _allowMSizeOptimization, bool _allowMSizeOptimization,
map<YulString, SideEffects> const* _functionSideEffects, std::map<YulString, SideEffects> const* _functionSideEffects,
set<YulString> const& _externallyUsedFunctions std::set<YulString> const& _externallyUsedFunctions
): ):
m_dialect(_dialect), m_dialect(_dialect),
m_allowMSizeOptimization(_allowMSizeOptimization), m_allowMSizeOptimization(_allowMSizeOptimization),
@ -60,7 +59,7 @@ UnusedPruner::UnusedPruner(
Dialect const& _dialect, Dialect const& _dialect,
FunctionDefinition& _function, FunctionDefinition& _function,
bool _allowMSizeOptimization, bool _allowMSizeOptimization,
set<YulString> const& _externallyUsedFunctions std::set<YulString> const& _externallyUsedFunctions
): ):
m_dialect(_dialect), m_dialect(_dialect),
m_allowMSizeOptimization(_allowMSizeOptimization) m_allowMSizeOptimization(_allowMSizeOptimization)
@ -73,7 +72,7 @@ UnusedPruner::UnusedPruner(
void UnusedPruner::operator()(Block& _block) void UnusedPruner::operator()(Block& _block)
{ {
for (auto&& statement: _block.statements) for (auto&& statement: _block.statements)
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
{ {
FunctionDefinition& funDef = std::get<FunctionDefinition>(statement); FunctionDefinition& funDef = std::get<FunctionDefinition>(statement);
if (!used(funDef.name)) if (!used(funDef.name))
@ -82,7 +81,7 @@ void UnusedPruner::operator()(Block& _block)
statement = Block{std::move(funDef.debugData), {}}; statement = Block{std::move(funDef.debugData), {}};
} }
} }
else if (holds_alternative<VariableDeclaration>(statement)) else if (std::holds_alternative<VariableDeclaration>(statement))
{ {
VariableDeclaration& varDecl = std::get<VariableDeclaration>(statement); VariableDeclaration& varDecl = std::get<VariableDeclaration>(statement);
// Multi-variable declarations are special. We can only remove it // Multi-variable declarations are special. We can only remove it
@ -114,7 +113,7 @@ void UnusedPruner::operator()(Block& _block)
}}; }};
} }
} }
else if (holds_alternative<ExpressionStatement>(statement)) else if (std::holds_alternative<ExpressionStatement>(statement))
{ {
ExpressionStatement& exprStmt = std::get<ExpressionStatement>(statement); ExpressionStatement& exprStmt = std::get<ExpressionStatement>(statement);
if ( if (
@ -136,8 +135,8 @@ void UnusedPruner::runUntilStabilised(
Dialect const& _dialect, Dialect const& _dialect,
Block& _ast, Block& _ast,
bool _allowMSizeOptimization, bool _allowMSizeOptimization,
map<YulString, SideEffects> const* _functionSideEffects, std::map<YulString, SideEffects> const* _functionSideEffects,
set<YulString> const& _externallyUsedFunctions std::set<YulString> const& _externallyUsedFunctions
) )
{ {
while (true) while (true)
@ -154,10 +153,10 @@ void UnusedPruner::runUntilStabilised(
void UnusedPruner::runUntilStabilisedOnFullAST( void UnusedPruner::runUntilStabilisedOnFullAST(
Dialect const& _dialect, Dialect const& _dialect,
Block& _ast, Block& _ast,
set<YulString> const& _externallyUsedFunctions std::set<YulString> const& _externallyUsedFunctions
) )
{ {
map<YulString, SideEffects> functionSideEffects = std::map<YulString, SideEffects> functionSideEffects =
SideEffectsPropagator::sideEffects(_dialect, CallGraphGenerator::callGraph(_ast)); SideEffectsPropagator::sideEffects(_dialect, CallGraphGenerator::callGraph(_ast));
bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast); bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast);
runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions);
@ -167,7 +166,7 @@ void UnusedPruner::runUntilStabilised(
Dialect const& _dialect, Dialect const& _dialect,
FunctionDefinition& _function, FunctionDefinition& _function,
bool _allowMSizeOptimization, bool _allowMSizeOptimization,
set<YulString> const& _externallyUsedFunctions std::set<YulString> const& _externallyUsedFunctions
) )
{ {
while (true) while (true)
@ -184,7 +183,7 @@ bool UnusedPruner::used(YulString _name) const
return m_references.count(_name) && m_references.at(_name) > 0; return m_references.count(_name) && m_references.at(_name) > 0;
} }
void UnusedPruner::subtractReferences(map<YulString, size_t> const& _subtrahend) void UnusedPruner::subtractReferences(std::map<YulString, size_t> const& _subtrahend)
{ {
for (auto const& ref: _subtrahend) for (auto const& ref: _subtrahend)
{ {

View File

@ -29,7 +29,6 @@
#include <range/v3/action/remove_if.hpp> #include <range/v3/action/remove_if.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -50,7 +49,7 @@ void UnusedStoreBase::operator()(Switch const& _switch)
ActiveStores const preState{m_activeStores}; ActiveStores const preState{m_activeStores};
bool hasDefault = false; bool hasDefault = false;
vector<ActiveStores> branches; std::vector<ActiveStores> branches;
for (auto const& c: _switch.cases) for (auto const& c: _switch.cases)
{ {
if (!c.value) if (!c.value)
@ -146,15 +145,15 @@ void UnusedStoreBase::operator()(Continue const&)
void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other)
{ {
util::joinMap(_target, std::move(_other), []( util::joinMap(_target, std::move(_other), [](
set<Statement const*>& _storesHere, std::set<Statement const*>& _storesHere,
set<Statement const*>&& _storesThere std::set<Statement const*>&& _storesThere
) )
{ {
_storesHere += _storesThere; _storesHere += _storesThere;
}); });
} }
void UnusedStoreBase::merge(ActiveStores& _target, vector<ActiveStores>&& _source) void UnusedStoreBase::merge(ActiveStores& _target, std::vector<ActiveStores>&& _source)
{ {
for (ActiveStores& ts: _source) for (ActiveStores& ts: _source)
merge(_target, std::move(ts)); merge(_target, std::move(ts));

View File

@ -40,26 +40,25 @@
#include <range/v3/algorithm/all_of.hpp> #include <range/v3/algorithm/all_of.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
/// Variable names for special constants that can never appear in actual Yul code. /// Variable names for special constants that can never appear in actual Yul code.
static string const zero{"@ 0"}; static std::string const zero{"@ 0"};
static string const one{"@ 1"}; static std::string const one{"@ 1"};
static string const thirtyTwo{"@ 32"}; static std::string const thirtyTwo{"@ 32"};
void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
{ {
map<YulString, SideEffects> functionSideEffects = SideEffectsPropagator::sideEffects( std::map<YulString, SideEffects> functionSideEffects = SideEffectsPropagator::sideEffects(
_context.dialect, _context.dialect,
CallGraphGenerator::callGraph(_ast) CallGraphGenerator::callGraph(_ast)
); );
SSAValueTracker ssaValues; SSAValueTracker ssaValues;
ssaValues(_ast); ssaValues(_ast);
map<YulString, AssignedValue> values; std::map<YulString, AssignedValue> values;
for (auto const& [name, expression]: ssaValues.values()) for (auto const& [name, expression]: ssaValues.values())
values[name] = AssignedValue{expression, {}}; values[name] = AssignedValue{expression, {}};
Expression const zeroLiteral{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; Expression const zeroLiteral{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}};
@ -87,16 +86,16 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
rse.markActiveAsUsed(Location::Storage); rse.markActiveAsUsed(Location::Storage);
rse.m_storesToRemove += rse.m_allStores - rse.m_usedStores; rse.m_storesToRemove += rse.m_allStores - rse.m_usedStores;
set<Statement const*> toRemove{rse.m_storesToRemove.begin(), rse.m_storesToRemove.end()}; std::set<Statement const*> toRemove{rse.m_storesToRemove.begin(), rse.m_storesToRemove.end()};
StatementRemover remover{toRemove}; StatementRemover remover{toRemove};
remover(_ast); remover(_ast);
} }
UnusedStoreEliminator::UnusedStoreEliminator( UnusedStoreEliminator::UnusedStoreEliminator(
Dialect const& _dialect, Dialect const& _dialect,
map<YulString, SideEffects> const& _functionSideEffects, std::map<YulString, SideEffects> const& _functionSideEffects,
map<YulString, ControlFlowSideEffects> _controlFlowSideEffects, std::map<YulString, ControlFlowSideEffects> _controlFlowSideEffects,
map<YulString, AssignedValue> const& _ssaValues, std::map<YulString, AssignedValue> const& _ssaValues,
bool _ignoreMemory bool _ignoreMemory
): ):
UnusedStoreBase(_dialect), UnusedStoreBase(_dialect),
@ -148,18 +147,18 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
UnusedStoreBase::visit(_statement); UnusedStoreBase::visit(_statement);
auto const* exprStatement = get_if<ExpressionStatement>(&_statement); auto const* exprStatement = std::get_if<ExpressionStatement>(&_statement);
if (!exprStatement) if (!exprStatement)
return; return;
FunctionCall const* funCall = get_if<FunctionCall>(&exprStatement->expression); FunctionCall const* funCall = std::get_if<FunctionCall>(&exprStatement->expression);
yulAssert(funCall); yulAssert(funCall);
optional<Instruction> instruction = toEVMInstruction(m_dialect, funCall->functionName.name); std::optional<Instruction> instruction = toEVMInstruction(m_dialect, funCall->functionName.name);
if (!instruction) if (!instruction)
return; return;
if (!ranges::all_of(funCall->arguments, [](Expression const& _expr) -> bool { if (!ranges::all_of(funCall->arguments, [](Expression const& _expr) -> bool {
return get_if<Identifier>(&_expr) || get_if<Literal>(&_expr); return std::get_if<Identifier>(&_expr) || std::get_if<Literal>(&_expr);
})) }))
return; return;
@ -195,7 +194,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
auto length = identifierNameIfSSA(funCall->arguments.at(2)); auto length = identifierNameIfSSA(funCall->arguments.at(2));
if (length && startOffset) if (length && startOffset)
{ {
FunctionCall const* lengthCall = get_if<FunctionCall>(m_ssaValues.at(*length).value); FunctionCall const* lengthCall = std::get_if<FunctionCall>(m_ssaValues.at(*length).value);
if ( if (
m_knowledgeBase.knownToBeZero(*startOffset) && m_knowledgeBase.knownToBeZero(*startOffset) &&
lengthCall && lengthCall &&
@ -207,7 +206,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
return; return;
} }
m_allStores.insert(&_statement); m_allStores.insert(&_statement);
vector<Operation> operations = operationsFromFunctionCall(*funCall); std::vector<Operation> operations = operationsFromFunctionCall(*funCall);
yulAssert(operations.size() == 1, ""); yulAssert(operations.size() == 1, "");
if (operations.front().location == Location::Storage) if (operations.front().location == Location::Storage)
activeStorageStores().insert(&_statement); activeStorageStores().insert(&_statement);
@ -217,7 +216,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
} }
} }
vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFunctionCall( std::vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFunctionCall(
FunctionCall const& _functionCall FunctionCall const& _functionCall
) const ) const
{ {
@ -230,10 +229,10 @@ vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFu
else else
sideEffects = m_functionSideEffects.at(functionName); sideEffects = m_functionSideEffects.at(functionName);
optional<Instruction> instruction = toEVMInstruction(m_dialect, functionName); std::optional<Instruction> instruction = toEVMInstruction(m_dialect, functionName);
if (!instruction) if (!instruction)
{ {
vector<Operation> result; std::vector<Operation> result;
// Unknown read is worse than unknown write. // Unknown read is worse than unknown write.
if (sideEffects.memory != SideEffects::Effect::None) if (sideEffects.memory != SideEffects::Effect::None)
result.emplace_back(Operation{Location::Memory, Effect::Read, {}, {}}); result.emplace_back(Operation{Location::Memory, Effect::Read, {}, {}});
@ -269,7 +268,7 @@ vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFu
void UnusedStoreEliminator::applyOperation(UnusedStoreEliminator::Operation const& _operation) void UnusedStoreEliminator::applyOperation(UnusedStoreEliminator::Operation const& _operation)
{ {
set<Statement const*>& active = std::set<Statement const*>& active =
_operation.location == Location::Storage ? _operation.location == Location::Storage ?
activeStorageStores() : activeStorageStores() :
activeMemoryStores(); activeMemoryStores();
@ -324,9 +323,9 @@ bool UnusedStoreEliminator::knownUnrelated(
if (_op1.start && _op1.length && _op2.start) if (_op1.start && _op1.length && _op2.start)
{ {
optional<u256> length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); std::optional<u256> length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length);
optional<u256> start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); std::optional<u256> start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start);
optional<u256> start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); std::optional<u256> start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start);
if ( if (
(length1 && start1 && start2) && (length1 && start1 && start2) &&
*start1 + *length1 >= *start1 && // no overflow *start1 + *length1 >= *start1 && // no overflow
@ -336,9 +335,9 @@ bool UnusedStoreEliminator::knownUnrelated(
} }
if (_op2.start && _op2.length && _op1.start) if (_op2.start && _op2.length && _op1.start)
{ {
optional<u256> length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); std::optional<u256> length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length);
optional<u256> start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); std::optional<u256> start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start);
optional<u256> start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); std::optional<u256> start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start);
if ( if (
(length2 && start2 && start1) && (length2 && start2 && start1) &&
*start2 + *length2 >= *start2 && // no overflow *start2 + *length2 >= *start2 && // no overflow
@ -349,8 +348,8 @@ bool UnusedStoreEliminator::knownUnrelated(
if (_op1.start && _op1.length && _op2.start && _op2.length) if (_op1.start && _op1.length && _op2.start && _op2.length)
{ {
optional<u256> length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); std::optional<u256> length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length);
optional<u256> length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); std::optional<u256> length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length);
if ( if (
(length1 && *length1 <= 32) && (length1 && *length1 <= 32) &&
(length2 && *length2 <= 32) && (length2 && *length2 <= 32) &&
@ -384,13 +383,13 @@ bool UnusedStoreEliminator::knownCovered(
// i.start <= e.start && e.start + e.length <= i.start + i.length // i.start <= e.start && e.start + e.length <= i.start + i.length
if (!_covered.start || !_covering.start || !_covered.length || !_covering.length) if (!_covered.start || !_covering.start || !_covered.length || !_covering.length)
return false; return false;
optional<u256> coveredLength = m_knowledgeBase.valueIfKnownConstant(*_covered.length); std::optional<u256> coveredLength = m_knowledgeBase.valueIfKnownConstant(*_covered.length);
optional<u256> coveringLength = m_knowledgeBase.valueIfKnownConstant(*_covering.length); std::optional<u256> coveringLength = m_knowledgeBase.valueIfKnownConstant(*_covering.length);
if (*_covered.start == *_covering.start) if (*_covered.start == *_covering.start)
if (coveredLength && coveringLength && *coveredLength <= *coveringLength) if (coveredLength && coveringLength && *coveredLength <= *coveringLength)
return true; return true;
optional<u256> coveredStart = m_knowledgeBase.valueIfKnownConstant(*_covered.start); std::optional<u256> coveredStart = m_knowledgeBase.valueIfKnownConstant(*_covered.start);
optional<u256> coveringStart = m_knowledgeBase.valueIfKnownConstant(*_covering.start); std::optional<u256> coveringStart = m_knowledgeBase.valueIfKnownConstant(*_covering.start);
if (coveredStart && coveringStart && coveredLength && coveringLength) if (coveredStart && coveringStart && coveredLength && coveringLength)
if ( if (
*coveringStart <= *coveredStart && *coveringStart <= *coveredStart &&
@ -408,32 +407,32 @@ bool UnusedStoreEliminator::knownCovered(
} }
void UnusedStoreEliminator::markActiveAsUsed( void UnusedStoreEliminator::markActiveAsUsed(
optional<UnusedStoreEliminator::Location> _onlyLocation std::optional<UnusedStoreEliminator::Location> _onlyLocation
) )
{ {
if (_onlyLocation == nullopt || _onlyLocation == Location::Memory) if (_onlyLocation == std::nullopt || _onlyLocation == Location::Memory)
for (Statement const* statement: activeMemoryStores()) for (Statement const* statement: activeMemoryStores())
m_usedStores.insert(statement); m_usedStores.insert(statement);
if (_onlyLocation == nullopt || _onlyLocation == Location::Storage) if (_onlyLocation == std::nullopt || _onlyLocation == Location::Storage)
for (Statement const* statement: activeStorageStores()) for (Statement const* statement: activeStorageStores())
m_usedStores.insert(statement); m_usedStores.insert(statement);
clearActive(_onlyLocation); clearActive(_onlyLocation);
} }
void UnusedStoreEliminator::clearActive( void UnusedStoreEliminator::clearActive(
optional<UnusedStoreEliminator::Location> _onlyLocation std::optional<UnusedStoreEliminator::Location> _onlyLocation
) )
{ {
if (_onlyLocation == nullopt || _onlyLocation == Location::Memory) if (_onlyLocation == std::nullopt || _onlyLocation == Location::Memory)
activeMemoryStores() = {}; activeMemoryStores() = {};
if (_onlyLocation == nullopt || _onlyLocation == Location::Storage) if (_onlyLocation == std::nullopt || _onlyLocation == Location::Storage)
activeStorageStores() = {}; activeStorageStores() = {};
} }
optional<YulString> UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const std::optional<YulString> UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const
{ {
if (Identifier const* identifier = get_if<Identifier>(&_expression)) if (Identifier const* identifier = std::get_if<Identifier>(&_expression))
if (m_ssaValues.count(identifier->name)) if (m_ssaValues.count(identifier->name))
return {identifier->name}; return {identifier->name};
return nullopt; return std::nullopt;
} }

View File

@ -23,7 +23,6 @@
#include <libsolutil/Visitor.h> #include <libsolutil/Visitor.h>
#include <libyul/Dialect.h> #include <libyul/Dialect.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -31,7 +30,7 @@ void VarDeclInitializer::operator()(Block& _block)
{ {
ASTModifier::operator()(_block); ASTModifier::operator()(_block);
using OptionalStatements = std::optional<vector<Statement>>; using OptionalStatements = std::optional<std::vector<Statement>>;
util::GenericVisitor visitor{ util::GenericVisitor visitor{
util::VisitorFallback<OptionalStatements>{}, util::VisitorFallback<OptionalStatements>{},
[this](VariableDeclaration& _varDecl) -> OptionalStatements [this](VariableDeclaration& _varDecl) -> OptionalStatements
@ -41,15 +40,15 @@ void VarDeclInitializer::operator()(Block& _block)
if (_varDecl.variables.size() == 1) if (_varDecl.variables.size() == 1)
{ {
_varDecl.value = make_unique<Expression>(m_dialect.zeroLiteralForType(_varDecl.variables.front().type)); _varDecl.value = std::make_unique<Expression>(m_dialect.zeroLiteralForType(_varDecl.variables.front().type));
return {}; return {};
} }
else else
{ {
OptionalStatements ret{vector<Statement>{}}; OptionalStatements ret{std::vector<Statement>{}};
for (auto& var: _varDecl.variables) for (auto& var: _varDecl.variables)
{ {
unique_ptr<Expression> expr = make_unique<Expression >(m_dialect.zeroLiteralForType(var.type)); std::unique_ptr<Expression> expr = std::make_unique<Expression >(m_dialect.zeroLiteralForType(var.type));
ret->emplace_back(VariableDeclaration{std::move(_varDecl.debugData), {std::move(var)}, std::move(expr)}); ret->emplace_back(VariableDeclaration{std::move(_varDecl.debugData), {std::move(var)}, std::move(expr)});
} }
return ret; return ret;

View File

@ -29,20 +29,19 @@
#include <regex> #include <regex>
#include <limits> #include <limits>
using namespace std;
using namespace solidity::yul; using namespace solidity::yul;
VarNameCleaner::VarNameCleaner( VarNameCleaner::VarNameCleaner(
Block const& _ast, Block const& _ast,
Dialect const& _dialect, Dialect const& _dialect,
set<YulString> _namesToKeep std::set<YulString> _namesToKeep
): ):
m_dialect{_dialect}, m_dialect{_dialect},
m_namesToKeep{std::move(_namesToKeep)}, m_namesToKeep{std::move(_namesToKeep)},
m_translatedNames{} m_translatedNames{}
{ {
for (auto const& statement: _ast.statements) for (auto const& statement: _ast.statements)
if (holds_alternative<FunctionDefinition>(statement)) if (std::holds_alternative<FunctionDefinition>(statement))
m_namesToKeep.insert(std::get<FunctionDefinition>(statement).name); m_namesToKeep.insert(std::get<FunctionDefinition>(statement).name);
m_usedNames = m_namesToKeep; m_usedNames = m_namesToKeep;
} }
@ -52,9 +51,9 @@ void VarNameCleaner::operator()(FunctionDefinition& _funDef)
yulAssert(!m_insideFunction, ""); yulAssert(!m_insideFunction, "");
m_insideFunction = true; m_insideFunction = true;
set<YulString> globalUsedNames = std::move(m_usedNames); std::set<YulString> globalUsedNames = std::move(m_usedNames);
m_usedNames = m_namesToKeep; m_usedNames = m_namesToKeep;
map<YulString, YulString> globalTranslatedNames; std::map<YulString, YulString> globalTranslatedNames;
swap(globalTranslatedNames, m_translatedNames); swap(globalTranslatedNames, m_translatedNames);
renameVariables(_funDef.parameters); renameVariables(_funDef.parameters);
@ -73,7 +72,7 @@ void VarNameCleaner::operator()(VariableDeclaration& _varDecl)
ASTModifier::operator()(_varDecl); ASTModifier::operator()(_varDecl);
} }
void VarNameCleaner::renameVariables(vector<TypedName>& _variables) void VarNameCleaner::renameVariables(std::vector<TypedName>& _variables)
{ {
for (TypedName& typedName: _variables) for (TypedName& typedName: _variables)
{ {
@ -101,9 +100,9 @@ YulString VarNameCleaner::findCleanName(YulString const& _name) const
return newName; return newName;
// create new name with suffix (by finding a free identifier) // create new name with suffix (by finding a free identifier)
for (size_t i = 1; i < numeric_limits<decltype(i)>::max(); ++i) for (size_t i = 1; i < std::numeric_limits<decltype(i)>::max(); ++i)
{ {
YulString newNameSuffixed = YulString{newName.str() + "_" + to_string(i)}; YulString newNameSuffixed = YulString{newName.str() + "_" + std::to_string(i)};
if (!isUsedName(newNameSuffixed)) if (!isUsedName(newNameSuffixed))
return newNameSuffixed; return newNameSuffixed;
} }
@ -117,9 +116,9 @@ bool VarNameCleaner::isUsedName(YulString const& _name) const
YulString VarNameCleaner::stripSuffix(YulString const& _name) const YulString VarNameCleaner::stripSuffix(YulString const& _name) const
{ {
static regex const suffixRegex("(_+[0-9]+)+$"); static std::regex const suffixRegex("(_+[0-9]+)+$");
smatch suffixMatch; std::smatch suffixMatch;
if (regex_search(_name.str(), suffixMatch, suffixRegex)) if (regex_search(_name.str(), suffixMatch, suffixRegex))
return {YulString{suffixMatch.prefix().str()}}; return {YulString{suffixMatch.prefix().str()}};
return _name; return _name;

View File

@ -34,6 +34,8 @@ NAMESPACE_STD_FREE_FILES=(
libsolidity/lsp/* libsolidity/lsp/*
libsolidity/parsing/* libsolidity/parsing/*
libsolutil/* libsolutil/*
libyul/backends/evm/*
libyul/optimiser/*
solc/* solc/*
) )