This commit is contained in:
Daniel 2023-10-02 13:12:00 -06:00 committed by GitHub
commit 5184077816
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 1 deletions

View File

@ -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.
* 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 IR Code Generation: Cheaper code for reverting with errors of a static small encoding size.
Bugfixes:

View File

@ -47,6 +47,7 @@
#include <libsolutil/FunctionSelector.h>
#include <libsolutil/Visitor.h>
#include <range/v3/algorithm/all_of.hpp>
#include <range/v3/view/transform.hpp>
using namespace solidity;
@ -57,6 +58,18 @@ using namespace std::string_literals;
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
{
using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>;
@ -3362,8 +3375,16 @@ void IRGeneratorForStatements::revertWithError(
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"({
<?needsAllocation>
let <pos> := <allocateUnbounded>()
<!needsAllocation>
let <pos> := 0
</needsAllocation>
mstore(<pos>, <hash>)
let <end> := <encode>(add(<pos>, 4) <argumentVars>)
revert(<pos>, sub(<end>, <pos>))
@ -3371,7 +3392,9 @@ void IRGeneratorForStatements::revertWithError(
templ("pos", m_context.newYulVariable());
templ("end", m_context.newYulVariable());
templ("hash", util::selectorFromSignatureU256(_signature).str());
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
templ("needsAllocation", needsAllocation);
if (needsAllocation)
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
std::vector<std::string> errorArgumentVars;
std::vector<Type const*> errorArgumentTypes;

View File

@ -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