mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge 87ce29542c
into 72671d6c88
This commit is contained in:
commit
5184077816
@ -81,6 +81,7 @@ Compiler Features:
|
|||||||
* SMTChecker: Properties that are proved safe are now reported explicitly at the end of analysis. By default, only the number of safe properties is shown. The CLI option ``--model-checker-show-proved-safe`` and the JSON option ``settings.modelChecker.showProvedSafe`` can be enabled to show the full list of safe properties.
|
* SMTChecker: Properties that are proved safe are now reported explicitly at the end of analysis. By default, only the number of safe properties is shown. The CLI option ``--model-checker-show-proved-safe`` and the JSON option ``settings.modelChecker.showProvedSafe`` can be enabled to show the full list of safe properties.
|
||||||
* Standard JSON Interface: Add experimental support for importing ASTs via Standard JSON.
|
* Standard JSON Interface: Add experimental support for importing ASTs via Standard JSON.
|
||||||
* Yul EVM Code Transform: If available, use ``push0`` instead of ``codesize`` to produce an arbitrary value on stack in order to create equal stack heights between branches.
|
* Yul EVM Code Transform: If available, use ``push0`` instead of ``codesize`` to produce an arbitrary value on stack in order to create equal stack heights between branches.
|
||||||
|
* Yul IR Code Generation: Cheaper code for reverting with errors of a static small encoding size.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <libsolutil/FunctionSelector.h>
|
#include <libsolutil/FunctionSelector.h>
|
||||||
#include <libsolutil/Visitor.h>
|
#include <libsolutil/Visitor.h>
|
||||||
|
|
||||||
|
#include <range/v3/algorithm/all_of.hpp>
|
||||||
#include <range/v3/view/transform.hpp>
|
#include <range/v3/view/transform.hpp>
|
||||||
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
@ -57,6 +58,18 @@ using namespace std::string_literals;
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
optional<size_t> staticEncodingSize(vector<Type const*> const& _parameterTypes)
|
||||||
|
{
|
||||||
|
size_t encodedSize = 0;
|
||||||
|
for (auto const* type: _parameterTypes)
|
||||||
|
{
|
||||||
|
if (type->isDynamicallyEncoded())
|
||||||
|
return nullopt;
|
||||||
|
encodedSize += type->calldataHeadSize();
|
||||||
|
}
|
||||||
|
return encodedSize;
|
||||||
|
}
|
||||||
|
|
||||||
struct CopyTranslate: public yul::ASTCopier
|
struct CopyTranslate: public yul::ASTCopier
|
||||||
{
|
{
|
||||||
using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>;
|
using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>;
|
||||||
@ -3362,8 +3375,16 @@ void IRGeneratorForStatements::revertWithError(
|
|||||||
std::vector<ASTPointer<Expression const>> const& _errorArguments
|
std::vector<ASTPointer<Expression const>> const& _errorArguments
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
bool needsAllocation = true;
|
||||||
|
if (optional<size_t> size = staticEncodingSize(_parameterTypes))
|
||||||
|
if (ranges::all_of(_parameterTypes, [](auto const* type) { return type && type->isValueType(); }))
|
||||||
|
needsAllocation = *size + 4 > CompilerUtils::generalPurposeMemoryStart;
|
||||||
Whiskers templ(R"({
|
Whiskers templ(R"({
|
||||||
|
<?needsAllocation>
|
||||||
let <pos> := <allocateUnbounded>()
|
let <pos> := <allocateUnbounded>()
|
||||||
|
<!needsAllocation>
|
||||||
|
let <pos> := 0
|
||||||
|
</needsAllocation>
|
||||||
mstore(<pos>, <hash>)
|
mstore(<pos>, <hash>)
|
||||||
let <end> := <encode>(add(<pos>, 4) <argumentVars>)
|
let <end> := <encode>(add(<pos>, 4) <argumentVars>)
|
||||||
revert(<pos>, sub(<end>, <pos>))
|
revert(<pos>, sub(<end>, <pos>))
|
||||||
@ -3371,6 +3392,8 @@ void IRGeneratorForStatements::revertWithError(
|
|||||||
templ("pos", m_context.newYulVariable());
|
templ("pos", m_context.newYulVariable());
|
||||||
templ("end", m_context.newYulVariable());
|
templ("end", m_context.newYulVariable());
|
||||||
templ("hash", util::selectorFromSignatureU256(_signature).str());
|
templ("hash", util::selectorFromSignatureU256(_signature).str());
|
||||||
|
templ("needsAllocation", needsAllocation);
|
||||||
|
if (needsAllocation)
|
||||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||||
|
|
||||||
std::vector<std::string> errorArgumentVars;
|
std::vector<std::string> errorArgumentVars;
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
error E();
|
||||||
|
contract A {
|
||||||
|
uint8[] x;
|
||||||
|
function f() public {
|
||||||
|
for (uint i = 0; i < 100; ++i)
|
||||||
|
x.push(uint8(i));
|
||||||
|
revert E();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract B {
|
||||||
|
function f() public {
|
||||||
|
(new A()).f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// f() -> FAILURE, hex"92bbf6e8"
|
||||||
|
// gas irOptimized: 270934
|
||||||
|
// gas legacy: 310592
|
||||||
|
// gas legacyOptimized: 273662
|
Loading…
Reference in New Issue
Block a user