mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Side effects propagator.
This commit is contained in:
parent
c047803b80
commit
a2a06d0318
@ -73,6 +73,16 @@ struct SideEffects
|
||||
*this = *this + _other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(SideEffects const& _other) const
|
||||
{
|
||||
return
|
||||
movable == _other.movable &&
|
||||
sideEffectFree == _other.sideEffectFree &&
|
||||
sideEffectFreeIfNoMSize == _other.sideEffectFreeIfNoMSize &&
|
||||
invalidatesStorage == _other.invalidatesStorage &&
|
||||
invalidatesMemory == _other.invalidatesMemory;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -29,18 +29,24 @@ using namespace std;
|
||||
using namespace dev;
|
||||
using namespace yul;
|
||||
|
||||
map<YulString, set<YulString>> CallGraphGenerator::callGraph(Block const& _ast)
|
||||
{
|
||||
CallGraphGenerator gen;
|
||||
gen(_ast);
|
||||
return std::move(gen.m_callGraph);
|
||||
}
|
||||
|
||||
void CallGraphGenerator::operator()(FunctionalInstruction const& _functionalInstruction)
|
||||
{
|
||||
m_callGraph.insert(m_currentFunction, YulString{
|
||||
dev::eth::instructionInfo(_functionalInstruction.instruction).name
|
||||
});
|
||||
string name = dev::eth::instructionInfo(_functionalInstruction.instruction).name;
|
||||
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
|
||||
m_callGraph[m_currentFunction].insert(YulString{name});
|
||||
ASTWalker::operator()(_functionalInstruction);
|
||||
}
|
||||
|
||||
void CallGraphGenerator::operator()(FunctionCall const& _functionCall)
|
||||
{
|
||||
m_callGraph.insert(m_currentFunction, _functionCall.functionName.name);
|
||||
m_callGraph[m_currentFunction].insert(_functionCall.functionName.name);
|
||||
ASTWalker::operator()(_functionCall);
|
||||
}
|
||||
|
||||
@ -48,7 +54,14 @@ void CallGraphGenerator::operator()(FunctionDefinition const& _functionDefinitio
|
||||
{
|
||||
YulString previousFunction = m_currentFunction;
|
||||
m_currentFunction = _functionDefinition.name;
|
||||
yulAssert(m_callGraph.count(m_currentFunction) == 0, "");
|
||||
m_callGraph[m_currentFunction] = {};
|
||||
ASTWalker::operator()(_functionDefinition);
|
||||
m_currentFunction = previousFunction;
|
||||
}
|
||||
|
||||
CallGraphGenerator::CallGraphGenerator()
|
||||
{
|
||||
m_callGraph[YulString{}] = {};
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,7 @@ namespace yul
|
||||
class CallGraphGenerator: public ASTWalker
|
||||
{
|
||||
public:
|
||||
/// @returns the call graph of the visited AST.
|
||||
InvertibleRelation<YulString> const& callGraph() const { return m_callGraph; }
|
||||
static std::map<YulString, std::set<YulString>> callGraph(Block const& _ast);
|
||||
|
||||
using ASTWalker::operator();
|
||||
void operator()(FunctionalInstruction const& _functionalInstruction) override;
|
||||
@ -49,7 +48,9 @@ public:
|
||||
void operator()(FunctionDefinition const& _functionDefinition) override;
|
||||
|
||||
private:
|
||||
InvertibleRelation<YulString> m_callGraph;
|
||||
CallGraphGenerator();
|
||||
|
||||
std::map<YulString, std::set<YulString>> m_callGraph;
|
||||
/// The name of the function we are currently visiting during traversal.
|
||||
YulString m_currentFunction;
|
||||
};
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <libevmasm/SemanticInformation.h>
|
||||
|
||||
#include <libdevcore/CommonData.h>
|
||||
#include <libdevcore/Algorithms.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
@ -93,6 +94,33 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall)
|
||||
m_msizeFound = true;
|
||||
}
|
||||
|
||||
|
||||
map<YulString, SideEffects> SideEffectsPropagator::sideEffects(
|
||||
Dialect const& _dialect,
|
||||
map<YulString, std::set<YulString>> const& _directCallGraph
|
||||
)
|
||||
{
|
||||
map<YulString, SideEffects> ret;
|
||||
for (auto const& call: _directCallGraph)
|
||||
{
|
||||
YulString funName = call.first;
|
||||
SideEffects sideEffects;
|
||||
BreadthFirstSearch<YulString>{call.second, {funName}}.run(
|
||||
[&](YulString _function, auto&& _addChild) {
|
||||
if (sideEffects == SideEffects::worst())
|
||||
return;
|
||||
if (BuiltinFunction const* f = _dialect.builtin(_function))
|
||||
sideEffects += f->sideEffects;
|
||||
else
|
||||
for (YulString callee: _directCallGraph.at(_function))
|
||||
_addChild(callee);
|
||||
}
|
||||
);
|
||||
ret[funName] = sideEffects;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression):
|
||||
MovableChecker(_dialect)
|
||||
{
|
||||
|
@ -62,6 +62,21 @@ private:
|
||||
SideEffects m_sideEffects;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class can be used to determine the side-effects of user-defined functions.
|
||||
*
|
||||
* It is given a dialect and a mapping that represents the direct calls from user-defined
|
||||
* functions to other user-defined functions and built-in functions.
|
||||
*/
|
||||
class SideEffectsPropagator
|
||||
{
|
||||
public:
|
||||
static std::map<YulString, SideEffects> sideEffects(
|
||||
Dialect const& _dialect,
|
||||
std::map<YulString, std::set<YulString>> const& _directCallGraph
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class that can be used to find out if certain code contains the MSize instruction.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user