Track unreachable variables globally instead of per function.

This commit is contained in:
Daniel Kirchner 2020-10-06 10:38:26 +02:00
parent 756e21a888
commit 0b87849bcb
3 changed files with 19 additions and 37 deletions

View File

@ -66,14 +66,13 @@ struct MemoryOffsetAllocator
if (unreachableVariables.count(_function))
{
yulAssert(!slotAllocations.count(_function), "");
auto& assignedSlots = slotAllocations[_function];
for (YulString variable: unreachableVariables.at(_function))
if (variable.empty())
{
// TODO: Too many function arguments or return parameters.
}
else
assignedSlots[variable] = requiredSlots++;
slotAllocations[variable] = requiredSlots++;
}
return slotsRequiredForFunction[_function] = requiredSlots;
@ -82,7 +81,7 @@ struct MemoryOffsetAllocator
map<YulString, set<YulString>> const& unreachableVariables;
map<YulString, set<YulString>> const& callGraph;
map<YulString, map<YulString, uint64_t>> slotAllocations{};
map<YulString, uint64_t> slotAllocations{};
map<YulString, uint64_t> slotsRequiredForFunction{};
};

View File

@ -54,7 +54,7 @@ vector<Statement> generateMemoryStore(
void StackToMemoryMover::run(
OptimiserStepContext& _context,
u256 _reservedMemory,
map<YulString, map<YulString, uint64_t>> const& _memorySlots,
map<YulString, uint64_t> const& _memorySlots,
uint64_t _numRequiredSlots,
Block& _block
)
@ -66,7 +66,7 @@ void StackToMemoryMover::run(
StackToMemoryMover::StackToMemoryMover(
OptimiserStepContext& _context,
u256 _reservedMemory,
map<YulString, map<YulString, uint64_t>> const& _memorySlots,
map<YulString, uint64_t> const& _memorySlots,
uint64_t _numRequiredSlots
):
m_context(_context),
@ -80,41 +80,25 @@ m_nameDispenser(_context.dispenser)
evmDialect && evmDialect->providesObjectAccess(),
"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)
{
if (m_memorySlots.count(_functionDefinition.name))
{
map<YulString, uint64_t> const* saved = m_currentFunctionMemorySlots;
m_currentFunctionMemorySlots = &m_memorySlots.at(_functionDefinition.name);
for (TypedName const& param: _functionDefinition.parameters + _functionDefinition.returnVariables)
if (m_currentFunctionMemorySlots->count(param.name))
{
// TODO: we cannot handle function parameters yet.
m_currentFunctionMemorySlots = saved;
return;
}
ASTModifier::operator()(_functionDefinition);
m_currentFunctionMemorySlots = saved;
}
for (TypedName const& param: _functionDefinition.parameters + _functionDefinition.returnVariables)
if (m_memorySlots.count(param.name))
{
// TODO: we cannot handle function parameters yet.
return;
}
ASTModifier::operator()(_functionDefinition);
}
void StackToMemoryMover::operator()(Block& _block)
{
using OptionalStatements = std::optional<vector<Statement>>;
if (!m_currentFunctionMemorySlots)
{
ASTModifier::operator()(_block);
return;
}
auto containsVariableNeedingEscalation = [&](auto const& _variables) {
return util::contains_if(_variables, [&](auto const& var) {
return m_currentFunctionMemorySlots->count(var.name);
return m_memorySlots.count(var.name);
});
};
auto rewriteAssignmentOrVariableDeclaration = [&](
@ -138,7 +122,7 @@ void StackToMemoryMover::operator()(Block& _block)
YulString tempVarName = m_nameDispenser.newName(var.name);
tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}});
if (m_currentFunctionMemorySlots->count(var.name))
if (m_memorySlots.count(var.name))
memoryAssignments += generateMemoryStore(
m_context.dialect,
_loc,
@ -203,7 +187,7 @@ void StackToMemoryMover::visit(Expression& _expression)
{
if (
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);
@ -227,8 +211,8 @@ void StackToMemoryMover::visit(Expression& _expression)
YulString StackToMemoryMover::memoryOffset(YulString _variable)
{
yulAssert(m_currentFunctionMemorySlots, "");
uint64_t slot = m_currentFunctionMemorySlots->at(_variable);
yulAssert(m_memorySlots.count(_variable), "");
uint64_t slot = m_memorySlots.at(_variable);
yulAssert(slot < m_numRequiredSlots, "");
return YulString{util::toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))};
}

View File

@ -90,7 +90,7 @@ public:
static void run(
OptimiserStepContext& _context,
u256 _reservedMemory,
std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots,
std::map<YulString, uint64_t> const& _memorySlots,
uint64_t _numRequiredSlots,
Block& _block
);
@ -103,7 +103,7 @@ private:
StackToMemoryMover(
OptimiserStepContext& _context,
u256 _reservedMemory,
std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots,
std::map<YulString, uint64_t> const& _memorySlots,
uint64_t _numRequiredSlots
);
@ -112,10 +112,9 @@ private:
OptimiserStepContext& m_context;
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;
NameDispenser& m_nameDispenser;
std::map<YulString, uint64_t> const* m_currentFunctionMemorySlots = nullptr;
};
}