Move memory load and store functions to the dialect.

This commit is contained in:
Daniel Kirchner 2020-09-17 18:00:08 +02:00
parent 48f620fb50
commit f3c2d6cfdc
4 changed files with 22 additions and 3 deletions

View File

@ -72,6 +72,9 @@ struct Dialect: boost::noncopyable
virtual BuiltinFunction const* equalityFunction(YulString /* _type */) const { return nullptr; } virtual BuiltinFunction const* equalityFunction(YulString /* _type */) const { return nullptr; }
virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; }
virtual BuiltinFunction const* memoryStoreFunction(YulString /* _type */) const { return nullptr; }
virtual BuiltinFunction const* memoryLoadFunction(YulString /* _type */) const { return nullptr; }
/// Check whether the given type is legal for the given literal value. /// Check whether the given type is legal for the given literal value.
/// Should only be called if the type exists in the dialect at all. /// Should only be called if the type exists in the dialect at all.
virtual bool validTypeForLiteral(LiteralKind _kind, YulString _value, YulString _type) const; virtual bool validTypeForLiteral(LiteralKind _kind, YulString _value, YulString _type) const;

View File

@ -73,6 +73,8 @@ struct EVMDialect: public Dialect
BuiltinFunctionForEVM const* discardFunction(YulString /*_type*/) const override { return builtin("pop"_yulstring); } BuiltinFunctionForEVM const* discardFunction(YulString /*_type*/) const override { return builtin("pop"_yulstring); }
BuiltinFunctionForEVM const* equalityFunction(YulString /*_type*/) const override { return builtin("eq"_yulstring); } BuiltinFunctionForEVM const* equalityFunction(YulString /*_type*/) const override { return builtin("eq"_yulstring); }
BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulstring); } BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulstring); }
BuiltinFunctionForEVM const* memoryStoreFunction(YulString /*_type*/) const override { return builtin("mstore"_yulstring); }
BuiltinFunctionForEVM const* memoryLoadFunction(YulString /*_type*/) const override { return builtin("mload"_yulstring); }
static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version);
static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version);

View File

@ -30,15 +30,18 @@ using namespace solidity::yul;
namespace namespace
{ {
vector<Statement> generateMemoryStore( vector<Statement> generateMemoryStore(
Dialect const& _dialect,
langutil::SourceLocation const& _loc, langutil::SourceLocation const& _loc,
YulString _mpos, YulString _mpos,
Expression _value Expression _value
) )
{ {
BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType);
yulAssert(memoryStoreFunction, "");
vector<Statement> result; vector<Statement> result;
result.emplace_back(ExpressionStatement{_loc, FunctionCall{ result.emplace_back(ExpressionStatement{_loc, FunctionCall{
_loc, _loc,
Identifier{_loc, "mstore"_yulstring}, Identifier{_loc, memoryStoreFunction->name},
{ {
Literal{_loc, LiteralKind::Number, _mpos, {}}, Literal{_loc, LiteralKind::Number, _mpos, {}},
std::move(_value) std::move(_value)
@ -66,6 +69,7 @@ StackToMemoryMover::StackToMemoryMover(
map<YulString, map<YulString, uint64_t>> const& _memorySlots, map<YulString, map<YulString, uint64_t>> const& _memorySlots,
uint64_t _numRequiredSlots uint64_t _numRequiredSlots
): ):
m_context(_context),
m_reservedMemory(std::move(_reservedMemory)), m_reservedMemory(std::move(_reservedMemory)),
m_memorySlots(_memorySlots), m_memorySlots(_memorySlots),
m_numRequiredSlots(_numRequiredSlots), m_numRequiredSlots(_numRequiredSlots),
@ -120,6 +124,7 @@ void StackToMemoryMover::operator()(Block& _block)
) -> std::vector<Statement> { ) -> std::vector<Statement> {
if (_variables.size() == 1) if (_variables.size() == 1)
return generateMemoryStore( return generateMemoryStore(
m_context.dialect,
_loc, _loc,
memoryOffset(_variables.front().name), memoryOffset(_variables.front().name),
_value ? *std::move(_value) : Literal{_loc, LiteralKind::Number, "0"_yulstring, {}} _value ? *std::move(_value) : Literal{_loc, LiteralKind::Number, "0"_yulstring, {}}
@ -134,7 +139,12 @@ void StackToMemoryMover::operator()(Block& _block)
tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}}); tempDecl.variables.emplace_back(TypedName{var.location, tempVarName, {}});
if (m_currentFunctionMemorySlots->count(var.name)) if (m_currentFunctionMemorySlots->count(var.name))
memoryAssignments += generateMemoryStore(_loc, memoryOffset(var.name), Identifier{_loc, tempVarName}); memoryAssignments += generateMemoryStore(
m_context.dialect,
_loc,
memoryOffset(var.name),
Identifier{_loc, tempVarName}
);
else if constexpr (std::is_same_v<std::decay_t<decltype(var)>, Identifier>) else if constexpr (std::is_same_v<std::decay_t<decltype(var)>, Identifier>)
variableAssignments.emplace_back(Assignment{ variableAssignments.emplace_back(Assignment{
_loc, { Identifier{var.location, var.name} }, _loc, { Identifier{var.location, var.name} },
@ -196,10 +206,12 @@ void StackToMemoryMover::visit(Expression& _expression)
identifier && m_currentFunctionMemorySlots && m_currentFunctionMemorySlots->count(identifier->name) identifier && m_currentFunctionMemorySlots && m_currentFunctionMemorySlots->count(identifier->name)
) )
{ {
BuiltinFunction const* memoryLoadFunction = m_context.dialect.memoryLoadFunction(m_context.dialect.defaultType);
yulAssert(memoryLoadFunction, "");
langutil::SourceLocation loc = identifier->location; langutil::SourceLocation loc = identifier->location;
_expression = FunctionCall{ _expression = FunctionCall{
loc, loc,
Identifier{loc, "mload"_yulstring}, { Identifier{loc, memoryLoadFunction->name}, {
Literal{ Literal{
loc, loc,
LiteralKind::Number, LiteralKind::Number,

View File

@ -109,6 +109,8 @@ private:
/// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal. /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal.
YulString memoryOffset(YulString _variable); YulString memoryOffset(YulString _variable);
OptimiserStepContext& m_context;
u256 m_reservedMemory; u256 m_reservedMemory;
std::map<YulString, std::map<YulString, uint64_t>> const& m_memorySlots; std::map<YulString, std::map<YulString, uint64_t>> const& m_memorySlots;
uint64_t m_numRequiredSlots = 0; uint64_t m_numRequiredSlots = 0;