From f3c2d6cfdc0043b8fd2de51a53e707ae968e0e8c Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 17 Sep 2020 18:00:08 +0200 Subject: [PATCH] Move memory load and store functions to the dialect. --- libyul/Dialect.h | 3 +++ libyul/backends/evm/EVMDialect.h | 2 ++ libyul/optimiser/StackToMemoryMover.cpp | 18 +++++++++++++++--- libyul/optimiser/StackToMemoryMover.h | 2 ++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libyul/Dialect.h b/libyul/Dialect.h index d47c09659..78b950d58 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -72,6 +72,9 @@ struct Dialect: boost::noncopyable virtual BuiltinFunction const* equalityFunction(YulString /* _type */) 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. /// Should only be called if the type exists in the dialect at all. virtual bool validTypeForLiteral(LiteralKind _kind, YulString _value, YulString _type) const; diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index fe1c67a4a..8cac1e0be 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -73,6 +73,8 @@ struct EVMDialect: public Dialect BuiltinFunctionForEVM const* discardFunction(YulString /*_type*/) const override { return builtin("pop"_yulstring); } BuiltinFunctionForEVM const* equalityFunction(YulString /*_type*/) const override { return builtin("eq"_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& strictAssemblyForEVMObjects(langutil::EVMVersion _version); diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index 136a6043d..385d508f2 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -30,15 +30,18 @@ using namespace solidity::yul; namespace { vector generateMemoryStore( + Dialect const& _dialect, langutil::SourceLocation const& _loc, YulString _mpos, Expression _value ) { + BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType); + yulAssert(memoryStoreFunction, ""); vector result; result.emplace_back(ExpressionStatement{_loc, FunctionCall{ _loc, - Identifier{_loc, "mstore"_yulstring}, + Identifier{_loc, memoryStoreFunction->name}, { Literal{_loc, LiteralKind::Number, _mpos, {}}, std::move(_value) @@ -66,6 +69,7 @@ StackToMemoryMover::StackToMemoryMover( map> const& _memorySlots, uint64_t _numRequiredSlots ): +m_context(_context), m_reservedMemory(std::move(_reservedMemory)), m_memorySlots(_memorySlots), m_numRequiredSlots(_numRequiredSlots), @@ -120,6 +124,7 @@ void StackToMemoryMover::operator()(Block& _block) ) -> std::vector { if (_variables.size() == 1) return generateMemoryStore( + m_context.dialect, _loc, memoryOffset(_variables.front().name), _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, {}}); 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, Identifier>) variableAssignments.emplace_back(Assignment{ _loc, { Identifier{var.location, var.name} }, @@ -196,10 +206,12 @@ void StackToMemoryMover::visit(Expression& _expression) 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; _expression = FunctionCall{ loc, - Identifier{loc, "mload"_yulstring}, { + Identifier{loc, memoryLoadFunction->name}, { Literal{ loc, LiteralKind::Number, diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index cf582aba6..ea38ea119 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -109,6 +109,8 @@ private: /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal. YulString memoryOffset(YulString _variable); + + OptimiserStepContext& m_context; u256 m_reservedMemory; std::map> const& m_memorySlots; uint64_t m_numRequiredSlots = 0;