Remove ContainsMSize from side-effect-collector.

This commit is contained in:
chriseth 2019-08-13 13:34:33 +02:00
parent 98e3caa28a
commit 57125de9ef
6 changed files with 51 additions and 16 deletions

View File

@ -262,10 +262,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly)
if (!m_useYulOptimizer) if (!m_useYulOptimizer)
return false; return false;
if (yul::SideEffectsCollector( if (yul::MSizeFinder::containsMSize(_inlineAssembly.dialect(), _inlineAssembly.operations()))
_inlineAssembly.dialect(),
_inlineAssembly.operations()
).containsMSize())
m_errorReporter.syntaxError( m_errorReporter.syntaxError(
_inlineAssembly.location(), _inlineAssembly.location(),
"The msize instruction cannot be used when the Yul optimizer is activated because " "The msize instruction cannot be used when the Yul optimizer is activated because "

View File

@ -31,7 +31,7 @@ using namespace yul;
void LoadResolver::run(Dialect const& _dialect, Block& _ast) void LoadResolver::run(Dialect const& _dialect, Block& _ast)
{ {
bool containsMSize = SideEffectsCollector(_dialect, _ast).containsMSize(); bool containsMSize = MSizeFinder::containsMSize(_dialect, _ast);
LoadResolver{_dialect, !containsMSize}(_ast); LoadResolver{_dialect, !containsMSize}(_ast);
} }

View File

@ -61,8 +61,6 @@ void SideEffectsCollector::operator()(FunctionalInstruction const& _instr)
m_sideEffectFree = false; m_sideEffectFree = false;
if (!eth::SemanticInformation::sideEffectFreeIfNoMSize(_instr.instruction)) if (!eth::SemanticInformation::sideEffectFreeIfNoMSize(_instr.instruction))
m_sideEffectFreeIfNoMSize = false; m_sideEffectFreeIfNoMSize = false;
if (_instr.instruction == eth::Instruction::MSIZE)
m_containsMSize = true;
if (eth::SemanticInformation::invalidatesStorage(_instr.instruction)) if (eth::SemanticInformation::invalidatesStorage(_instr.instruction))
m_invalidatesStorage = true; m_invalidatesStorage = true;
if (eth::SemanticInformation::invalidatesMemory(_instr.instruction)) if (eth::SemanticInformation::invalidatesMemory(_instr.instruction))
@ -81,8 +79,6 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall)
m_sideEffectFree = false; m_sideEffectFree = false;
if (!f->sideEffectFreeIfNoMSize) if (!f->sideEffectFreeIfNoMSize)
m_sideEffectFreeIfNoMSize = false; m_sideEffectFreeIfNoMSize = false;
if (f->isMSize)
m_containsMSize = true;
if (f->invalidatesStorage) if (f->invalidatesStorage)
m_invalidatesStorage = true; m_invalidatesStorage = true;
if (f->invalidatesMemory) if (f->invalidatesMemory)
@ -98,6 +94,30 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall)
} }
} }
bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast)
{
MSizeFinder finder(_dialect);
finder(_ast);
return finder.m_msizeFound;
}
void MSizeFinder::operator()(FunctionalInstruction const& _instr)
{
ASTWalker::operator()(_instr);
if (_instr.instruction == eth::Instruction::MSIZE)
m_msizeFound = true;
}
void MSizeFinder::operator()(FunctionCall const& _functionCall)
{
ASTWalker::operator()(_functionCall);
if (BuiltinFunction const* f = m_dialect.builtin(_functionCall.functionName.name))
if (f->isMSize)
m_msizeFound = true;
}
MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression): MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression):
MovableChecker(_dialect) MovableChecker(_dialect)
{ {

View File

@ -53,7 +53,6 @@ public:
return m_sideEffectFree; return m_sideEffectFree;
} }
bool sideEffectFreeIfNoMSize() const { return m_sideEffectFreeIfNoMSize; } bool sideEffectFreeIfNoMSize() const { return m_sideEffectFreeIfNoMSize; }
bool containsMSize() const { return m_containsMSize; }
bool invalidatesStorage() const { return m_invalidatesStorage; } bool invalidatesStorage() const { return m_invalidatesStorage; }
bool invalidatesMemory() const { return m_invalidatesMemory; } bool invalidatesMemory() const { return m_invalidatesMemory; }
@ -67,16 +66,35 @@ private:
/// Is the current expression side-effect free up to msize, i.e. can be removed /// Is the current expression side-effect free up to msize, i.e. can be removed
/// without changing the semantics except for the value returned by the msize instruction. /// without changing the semantics except for the value returned by the msize instruction.
bool m_sideEffectFreeIfNoMSize = true; bool m_sideEffectFreeIfNoMSize = true;
/// Does the current code contain the MSize operation?
/// Note that this is a purely syntactic property meaning that even if this is false,
/// the code can still contain calls to functions that contain the msize instruction.
bool m_containsMSize = false;
/// If false, storage is guaranteed to be unchanged by the code under all /// If false, storage is guaranteed to be unchanged by the code under all
/// circumstances. /// circumstances.
bool m_invalidatesStorage = false; bool m_invalidatesStorage = false;
bool m_invalidatesMemory = false; bool m_invalidatesMemory = false;
}; };
/**
* Class that can be used to find out if certain code contains the MSize instruction.
*
* Note that this is a purely syntactic property meaning that even if this is false,
* the code can still contain calls to functions that contain the msize instruction.
*
* The only safe way to determine this is by passing the full AST.
*/
class MSizeFinder: public ASTWalker
{
public:
static bool containsMSize(Dialect const& _dialect, Block const& _ast);
using ASTWalker::operator();
void operator()(FunctionalInstruction const& _instr);
void operator()(FunctionCall const& _funCall);
private:
MSizeFinder(Dialect const& _dialect): m_dialect(_dialect) {}
Dialect const& m_dialect;
bool m_msizeFound = false;
};
/** /**
* Specific AST walker that determines whether an expression is movable * Specific AST walker that determines whether an expression is movable
* and collects the referenced variables. * and collects the referenced variables.

View File

@ -165,7 +165,7 @@ bool StackCompressor::run(
_object.code->statements.size() > 0 && _object.code->statements.at(0).type() == typeid(Block), _object.code->statements.size() > 0 && _object.code->statements.at(0).type() == typeid(Block),
"Need to run the function grouper before the stack compressor." "Need to run the function grouper before the stack compressor."
); );
bool allowMSizeOptimzation = !SideEffectsCollector(_dialect, *_object.code).containsMSize(); bool allowMSizeOptimzation = !MSizeFinder::containsMSize(_dialect, *_object.code);
for (size_t iterations = 0; iterations < _maxIterations; iterations++) for (size_t iterations = 0; iterations < _maxIterations; iterations++)
{ {
map<YulString, int> stackSurplus = CompilabilityChecker::run(_dialect, _object, _optimizeStackAllocation); map<YulString, int> stackSurplus = CompilabilityChecker::run(_dialect, _object, _optimizeStackAllocation);

View File

@ -138,7 +138,7 @@ void UnusedPruner::runUntilStabilised(
set<YulString> const& _externallyUsedFunctions set<YulString> const& _externallyUsedFunctions
) )
{ {
bool allowMSizeOptimization = !SideEffectsCollector(_dialect, _ast).containsMSize(); bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast);
runUntilStabilised(_dialect, _ast, allowMSizeOptimization, _externallyUsedFunctions); runUntilStabilised(_dialect, _ast, allowMSizeOptimization, _externallyUsedFunctions);
} }