Deterministically choose memory slots for variables independently of names that may depend on AST IDs.

This commit is contained in:
Daniel Kirchner
2023-06-12 17:28:01 +02:00
committed by r0qs
parent 6c4e40bcef
commit b7abd9bba4
16 changed files with 97 additions and 82 deletions
+3 -1
View File
@@ -63,7 +63,9 @@ CompilabilityChecker::CompilabilityChecker(
for (StackTooDeepError const& error: transform.stackErrors())
{
unreachableVariables[error.functionName].emplace(error.variable);
auto& unreachables = unreachableVariables[error.functionName];
if (!util::contains(unreachables, error.variable))
unreachables.emplace_back(error.variable);
int& deficit = stackDeficit[error.functionName];
deficit = std::max(error.depth, deficit);
}
+1 -1
View File
@@ -45,7 +45,7 @@ namespace solidity::yul
struct CompilabilityChecker
{
CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation);
std::map<YulString, std::set<YulString>> unreachableVariables;
std::map<YulString, std::vector<YulString>> unreachableVariables;
std::map<YulString, int> stackDeficit;
};
+4 -1
View File
@@ -22,6 +22,7 @@
#include <libyul/AST.h>
#include <libyul/optimiser/CallGraphGenerator.h>
#include <libsolutil/CommonData.h>
#include <stack>
using namespace std;
@@ -79,7 +80,9 @@ CallGraph CallGraphGenerator::callGraph(Block const& _ast)
void CallGraphGenerator::operator()(FunctionCall const& _functionCall)
{
m_callGraph.functionCalls[m_currentFunction].insert(_functionCall.functionName.name);
auto& functionCalls = m_callGraph.functionCalls[m_currentFunction];
if (!util::contains(functionCalls, _functionCall.functionName.name))
functionCalls.emplace_back(_functionCall.functionName.name);
ASTWalker::operator()(_functionCall);
}
+1 -1
View File
@@ -32,7 +32,7 @@ namespace solidity::yul
struct CallGraph
{
std::map<YulString, std::set<YulString>> functionCalls;
std::map<YulString, std::vector<YulString>> functionCalls;
std::set<YulString> functionsWithLoops;
/// @returns the set of functions contained in cycles in the call graph, i.e.
/// functions that are part of a (mutual) recursion.
+4 -1
View File
@@ -37,6 +37,8 @@
#include <libsolutil/CommonData.h>
#include <libsolutil/Visitor.h>
#include <range/v3/action/remove.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::yul;
@@ -156,7 +158,8 @@ map<YulString, size_t> FullInliner::callDepths() const
}
for (auto& call: cg.functionCalls)
call.second -= removed;
for (YulString toBeRemoved: removed)
ranges::actions::remove(call.second, toBeRemoved);
currentDepth++;
+10 -5
View File
@@ -97,9 +97,9 @@ struct MemoryOffsetAllocator
/// 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.
map<YulString, set<YulString>> const& unreachableVariables;
map<YulString, vector<YulString>> const& unreachableVariables;
/// The graph of immediate function calls of all functions.
map<YulString, set<YulString>> const& callGraph;
map<YulString, vector<YulString>> const& callGraph;
/// Maps the name of each user-defined function to its definition.
map<YulString, FunctionDefinition const*> const& functionDefinitions;
@@ -149,18 +149,23 @@ void StackLimitEvader::run(
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> const& _stackTooDeepErrors
)
{
map<YulString, set<YulString>> unreachableVariables;
map<YulString, vector<YulString>> unreachableVariables;
for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors)
{
auto& unreachables = unreachableVariables[function];
// TODO: choose wisely.
for (auto const& stackTooDeepError: stackTooDeepErrors)
unreachableVariables[function] += stackTooDeepError.variableChoices | ranges::views::take(stackTooDeepError.deficit) | ranges::to<set<YulString>>;
for (auto variable: stackTooDeepError.variableChoices | ranges::views::take(stackTooDeepError.deficit))
if (!util::contains(unreachables, variable))
unreachables.emplace_back(variable);
}
run(_context, _object, unreachableVariables);
}
void StackLimitEvader::run(
OptimiserStepContext& _context,
Object& _object,
map<YulString, set<YulString>> const& _unreachableVariables
map<YulString, vector<YulString>> const& _unreachableVariables
)
{
yulAssert(_object.code, "");
+1 -1
View File
@@ -60,7 +60,7 @@ public:
static void run(
OptimiserStepContext& _context,
Object& _object,
std::map<YulString, std::set<YulString>> const& _unreachableVariables
std::map<YulString, std::vector<YulString>> const& _unreachableVariables
);
/// @a _stackTooDeepErrors can be determined by the StackLayoutGenerator.
/// Can only be run on the EVM dialect with objects.