mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9960 from ethereum/stackLimitEvaderRefactor
StackLimitEvader: Track unreachable variables globally instead of per function.
This commit is contained in:
commit
70ebc0a13c
@ -66,14 +66,13 @@ struct MemoryOffsetAllocator
|
|||||||
if (unreachableVariables.count(_function))
|
if (unreachableVariables.count(_function))
|
||||||
{
|
{
|
||||||
yulAssert(!slotAllocations.count(_function), "");
|
yulAssert(!slotAllocations.count(_function), "");
|
||||||
auto& assignedSlots = slotAllocations[_function];
|
|
||||||
for (YulString variable: unreachableVariables.at(_function))
|
for (YulString variable: unreachableVariables.at(_function))
|
||||||
if (variable.empty())
|
if (variable.empty())
|
||||||
{
|
{
|
||||||
// TODO: Too many function arguments or return parameters.
|
// TODO: Too many function arguments or return parameters.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assignedSlots[variable] = requiredSlots++;
|
slotAllocations[variable] = requiredSlots++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return slotsRequiredForFunction[_function] = requiredSlots;
|
return slotsRequiredForFunction[_function] = requiredSlots;
|
||||||
@ -82,7 +81,7 @@ struct MemoryOffsetAllocator
|
|||||||
map<YulString, set<YulString>> const& unreachableVariables;
|
map<YulString, set<YulString>> const& unreachableVariables;
|
||||||
map<YulString, set<YulString>> const& callGraph;
|
map<YulString, set<YulString>> const& callGraph;
|
||||||
|
|
||||||
map<YulString, map<YulString, uint64_t>> slotAllocations{};
|
map<YulString, uint64_t> slotAllocations{};
|
||||||
map<YulString, uint64_t> slotsRequiredForFunction{};
|
map<YulString, uint64_t> slotsRequiredForFunction{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ vector<Statement> generateMemoryStore(
|
|||||||
void StackToMemoryMover::run(
|
void StackToMemoryMover::run(
|
||||||
OptimiserStepContext& _context,
|
OptimiserStepContext& _context,
|
||||||
u256 _reservedMemory,
|
u256 _reservedMemory,
|
||||||
map<YulString, map<YulString, uint64_t>> const& _memorySlots,
|
map<YulString, uint64_t> const& _memorySlots,
|
||||||
uint64_t _numRequiredSlots,
|
uint64_t _numRequiredSlots,
|
||||||
Block& _block
|
Block& _block
|
||||||
)
|
)
|
||||||
@ -66,7 +66,7 @@ void StackToMemoryMover::run(
|
|||||||
StackToMemoryMover::StackToMemoryMover(
|
StackToMemoryMover::StackToMemoryMover(
|
||||||
OptimiserStepContext& _context,
|
OptimiserStepContext& _context,
|
||||||
u256 _reservedMemory,
|
u256 _reservedMemory,
|
||||||
map<YulString, map<YulString, uint64_t>> const& _memorySlots,
|
map<YulString, uint64_t> const& _memorySlots,
|
||||||
uint64_t _numRequiredSlots
|
uint64_t _numRequiredSlots
|
||||||
):
|
):
|
||||||
m_context(_context),
|
m_context(_context),
|
||||||
@ -80,41 +80,25 @@ m_nameDispenser(_context.dispenser)
|
|||||||
evmDialect && evmDialect->providesObjectAccess(),
|
evmDialect && evmDialect->providesObjectAccess(),
|
||||||
"StackToMemoryMover can only be run on objects using the EVMDialect with object access."
|
"StackToMemoryMover can only be run on objects using the EVMDialect with object access."
|
||||||
);
|
);
|
||||||
|
|
||||||
if (m_memorySlots.count(YulString{}))
|
|
||||||
// If the global scope contains variables to be moved, start with those as if it were a function.
|
|
||||||
m_currentFunctionMemorySlots = &m_memorySlots.at(YulString{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
|
void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
|
||||||
{
|
{
|
||||||
if (m_memorySlots.count(_functionDefinition.name))
|
for (TypedName const& param: _functionDefinition.parameters + _functionDefinition.returnVariables)
|
||||||
{
|
if (m_memorySlots.count(param.name))
|
||||||
map<YulString, uint64_t> const* saved = m_currentFunctionMemorySlots;
|
{
|
||||||
m_currentFunctionMemorySlots = &m_memorySlots.at(_functionDefinition.name);
|
// TODO: we cannot handle function parameters yet.
|
||||||
for (TypedName const& param: _functionDefinition.parameters + _functionDefinition.returnVariables)
|
return;
|
||||||
if (m_currentFunctionMemorySlots->count(param.name))
|
}
|
||||||
{
|
ASTModifier::operator()(_functionDefinition);
|
||||||
// TODO: we cannot handle function parameters yet.
|
|
||||||
m_currentFunctionMemorySlots = saved;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ASTModifier::operator()(_functionDefinition);
|
|
||||||
m_currentFunctionMemorySlots = saved;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackToMemoryMover::operator()(Block& _block)
|
void StackToMemoryMover::operator()(Block& _block)
|
||||||
{
|
{
|
||||||
using OptionalStatements = std::optional<vector<Statement>>;
|
using OptionalStatements = std::optional<vector<Statement>>;
|
||||||
if (!m_currentFunctionMemorySlots)
|
|
||||||
{
|
|
||||||
ASTModifier::operator()(_block);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto containsVariableNeedingEscalation = [&](auto const& _variables) {
|
auto containsVariableNeedingEscalation = [&](auto const& _variables) {
|
||||||
return util::contains_if(_variables, [&](auto const& var) {
|
return util::contains_if(_variables, [&](auto const& var) {
|
||||||
return m_currentFunctionMemorySlots->count(var.name);
|
return m_memorySlots.count(var.name);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
auto rewriteAssignmentOrVariableDeclaration = [&](
|
auto rewriteAssignmentOrVariableDeclaration = [&](
|
||||||
@ -138,7 +122,7 @@ void StackToMemoryMover::operator()(Block& _block)
|
|||||||
YulString tempVarName = m_nameDispenser.newName(var.name);
|
YulString tempVarName = m_nameDispenser.newName(var.name);
|
||||||
tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}});
|
tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}});
|
||||||
|
|
||||||
if (m_currentFunctionMemorySlots->count(var.name))
|
if (m_memorySlots.count(var.name))
|
||||||
memoryAssignments += generateMemoryStore(
|
memoryAssignments += generateMemoryStore(
|
||||||
m_context.dialect,
|
m_context.dialect,
|
||||||
_loc,
|
_loc,
|
||||||
@ -203,7 +187,7 @@ void StackToMemoryMover::visit(Expression& _expression)
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
Identifier* identifier = std::get_if<Identifier>(&_expression);
|
Identifier* identifier = std::get_if<Identifier>(&_expression);
|
||||||
identifier && m_currentFunctionMemorySlots && m_currentFunctionMemorySlots->count(identifier->name)
|
identifier && m_memorySlots.count(identifier->name)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BuiltinFunction const* memoryLoadFunction = m_context.dialect.memoryLoadFunction(m_context.dialect.defaultType);
|
BuiltinFunction const* memoryLoadFunction = m_context.dialect.memoryLoadFunction(m_context.dialect.defaultType);
|
||||||
@ -227,8 +211,8 @@ void StackToMemoryMover::visit(Expression& _expression)
|
|||||||
|
|
||||||
YulString StackToMemoryMover::memoryOffset(YulString _variable)
|
YulString StackToMemoryMover::memoryOffset(YulString _variable)
|
||||||
{
|
{
|
||||||
yulAssert(m_currentFunctionMemorySlots, "");
|
yulAssert(m_memorySlots.count(_variable), "");
|
||||||
uint64_t slot = m_currentFunctionMemorySlots->at(_variable);
|
uint64_t slot = m_memorySlots.at(_variable);
|
||||||
yulAssert(slot < m_numRequiredSlots, "");
|
yulAssert(slot < m_numRequiredSlots, "");
|
||||||
return YulString{util::toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))};
|
return YulString{util::toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))};
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public:
|
|||||||
static void run(
|
static void run(
|
||||||
OptimiserStepContext& _context,
|
OptimiserStepContext& _context,
|
||||||
u256 _reservedMemory,
|
u256 _reservedMemory,
|
||||||
std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots,
|
std::map<YulString, uint64_t> const& _memorySlots,
|
||||||
uint64_t _numRequiredSlots,
|
uint64_t _numRequiredSlots,
|
||||||
Block& _block
|
Block& _block
|
||||||
);
|
);
|
||||||
@ -103,7 +103,7 @@ private:
|
|||||||
StackToMemoryMover(
|
StackToMemoryMover(
|
||||||
OptimiserStepContext& _context,
|
OptimiserStepContext& _context,
|
||||||
u256 _reservedMemory,
|
u256 _reservedMemory,
|
||||||
std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots,
|
std::map<YulString, uint64_t> const& _memorySlots,
|
||||||
uint64_t _numRequiredSlots
|
uint64_t _numRequiredSlots
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -112,10 +112,9 @@ private:
|
|||||||
|
|
||||||
OptimiserStepContext& m_context;
|
OptimiserStepContext& m_context;
|
||||||
u256 m_reservedMemory;
|
u256 m_reservedMemory;
|
||||||
std::map<YulString, std::map<YulString, uint64_t>> const& m_memorySlots;
|
std::map<YulString, uint64_t> const& m_memorySlots;
|
||||||
uint64_t m_numRequiredSlots = 0;
|
uint64_t m_numRequiredSlots = 0;
|
||||||
NameDispenser& m_nameDispenser;
|
NameDispenser& m_nameDispenser;
|
||||||
std::map<YulString, uint64_t> const* m_currentFunctionMemorySlots = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user