From 8a4497a8d32355e29f7008db25b4f0e0ae4f1235 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 15 Apr 2021 15:13:31 +0200 Subject: [PATCH] Fix argument stack slot reuse for functions without return variables. --- libyul/backends/evm/EVMCodeTransform.cpp | 6 ++-- libyul/backends/evm/EVMCodeTransform.h | 4 +++ ...ction_argument_reuse_without_retparams.yul | 29 +++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 8c8efe46d..ba4eb5135 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -402,7 +402,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) subTransform.deleteVariable(var); } - if (!m_allowStackOpt || _function.returnVariables.empty()) + if (!m_allowStackOpt) subTransform.setupReturnVariablesAndFunctionExit(); subTransform(_function.body); @@ -592,6 +592,7 @@ void CodeTransform::visitExpression(Expression const& _expression) void CodeTransform::setupReturnVariablesAndFunctionExit() { + yulAssert(isInsideFunction(), ""); yulAssert(!returnVariablesAndFunctionExitAreSetup(), ""); yulAssert(m_scope, ""); @@ -654,7 +655,8 @@ void CodeTransform::visitStatements(vector const& _statements) { freeUnusedVariables(); if ( - !m_delayedReturnVariables.empty() && + isInsideFunction() && + !returnVariablesAndFunctionExitAreSetup() && statementNeedsReturnVariableSetup(statement, m_delayedReturnVariables) ) setupReturnVariablesAndFunctionExit(); diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index be7fef528..bf4f8520d 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -183,6 +183,10 @@ private: { return m_functionExitStackHeight.has_value(); } + bool isInsideFunction() const + { + return m_functionExitLabel.has_value(); + } AbstractAssembly& m_assembly; AsmAnalysisInfo& m_info; diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul new file mode 100644 index 000000000..d1f6b5bdc --- /dev/null +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul @@ -0,0 +1,29 @@ +{ + function f(x, y) { + mstore(0x80, x) + if calldataload(0) { sstore(y, y) } + } +} +// ==== +// stackOptimization: true +// ---- +// PUSH1 0x17 +// JUMP +// JUMPDEST +// DUP1 +// PUSH1 0x80 +// MSTORE +// POP +// PUSH1 0x0 +// CALLDATALOAD +// ISZERO +// PUSH1 0x13 +// JUMPI +// DUP1 +// DUP2 +// SSTORE +// JUMPDEST +// POP +// JUMPDEST +// JUMP +// JUMPDEST