diff options
-rw-r--r-- | libjulia/backends/evm/EVMCodeTransform.cpp | 27 | ||||
-rw-r--r-- | libjulia/backends/evm/EVMCodeTransform.h | 10 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 6 |
3 files changed, 28 insertions, 15 deletions
diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp index 853c4b78..c9624f82 100644 --- a/libjulia/backends/evm/EVMCodeTransform.cpp +++ b/libjulia/backends/evm/EVMCodeTransform.cpp @@ -105,6 +105,7 @@ void CodeTransform::operator()(FunctionCall const& _call) { returnLabel = m_assembly.newLabelId(); m_assembly.appendLabelReference(returnLabel); + m_stackAdjustment++; } Scope::Function* function = nullptr; @@ -125,6 +126,7 @@ void CodeTransform::operator()(FunctionCall const& _call) { m_assembly.appendJumpTo(*function->id, function->returns.size() - function->arguments.size() - 1); m_assembly.appendLabel(returnLabel); + m_stackAdjustment--; } checkStackHeight(&_call); } @@ -280,7 +282,8 @@ void CodeTransform::operator()(FunctionDefinition const& _function) Scope::Function& function = boost::get<Scope::Function>(m_scope->identifiers.at(_function.name)); assignLabelIdIfUnset(function.id); - int height = m_evm15 ? 0 : 1; + int const localStackAdjustment = m_evm15 ? 0 : 1; + int height = localStackAdjustment; solAssert(m_info.scopes.at(&_function.body), ""); Scope* varScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get(); solAssert(varScope, ""); @@ -294,12 +297,18 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_assembly.setSourceLocation(_function.location); int stackHeightBefore = m_assembly.stackHeight(); AbstractAssembly::LabelID afterFunction = m_assembly.newLabelId(); - m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height); if (m_evm15) + { + m_assembly.appendJumpTo(afterFunction, -stackHeightBefore); m_assembly.appendBeginsub(*function.id, _function.arguments.size()); + } else + { + m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height); m_assembly.appendLabel(*function.id); + } + m_stackAdjustment += localStackAdjustment; for (auto const& v: _function.returns) { @@ -309,10 +318,11 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_assembly.appendConstant(u256(0)); } - CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, 0).run(_function.body); + CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment) + .run(_function.body); - if (_function.arguments.size() > 0) { + // Stack of target positions of stack elements vector<int> stackLayout; if (!m_evm15) stackLayout.push_back(_function.returns.size()); // Move return label to the top @@ -321,7 +331,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) stackLayout.push_back(i); solAssert(stackLayout.size() <= 17, "Stack too deep"); - while (stackLayout.back() != int(stackLayout.size() - 1)) + while (!stackLayout.empty() && stackLayout.back() != int(stackLayout.size() - 1)) if (stackLayout.back() < 0) { m_assembly.appendInstruction(solidity::Instruction::POP); @@ -340,13 +350,14 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_assembly.appendReturnsub(_function.returns.size()); else m_assembly.appendJump(stackHeightBefore - _function.returns.size()); + m_stackAdjustment -= localStackAdjustment; m_assembly.appendLabel(afterFunction); checkStackHeight(&_function); } void CodeTransform::operator()(Block const& _block) { - CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_initialStackHeight).run(_block); + CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block); } AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier) @@ -420,11 +431,11 @@ void CodeTransform::checkStackHeight(void const* _astElement) { solAssert(m_info.stackHeightInfo.count(_astElement), "Stack height for AST element not found."); solAssert( - m_info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_initialStackHeight, + m_info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_stackAdjustment, "Stack height mismatch between analysis and code generation phase: Analysis: " + to_string(m_info.stackHeightInfo.at(_astElement)) + " code gen: " + - to_string(m_assembly.stackHeight() - m_initialStackHeight) + to_string(m_assembly.stackHeight() - m_stackAdjustment) ); } diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h index d82462a7..a817efea 100644 --- a/libjulia/backends/evm/EVMCodeTransform.h +++ b/libjulia/backends/evm/EVMCodeTransform.h @@ -80,14 +80,14 @@ protected: solidity::assembly::AsmAnalysisInfo& _analysisInfo, bool _evm15, ExternalIdentifierAccess const& _identifierAccess, - int _initialStackHeight + int _stackAdjustment ): m_errorReporter(_errorReporter), m_assembly(_assembly), m_info(_analysisInfo), m_evm15(_evm15), m_identifierAccess(_identifierAccess), - m_initialStackHeight(_initialStackHeight) + m_stackAdjustment(_stackAdjustment) {} public: @@ -128,7 +128,11 @@ public: solidity::assembly::Scope* m_scope = nullptr; bool m_evm15 = false; ExternalIdentifierAccess m_identifierAccess; - int const m_initialStackHeight; + /// Adjustment between the stack height as determined during the analysis phase + /// and the stack height in the assembly. This is caused by an initial stack being present + /// for inline assembly and different stack heights depending on the EVM backend used + /// (EVM 1.0 or 1.5). + int m_stackAdjustment = 0; }; } diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index b59a8527..bfc6b2af 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -203,8 +203,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) } int const stackHeight = m_stackHeight; - // 1 for return label, depends on VM version - m_stackHeight = 1 + _funDef.arguments.size() + _funDef.returns.size(); + m_stackHeight = _funDef.arguments.size() + _funDef.returns.size(); bool success = (*this)(_funDef.body); @@ -258,11 +257,10 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall) success = false; } } - m_stackHeight += 1; // Return label, but depends on backend for (auto const& arg: _funCall.arguments | boost::adaptors::reversed) if (!expectExpression(arg)) success = false; - m_stackHeight += int(returns) - int(arguments) - 1; // Return label, but depends on backend + m_stackHeight += int(returns) - int(arguments); m_info.stackHeightInfo[&_funCall] = m_stackHeight; return success; } |