mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactor stack to memory mover in preparation of moving function arguments.
This commit is contained in:
parent
abfa136afb
commit
61a03036fe
@ -49,6 +49,23 @@ vector<Statement> generateMemoryStore(
|
|||||||
}});
|
}});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::SourceLocation const& _loc, YulString _mpos)
|
||||||
|
{
|
||||||
|
BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType);
|
||||||
|
yulAssert(memoryLoadFunction, "");
|
||||||
|
return FunctionCall{
|
||||||
|
_loc,
|
||||||
|
Identifier{_loc, memoryLoadFunction->name}, {
|
||||||
|
Literal{
|
||||||
|
_loc,
|
||||||
|
LiteralKind::Number,
|
||||||
|
_mpos,
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackToMemoryMover::run(
|
void StackToMemoryMover::run(
|
||||||
@ -93,29 +110,34 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
|
|||||||
void StackToMemoryMover::operator()(Block& _block)
|
void StackToMemoryMover::operator()(Block& _block)
|
||||||
{
|
{
|
||||||
using OptionalStatements = std::optional<vector<Statement>>;
|
using OptionalStatements = std::optional<vector<Statement>>;
|
||||||
auto containsVariableNeedingEscalation = [&](auto const& _variables) {
|
auto rewriteAssignmentOrVariableDeclaration = [&](
|
||||||
return util::contains_if(_variables, [&](auto const& var) {
|
auto& _stmt,
|
||||||
|
auto const& _variables
|
||||||
|
) -> OptionalStatements {
|
||||||
|
using StatementType = decay_t<decltype(_stmt)>;
|
||||||
|
if (_stmt.value)
|
||||||
|
visit(*_stmt.value);
|
||||||
|
bool leftHandSideNeedsMoving = util::contains_if(_variables, [&](auto const& var) {
|
||||||
return m_memoryOffsetTracker(var.name);
|
return m_memoryOffsetTracker(var.name);
|
||||||
});
|
});
|
||||||
};
|
if (!leftHandSideNeedsMoving)
|
||||||
auto rewriteAssignmentOrVariableDeclaration = [&](
|
return {};
|
||||||
langutil::SourceLocation const& _loc,
|
|
||||||
auto const& _variables,
|
langutil::SourceLocation loc = _stmt.location;
|
||||||
std::unique_ptr<Expression> _value
|
|
||||||
) -> std::vector<Statement> {
|
|
||||||
if (_variables.size() == 1)
|
if (_variables.size() == 1)
|
||||||
{
|
{
|
||||||
optional<YulString> offset = m_memoryOffsetTracker(_variables.front().name);
|
optional<YulString> offset = m_memoryOffsetTracker(_variables.front().name);
|
||||||
yulAssert(offset, "");
|
yulAssert(offset, "");
|
||||||
return generateMemoryStore(
|
return generateMemoryStore(
|
||||||
m_context.dialect,
|
m_context.dialect,
|
||||||
_loc,
|
loc,
|
||||||
*offset,
|
*offset,
|
||||||
_value ? *std::move(_value) : Literal{_loc, LiteralKind::Number, "0"_yulstring, {}}
|
_stmt.value ? *std::move(_stmt.value) : Literal{loc, LiteralKind::Number, "0"_yulstring, {}}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDeclaration tempDecl{_loc, {}, std::move(_value)};
|
VariableDeclaration tempDecl{loc, {}, std::move(_stmt.value)};
|
||||||
vector<Statement> memoryAssignments;
|
vector<Statement> memoryAssignments;
|
||||||
vector<Statement> variableAssignments;
|
vector<Statement> variableAssignments;
|
||||||
for (auto& var: _variables)
|
for (auto& var: _variables)
|
||||||
@ -126,19 +148,14 @@ void StackToMemoryMover::operator()(Block& _block)
|
|||||||
if (optional<YulString> offset = m_memoryOffsetTracker(var.name))
|
if (optional<YulString> offset = m_memoryOffsetTracker(var.name))
|
||||||
memoryAssignments += generateMemoryStore(
|
memoryAssignments += generateMemoryStore(
|
||||||
m_context.dialect,
|
m_context.dialect,
|
||||||
_loc,
|
loc,
|
||||||
*offset,
|
*offset,
|
||||||
Identifier{_loc, tempVarName}
|
Identifier{loc, tempVarName}
|
||||||
);
|
);
|
||||||
else if constexpr (std::is_same_v<std::decay_t<decltype(var)>, Identifier>)
|
|
||||||
variableAssignments.emplace_back(Assignment{
|
|
||||||
_loc, { Identifier{var.location, var.name} },
|
|
||||||
make_unique<Expression>(Identifier{_loc, tempVarName})
|
|
||||||
});
|
|
||||||
else
|
else
|
||||||
variableAssignments.emplace_back(VariableDeclaration{
|
variableAssignments.emplace_back(StatementType{
|
||||||
_loc, {std::move(var)},
|
loc, {move(var)},
|
||||||
make_unique<Expression>(Identifier{_loc, tempVarName})
|
make_unique<Expression>(Identifier{loc, tempVarName})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
std::vector<Statement> result;
|
std::vector<Statement> result;
|
||||||
@ -147,65 +164,34 @@ void StackToMemoryMover::operator()(Block& _block)
|
|||||||
result += std::move(memoryAssignments);
|
result += std::move(memoryAssignments);
|
||||||
std::reverse(variableAssignments.begin(), variableAssignments.end());
|
std::reverse(variableAssignments.begin(), variableAssignments.end());
|
||||||
result += std::move(variableAssignments);
|
result += std::move(variableAssignments);
|
||||||
return result;
|
return OptionalStatements{move(result)};
|
||||||
};
|
};
|
||||||
|
|
||||||
util::iterateReplacing(
|
util::iterateReplacing(
|
||||||
_block.statements,
|
_block.statements,
|
||||||
[&](Statement& _statement)
|
[&](Statement& _statement)
|
||||||
{
|
{
|
||||||
auto defaultVisit = [&]() { ASTModifier::visit(_statement); return OptionalStatements{}; };
|
|
||||||
return std::visit(util::GenericVisitor{
|
return std::visit(util::GenericVisitor{
|
||||||
[&](Assignment& _assignment) -> OptionalStatements
|
[&](Assignment& _assignment) -> OptionalStatements
|
||||||
{
|
{
|
||||||
if (!containsVariableNeedingEscalation(_assignment.variableNames))
|
return rewriteAssignmentOrVariableDeclaration(_assignment, _assignment.variableNames);
|
||||||
return defaultVisit();
|
|
||||||
visit(*_assignment.value);
|
|
||||||
return {rewriteAssignmentOrVariableDeclaration(
|
|
||||||
_assignment.location,
|
|
||||||
_assignment.variableNames,
|
|
||||||
std::move(_assignment.value)
|
|
||||||
)};
|
|
||||||
},
|
},
|
||||||
[&](VariableDeclaration& _varDecl) -> OptionalStatements
|
[&](VariableDeclaration& _varDecl) -> OptionalStatements
|
||||||
{
|
{
|
||||||
if (!containsVariableNeedingEscalation(_varDecl.variables))
|
return rewriteAssignmentOrVariableDeclaration(_varDecl, _varDecl.variables);
|
||||||
return defaultVisit();
|
|
||||||
if (_varDecl.value)
|
|
||||||
visit(*_varDecl.value);
|
|
||||||
return {rewriteAssignmentOrVariableDeclaration(
|
|
||||||
_varDecl.location,
|
|
||||||
_varDecl.variables,
|
|
||||||
std::move(_varDecl.value)
|
|
||||||
)};
|
|
||||||
},
|
},
|
||||||
[&](auto&) { return defaultVisit(); }
|
[&](auto& _stmt) -> OptionalStatements { (*this)(_stmt); return {}; }
|
||||||
}, _statement);
|
}, _statement);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackToMemoryMover::visit(Expression& _expression)
|
void StackToMemoryMover::visit(Expression& _expression)
|
||||||
{
|
{
|
||||||
|
ASTModifier::visit(_expression);
|
||||||
if (Identifier* identifier = std::get_if<Identifier>(&_expression))
|
if (Identifier* identifier = std::get_if<Identifier>(&_expression))
|
||||||
if (optional<YulString> offset = m_memoryOffsetTracker(identifier->name))
|
if (optional<YulString> offset = m_memoryOffsetTracker(identifier->name))
|
||||||
{
|
_expression = generateMemoryLoad(m_context.dialect, identifier->location, *offset);
|
||||||
BuiltinFunction const* memoryLoadFunction = m_context.dialect.memoryLoadFunction(m_context.dialect.defaultType);
|
|
||||||
yulAssert(memoryLoadFunction, "");
|
|
||||||
langutil::SourceLocation loc = identifier->location;
|
|
||||||
_expression = FunctionCall{
|
|
||||||
loc,
|
|
||||||
Identifier{loc, memoryLoadFunction->name}, {
|
|
||||||
Literal{
|
|
||||||
loc,
|
|
||||||
LiteralKind::Number,
|
|
||||||
*offset,
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ASTModifier::visit(_expression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const
|
optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const
|
||||||
|
@ -126,7 +126,7 @@ void OptimiserSuite::run(
|
|||||||
{
|
{
|
||||||
yulAssert(_meter, "");
|
yulAssert(_meter, "");
|
||||||
ConstantOptimiser{*dialect, *_meter}(ast);
|
ConstantOptimiser{*dialect, *_meter}(ast);
|
||||||
if (dialect->providesObjectAccess())
|
if (dialect->providesObjectAccess() && _optimizeStackAllocation)
|
||||||
StackLimitEvader::run(suite.m_context, _object, CompilabilityChecker{
|
StackLimitEvader::run(suite.m_context, _object, CompilabilityChecker{
|
||||||
_dialect,
|
_dialect,
|
||||||
_object,
|
_object,
|
||||||
|
Loading…
Reference in New Issue
Block a user