diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 397d20f16..abae23a83 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -163,7 +164,7 @@ AssemblyItems CSECodeGenerator::generateCode( // Invalid sequenced operation. // @todo quick fix for now. Proper fix needs to choose representative with higher // sequence number during dependency analysis. - assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, ""); + assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, util::stackTooDeepString); sequencedExpressions.insert(make_pair(seqNr, id)); } @@ -471,7 +472,7 @@ void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _locat { assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); int instructionNum = 1 + m_stackHeight - _fromPosition; - assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep, try removing local variables."); + assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); appendItem(AssemblyItem(dupInstruction(static_cast(instructionNum)), _location)); m_stack[m_stackHeight] = m_stack[_fromPosition]; @@ -484,7 +485,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons if (_fromPosition == m_stackHeight) return; int instructionNum = m_stackHeight - _fromPosition; - assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep, try removing local variables."); + assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); appendItem(AssemblyItem(swapInstruction(static_cast(instructionNum)), _location)); diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index d2691c877..725727869 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -242,7 +243,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons assertThrow( 2 + byteOffsetSize + sourceBaseType->sizeOnStack() <= 16, StackTooDeepError, - "Stack too deep, try removing local variables." + util::stackTooDeepString ); // fetch target storage reference _context << dupInstruction(2 + byteOffsetSize + sourceBaseType->sizeOnStack()); diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 99b87e5a7..55089dde1 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -422,7 +423,7 @@ void CompilerContext::appendInlineAssembly( BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(nativeLocationOf(_identifier)) << - util::errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); if (_context == yul::IdentifierContext::RValue) _assembly.appendInstruction(dupInstruction(static_cast(stackDiff))); diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 0ad37241b..32b1f1bba 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -31,6 +31,7 @@ #include #include #include +#include using namespace std; using namespace solidity; @@ -476,7 +477,7 @@ void CompilerUtils::encodeToMemory( assertThrow( (argSize + dynPointers) < 16, StackTooDeepError, - "Stack too deep, try using fewer variables." + util::stackTooDeepString ); } else @@ -537,7 +538,7 @@ void CompilerUtils::encodeToMemory( assertThrow( (2 + dynPointers) <= 16, StackTooDeepError, - "Stack too deep(" + to_string(2 + dynPointers) + "), try using fewer variables." + util::stackTooDeepString ); m_context << dupInstruction(2 + dynPointers) << Instruction::DUP2; m_context << Instruction::SUB; @@ -1418,7 +1419,7 @@ void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_variable.location()) << - util::errinfo_comment("Stack too deep, try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); for (unsigned i = 0; i < size; ++i) m_context << swapInstruction(stackPosition - size + 1) << Instruction::POP; @@ -1429,7 +1430,7 @@ void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize) assertThrow( _stackDepth <= 16, StackTooDeepError, - "Stack too deep, try removing local variables." + util::stackTooDeepString ); for (unsigned i = 0; i < _itemSize; ++i) m_context << dupInstruction(_stackDepth); @@ -1455,7 +1456,7 @@ void CompilerUtils::rotateStackUp(unsigned _items) assertThrow( _items - 1 <= 16, StackTooDeepError, - "Stack too deep, try removing local variables." + util::stackTooDeepString ); for (unsigned i = 1; i < _items; ++i) m_context << swapInstruction(_items - i); @@ -1466,7 +1467,7 @@ void CompilerUtils::rotateStackDown(unsigned _items) assertThrow( _items - 1 <= 16, StackTooDeepError, - "Stack too deep, try removing local variables." + util::stackTooDeepString ); for (unsigned i = 1; i < _items; ++i) m_context << swapInstruction(i); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index d2c71e2af..bdad48173 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -48,6 +48,7 @@ #include #include +#include #include @@ -672,7 +673,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_function.location()) << - util::errinfo_comment("Stack too deep, try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); while (!stackLayout.empty() && stackLayout.back() != static_cast(stackLayout.size() - 1)) if (stackLayout.back() < 0) @@ -842,7 +843,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_inlineAssembly.location()) << - util::errinfo_comment("Stack too deep, try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); _assembly.appendInstruction(dupInstruction(stackDiff)); } @@ -916,7 +917,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_inlineAssembly.location()) << - util::errinfo_comment("Stack too deep(" + to_string(stackDiff) + "), try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); _assembly.appendInstruction(swapInstruction(stackDiff)); _assembly.appendInstruction(Instruction::POP); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 21cb45e77..36646ea21 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -268,7 +269,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_varDecl.location()) << - util::errinfo_comment("Stack too deep.") + util::errinfo_comment(util::stackTooDeepString) ); m_context << dupInstruction(retSizeOnStack + 1); m_context.appendJump(evmasm::AssemblyItem::JumpType::OutOfFunction); @@ -350,7 +351,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_assignment.location()) << - util::errinfo_comment("Stack too deep, try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); // value [lvalue_ref] updated_value for (unsigned i = 0; i < itemSize; ++i) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 379e9818b..aa7524c93 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace std; using namespace solidity; using namespace solidity::evmasm; @@ -50,7 +52,7 @@ void StackVariable::retrieveValue(SourceLocation const& _location, bool) const BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_location) << - util::errinfo_comment("Stack too deep, try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); solAssert(stackPos + 1 >= m_size, "Size and stack pos mismatch."); for (unsigned i = 0; i < m_size; ++i) @@ -64,7 +66,7 @@ void StackVariable::storeValue(Type const&, SourceLocation const& _location, boo BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_location) << - util::errinfo_comment("Stack too deep, try removing local variables.") + util::errinfo_comment(util::stackTooDeepString) ); else if (stackDiff > 0) for (unsigned i = 0; i < m_size; ++i) diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index e055317be..363baba19 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -28,6 +28,7 @@ set(sources picosha2.h Result.h SetOnce.h + StackTooDeepString.h StringUtils.cpp StringUtils.h SwarmHash.cpp diff --git a/libsolutil/StackTooDeepString.h b/libsolutil/StackTooDeepString.h new file mode 100644 index 000000000..75fe557e2 --- /dev/null +++ b/libsolutil/StackTooDeepString.h @@ -0,0 +1,28 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#pragma once + +#include + +namespace solidity::util +{ + static std::string stackTooDeepString = + "Stack too deep. " + "Try compiling with `--via-ir` (cli) or the equivalent `viaIR: true` (standard JSON) " + "while enabling the optimizer. Otherwise, try removing local variables."; +} diff --git a/libyul/backends/evm/AsmCodeGen.cpp b/libyul/backends/evm/AsmCodeGen.cpp index 6ef142906..c4d276fa1 100644 --- a/libyul/backends/evm/AsmCodeGen.cpp +++ b/libyul/backends/evm/AsmCodeGen.cpp @@ -26,6 +26,8 @@ #include #include +#include + using namespace std; using namespace solidity; using namespace solidity::yul; @@ -61,7 +63,7 @@ void CodeGenerator::assemble( assertThrow( false, langutil::StackTooDeepError, - "Stack too deep when compiling inline assembly" + + util::stackTooDeepString + " When compiling inline assembly" + (transform.stackErrors().front().comment() ? ": " + *transform.stackErrors().front().comment() : ".") ); } diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 8497fc0c0..319a60885 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1428,7 +1428,7 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization) BOOST_REQUIRE(result["errors"].isArray()); BOOST_CHECK(result["errors"][0]["severity"] == "error"); BOOST_REQUIRE(result["errors"][0]["message"].isString()); - BOOST_CHECK(result["errors"][0]["message"].asString().find("Stack too deep when compiling inline assembly") != std::string::npos); + BOOST_CHECK(result["errors"][0]["message"].asString().find("When compiling inline assembly") != std::string::npos); BOOST_CHECK(result["errors"][0]["type"] == "CompilerError"); }