returnSize assigned according to truth value of returnInfo.dynamicReturnSize

This commit is contained in:
nishant-sachdeva 2022-02-16 17:33:39 +05:30
parent ebefb5d980
commit beabc51c20
40 changed files with 261 additions and 116 deletions

View File

@ -54,4 +54,6 @@ ReturnInfo::ReturnInfo(EVMVersion const& _evmVersion, FunctionType const& _funct
estimatedReturnSize += retType->decodingType()->calldataEncodedSize(); estimatedReturnSize += retType->decodingType()->calldataEncodedSize();
} }
} }
if (dynamicReturnSize)
solAssert(estimatedReturnSize == 0);
} }

View File

@ -2505,6 +2505,8 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n"; appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
} }
// NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically.
// When it's dynamic, we get zero from estimatedReturnSize() instead and then we need an explicit returndatacopy().
Whiskers templ(R"( Whiskers templ(R"(
<?checkExtcodesize> <?checkExtcodesize>
if iszero(extcodesize(<address>)) { <revertNoCode>() } if iszero(extcodesize(<address>)) { <revertNoCode>() }
@ -2514,22 +2516,29 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
mstore(<pos>, <shl28>(<funSel>)) mstore(<pos>, <shl28>(<funSel>))
let <end> := <encodeArgs>(add(<pos>, 4) <argumentString>) let <end> := <encodeArgs>(add(<pos>, 4) <argumentString>)
let <success> := <call>(<gas>, <address>, <?hasValue> <value>, </hasValue> <pos>, sub(<end>, <pos>), <pos>, <reservedReturnSize>) let <success> := <call>(<gas>, <address>, <?hasValue> <value>, </hasValue> <pos>, sub(<end>, <pos>), <pos>, <staticReturndataSize>)
<?noTryCall> <?noTryCall>
if iszero(<success>) { <forwardingRevert>() } if iszero(<success>) { <forwardingRevert>() }
</noTryCall> </noTryCall>
<?+retVars> let <retVars> </+retVars> <?+retVars> let <retVars> </+retVars>
if <success> { if <success> {
<?dynamicReturnSize> <?isReturndataSizeDynamic>
// copy dynamic return data out let <returnDataSizeVar> := returndatasize()
returndatacopy(<pos>, 0, returndatasize()) returndatacopy(<pos>, 0, <returnDataSizeVar>)
</dynamicReturnSize> <!isReturndataSizeDynamic>
let <returnDataSizeVar> := <staticReturndataSize>
<?supportsReturnData>
if gt(<returnDataSizeVar>, returndatasize()) {
<returnDataSizeVar> := returndatasize()
}
</supportsReturnData>
</isReturndataSizeDynamic>
// update freeMemoryPointer according to dynamic return size // update freeMemoryPointer according to dynamic return size
<finalizeAllocation>(<pos>, <returnSize>) <finalizeAllocation>(<pos>, <returnDataSizeVar>)
// decode return parameters from external try-call into retVars // decode return parameters from external try-call into retVars
<?+retVars> <retVars> := </+retVars> <abiDecode>(<pos>, add(<pos>, <returnSize>)) <?+retVars> <retVars> := </+retVars> <abiDecode>(<pos>, add(<pos>, <returnDataSizeVar>))
} }
)"); )");
templ("revertNoCode", m_utils.revertReasonIfDebugFunction("Target contract does not contain code")); templ("revertNoCode", m_utils.revertReasonIfDebugFunction("Target contract does not contain code"));
@ -2558,21 +2567,18 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
templ("funSel", IRVariable(_functionCall.expression()).part("functionSelector").name()); templ("funSel", IRVariable(_functionCall.expression()).part("functionSelector").name());
templ("address", IRVariable(_functionCall.expression()).part("address").name()); templ("address", IRVariable(_functionCall.expression()).part("address").name());
// Always use the actual return length, and not our calculated expected length, if returndatacopy is supported. if (returnInfo.dynamicReturnSize)
// This ensures it can catch badly formatted input from external calls. solAssert(m_context.evmVersion().supportsReturndata());
if (m_context.evmVersion().supportsReturndata()) templ("returnDataSizeVar", m_context.newYulVariable());
templ("returnSize", "returndatasize()"); templ("staticReturndataSize", to_string(returnInfo.estimatedReturnSize));
else templ("supportsReturnData", m_context.evmVersion().supportsReturndata());
templ("returnSize", to_string(returnInfo.estimatedReturnSize));
templ("reservedReturnSize", returnInfo.dynamicReturnSize ? "0" : to_string(returnInfo.estimatedReturnSize));
string const retVars = IRVariable(_functionCall).commaSeparatedList(); string const retVars = IRVariable(_functionCall).commaSeparatedList();
templ("retVars", retVars); templ("retVars", retVars);
solAssert(retVars.empty() == returnInfo.returnTypes.empty()); solAssert(retVars.empty() == returnInfo.returnTypes.empty());
templ("abiDecode", m_context.abiFunctions().tupleDecoder(returnInfo.returnTypes, true)); templ("abiDecode", m_context.abiFunctions().tupleDecoder(returnInfo.returnTypes, true));
templ("dynamicReturnSize", returnInfo.dynamicReturnSize); templ("isReturndataSizeDynamic", returnInfo.dynamicReturnSize);
templ("noTryCall", !_functionCall.annotation().tryCall); templ("noTryCall", !_functionCall.annotation().tryCall);

View File

@ -265,34 +265,39 @@ sub_0: assembly {
return return
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
tag_36: tag_36:
/* \"C\":79:428 contract C... */
swap1 swap1
swap2 swap2
pop pop
/* \"C\":403:411 this.f() */ 0x20
swap1
returndatasize returndatasize
dup3
gt
tag_41
jumpi
tag_42:
/* \"C\":79:428 contract C... */ /* \"C\":79:428 contract C... */
0x1f 0x1f
dup3
add add
not(0x1f) not(0x1f)
and and
dup3 dup4
add add
swap1 swap1
0xffffffffffffffff 0xffffffffffffffff
dup3 dup3
gt gt
dup4 dup5
dup4 dup4
lt lt
or or
tag_41 tag_43
jumpi jumpi
pop pop
tag_40
swap3 swap3
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
tag_43 tag_45
/* \"C\":392:422 stateVar + this.f() + immutVar */ /* \"C\":392:422 stateVar + this.f() + immutVar */
tag_39 tag_39
/* \"C\":79:428 contract C... */ /* \"C\":79:428 contract C... */
@ -301,34 +306,41 @@ sub_0: assembly {
tag_38 tag_38
/* \"C\":79:428 contract C... */ /* \"C\":79:428 contract C... */
swap4 swap4
tag_40
swap7
0x40 0x40
mstore mstore
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
returndatasize
dup2 dup2
add add
swap1 swap1
tag_6 tag_6
jump\t// in jump\t// in
tag_43: tag_45:
swap3 swap3
pop pop
swap3 swap3
jump(tag_37) jump(tag_37)
/* \"C\":79:428 contract C... */ /* \"C\":79:428 contract C... */
tag_41: tag_43:
shl(0xe0, 0x4e487b71) shl(0xe0, 0x4e487b71)
dup2 dup2
mstore mstore
mstore(0x04, 0x41) mstore(0x04, 0x41)
0x24 0x24
swap4 swap5
pop
swap3
pop pop
swap2
pop pop
pop pop
revert revert
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
tag_41:
returndatasize
swap2
pop
jump(tag_42)
tag_34: tag_34:
/* \"C\":79:428 contract C... */ /* \"C\":79:428 contract C... */
swap3 swap3
@ -345,10 +357,10 @@ sub_0: assembly {
swap1 swap1
revert revert
tag_32: tag_32:
tag_44 tag_46
tag_4 tag_4
jump\t// in jump\t// in
tag_44: tag_46:
jump(tag_33) jump(tag_33)
/* \"C\":117:119 41 */ /* \"C\":117:119 41 */
tag_4: tag_4:
@ -373,9 +385,9 @@ sub_0: assembly {
dup5 dup5
sgt sgt
and and
tag_45 tag_47
jumpi jumpi
tag_46: tag_48:
shl(0xff, 0x01) shl(0xff, 0x01)
dup3 dup3
swap1 swap1
@ -383,25 +395,25 @@ sub_0: assembly {
dup4 dup4
slt slt
and and
tag_47 tag_49
jumpi jumpi
add add
swap1 swap1
jump\t// out jump\t// out
tag_47: tag_49:
tag_49 tag_51
tag_4 tag_4
jump\t// in jump\t// in
tag_49: tag_51:
add add
swap1 swap1
jump\t// out jump\t// out
tag_45: tag_47:
tag_50 tag_52
tag_4 tag_4
jump\t// in jump\t// in
tag_50: tag_52:
jump(tag_46) jump(tag_48)
/* \"C\":79:428 contract C... */ /* \"C\":79:428 contract C... */
tag_6: tag_6:
swap1 swap1
@ -410,12 +422,12 @@ sub_0: assembly {
swap2 swap2
sub sub
slt slt
tag_51 tag_53
jumpi jumpi
mload mload
swap1 swap1
jump\t// out jump\t// out
tag_51: tag_53:
pop pop
pop pop
0x00 0x00
@ -732,34 +744,39 @@ sub_0: assembly {
return return
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
tag_36: tag_36:
/* \"D\":91:166 contract D is C(3)... */
swap1 swap1
swap2 swap2
pop pop
/* \"C\":403:411 this.f() */ 0x20
swap1
returndatasize returndatasize
dup3
gt
tag_41
jumpi
tag_42:
/* \"D\":91:166 contract D is C(3)... */ /* \"D\":91:166 contract D is C(3)... */
0x1f 0x1f
dup3
add add
not(0x1f) not(0x1f)
and and
dup3 dup4
add add
swap1 swap1
0xffffffffffffffff 0xffffffffffffffff
dup3 dup3
gt gt
dup4 dup5
dup4 dup4
lt lt
or or
tag_41 tag_43
jumpi jumpi
pop pop
tag_40
swap3 swap3
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
tag_43 tag_45
/* \"C\":392:422 stateVar + this.f() + immutVar */ /* \"C\":392:422 stateVar + this.f() + immutVar */
tag_39 tag_39
/* \"D\":91:166 contract D is C(3)... */ /* \"D\":91:166 contract D is C(3)... */
@ -768,34 +785,41 @@ sub_0: assembly {
tag_38 tag_38
/* \"D\":91:166 contract D is C(3)... */ /* \"D\":91:166 contract D is C(3)... */
swap4 swap4
tag_40
swap7
0x40 0x40
mstore mstore
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
returndatasize
dup2 dup2
add add
swap1 swap1
tag_6 tag_6
jump\t// in jump\t// in
tag_43: tag_45:
swap3 swap3
pop pop
swap3 swap3
jump(tag_37) jump(tag_37)
/* \"D\":91:166 contract D is C(3)... */ /* \"D\":91:166 contract D is C(3)... */
tag_41: tag_43:
shl(0xe0, 0x4e487b71) shl(0xe0, 0x4e487b71)
dup2 dup2
mstore mstore
mstore(0x04, 0x41) mstore(0x04, 0x41)
0x24 0x24
swap4 swap5
pop
swap3
pop pop
swap2
pop pop
pop pop
revert revert
/* \"C\":403:411 this.f() */ /* \"C\":403:411 this.f() */
tag_41:
returndatasize
swap2
pop
jump(tag_42)
tag_34: tag_34:
/* \"D\":91:166 contract D is C(3)... */ /* \"D\":91:166 contract D is C(3)... */
swap3 swap3
@ -812,10 +836,10 @@ sub_0: assembly {
swap1 swap1
revert revert
tag_32: tag_32:
tag_44 tag_46
tag_4 tag_4
jump\t// in jump\t// in
tag_44: tag_46:
jump(tag_33) jump(tag_33)
/* \"C\":117:119 41 */ /* \"C\":117:119 41 */
tag_4: tag_4:
@ -840,9 +864,9 @@ sub_0: assembly {
dup5 dup5
sgt sgt
and and
tag_45 tag_47
jumpi jumpi
tag_46: tag_48:
shl(0xff, 0x01) shl(0xff, 0x01)
dup3 dup3
swap1 swap1
@ -850,25 +874,25 @@ sub_0: assembly {
dup4 dup4
slt slt
and and
tag_47 tag_49
jumpi jumpi
add add
swap1 swap1
jump\t// out jump\t// out
tag_47: tag_49:
tag_49 tag_51
tag_4 tag_4
jump\t// in jump\t// in
tag_49: tag_51:
add add
swap1 swap1
jump\t// out jump\t// out
tag_45: tag_47:
tag_50 tag_52
tag_4 tag_4
jump\t// in jump\t// in
tag_50: tag_52:
jump(tag_46) jump(tag_48)
/* \"D\":91:166 contract D is C(3)... */ /* \"D\":91:166 contract D is C(3)... */
tag_6: tag_6:
swap1 swap1
@ -877,12 +901,12 @@ sub_0: assembly {
swap2 swap2
sub sub
slt slt
tag_51 tag_53
jumpi jumpi
mload mload
swap1 swap1
jump\t// out jump\t// out
tag_51: tag_53:
pop pop
pop pop
0x00 0x00

View File

@ -563,18 +563,24 @@ object \"C_54\" {
let expr_47 let expr_47
if _12 { if _12 {
let _13 := 32
if gt(_13, returndatasize()) {
_13 := returndatasize()
}
// update freeMemoryPointer according to dynamic return size // update freeMemoryPointer according to dynamic return size
finalize_allocation(_10, returndatasize()) finalize_allocation(_10, _13)
// decode return parameters from external try-call into retVars // decode return parameters from external try-call into retVars
expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, returndatasize())) expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, _13))
} }
/// @src 0:399:418 \"stateVar + this.f()\" /// @src 0:399:418 \"stateVar + this.f()\"
let expr_48 := checked_add_t_int256(expr_44, expr_47) let expr_48 := checked_add_t_int256(expr_44, expr_47)
/// @src 0:421:429 \"immutVar\" /// @src 0:421:429 \"immutVar\"
let _13 := loadimmutable(\"8\") let _14 := loadimmutable(\"8\")
let expr_49 := _13 let expr_49 := _14
/// @src 0:399:429 \"stateVar + this.f() + immutVar\" /// @src 0:399:429 \"stateVar + this.f() + immutVar\"
let expr_50 := checked_add_t_int256(expr_48, expr_49) let expr_50 := checked_add_t_int256(expr_48, expr_49)
@ -718,8 +724,10 @@ object \"C_54\" {
/// @src 0:410:418 \"this.f()\" /// @src 0:410:418 \"this.f()\"
if _4 if _4
{ {
let _5 := 32
if gt(_5, returndatasize()) { _5 := returndatasize() }
/// @src 0:79:435 \"contract C...\" /// @src 0:79:435 \"contract C...\"
let newFreePtr := add(_3, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 0:79:435 \"contract C...\" */ 31), not(31))) let newFreePtr := add(_3, and(add(_5, 31), not(31)))
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3)) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3))
{ {
mstore(_1, shl(224, 0x4e487b71)) mstore(_1, shl(224, 0x4e487b71))
@ -728,7 +736,7 @@ object \"C_54\" {
} }
mstore(64, newFreePtr) mstore(64, newFreePtr)
/// @src 0:410:418 \"this.f()\" /// @src 0:410:418 \"this.f()\"
expr := abi_decode_int256_fromMemory(_3, add(_3, returndatasize())) expr := abi_decode_int256_fromMemory(_3, add(_3, _5))
} }
/// @src 0:399:418 \"stateVar + this.f()\" /// @src 0:399:418 \"stateVar + this.f()\"
let expr_1 := checked_add_int256(ret, expr) let expr_1 := checked_add_int256(ret, expr)
@ -1402,18 +1410,24 @@ object \"D_72\" {
let expr_47 let expr_47
if _12 { if _12 {
let _13 := 32
if gt(_13, returndatasize()) {
_13 := returndatasize()
}
// update freeMemoryPointer according to dynamic return size // update freeMemoryPointer according to dynamic return size
finalize_allocation(_10, returndatasize()) finalize_allocation(_10, _13)
// decode return parameters from external try-call into retVars // decode return parameters from external try-call into retVars
expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, returndatasize())) expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, _13))
} }
/// @src 0:399:418 \"stateVar + this.f()\" /// @src 0:399:418 \"stateVar + this.f()\"
let expr_48 := checked_add_t_int256(expr_44, expr_47) let expr_48 := checked_add_t_int256(expr_44, expr_47)
/// @src 0:421:429 \"immutVar\" /// @src 0:421:429 \"immutVar\"
let _13 := loadimmutable(\"8\") let _14 := loadimmutable(\"8\")
let expr_49 := _13 let expr_49 := _14
/// @src 0:399:429 \"stateVar + this.f() + immutVar\" /// @src 0:399:429 \"stateVar + this.f() + immutVar\"
let expr_50 := checked_add_t_int256(expr_48, expr_49) let expr_50 := checked_add_t_int256(expr_48, expr_49)
@ -1565,8 +1579,10 @@ object \"D_72\" {
/// @src 0:410:418 \"this.f()\" /// @src 0:410:418 \"this.f()\"
if _4 if _4
{ {
let _5 := 32
if gt(_5, returndatasize()) { _5 := returndatasize() }
/// @src 1:91:166 \"contract D is C(3)...\" /// @src 1:91:166 \"contract D is C(3)...\"
let newFreePtr := add(_3, and(add(/** @src 0:410:418 \"this.f()\" */ returndatasize(), /** @src 1:91:166 \"contract D is C(3)...\" */ 31), not(31))) let newFreePtr := add(_3, and(add(_5, 31), not(31)))
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3)) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _3))
{ {
mstore(_1, shl(224, 0x4e487b71)) mstore(_1, shl(224, 0x4e487b71))
@ -1575,7 +1591,7 @@ object \"D_72\" {
} }
mstore(64, newFreePtr) mstore(64, newFreePtr)
/// @src 0:410:418 \"this.f()\" /// @src 0:410:418 \"this.f()\"
expr := abi_decode_int256_fromMemory(_3, add(_3, returndatasize())) expr := abi_decode_int256_fromMemory(_3, add(_3, _5))
} }
/// @src 0:399:418 \"stateVar + this.f()\" /// @src 0:399:418 \"stateVar + this.f()\"
let expr_1 := checked_add_int256(ret, expr) let expr_1 := checked_add_int256(ret, expr)

View File

@ -60,10 +60,10 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test_bytes() -> // test_bytes() ->
// gas irOptimized: 371847 // gas irOptimized: 371919
// gas legacy: 418955 // gas legacy: 418955
// gas legacyOptimized: 326783 // gas legacyOptimized: 326783
// test_uint256() -> // test_uint256() ->
// gas irOptimized: 522929 // gas irOptimized: 523001
// gas legacy: 586784 // gas legacy: 586784
// gas legacyOptimized: 451529 // gas legacyOptimized: 451529

View File

@ -26,6 +26,6 @@ contract C {
// ---- // ----
// library: L // library: L
// f() -> 8, 7, 1, 2, 7, 12 // f() -> 8, 7, 1, 2, 7, 12
// gas irOptimized: 167672 // gas irOptimized: 167696
// gas legacy: 169347 // gas legacy: 169347
// gas legacyOptimized: 167269 // gas legacyOptimized: 167269

View File

@ -61,10 +61,10 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test_bytes() -> // test_bytes() ->
// gas irOptimized: 371847 // gas irOptimized: 371919
// gas legacy: 418955 // gas legacy: 418955
// gas legacyOptimized: 326783 // gas legacyOptimized: 326783
// test_uint256() -> // test_uint256() ->
// gas irOptimized: 522929 // gas irOptimized: 523001
// gas legacy: 586784 // gas legacy: 586784
// gas legacyOptimized: 451529 // gas legacyOptimized: 451529

View File

@ -32,6 +32,6 @@ contract C is B {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> 77 // test() -> 77
// gas irOptimized: 119895 // gas irOptimized: 119919
// gas legacy: 155093 // gas legacy: 155093
// gas legacyOptimized: 111550 // gas legacyOptimized: 111550

View File

@ -21,6 +21,6 @@ contract C {
// f(uint256[][1]): 32, 32, 0 -> true // f(uint256[][1]): 32, 32, 0 -> true
// f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 1, 42 -> true
// f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true
// gas irOptimized: 171838 // gas irOptimized: 171842
// gas legacy: 141644 // gas legacy: 141644
// gas legacyOptimized: 121532 // gas legacyOptimized: 121532

View File

@ -21,6 +21,6 @@ contract B {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004 // f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004
// gas irOptimized: 130097 // gas irOptimized: 130152
// gas legacy: 234943 // gas legacy: 234943
// gas legacyOptimized: 132863 // gas legacyOptimized: 132863

View File

@ -45,6 +45,6 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test() -> 5, 6, 7 // test() -> 5, 6, 7
// gas irOptimized: 290567 // gas irOptimized: 298983
// gas legacy: 452172 // gas legacy: 452172
// gas legacyOptimized: 285017 // gas legacyOptimized: 285017

View File

@ -26,6 +26,6 @@ contract Main {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1
// gas irOptimized: 113552 // gas irOptimized: 113598
// gas legacy: 126596 // gas legacy: 126596
// gas legacyOptimized: 113823 // gas legacyOptimized: 113823

View File

@ -26,6 +26,6 @@ contract Creator {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8
// gas irOptimized: 443921 // gas irOptimized: 443960
// gas legacy: 590683 // gas legacy: 590683
// gas legacyOptimized: 448326 // gas legacyOptimized: 448326

View File

@ -26,6 +26,6 @@ contract Creator {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
// gas irOptimized: 300765 // gas irOptimized: 300804
// gas legacy: 428917 // gas legacy: 428917
// gas legacyOptimized: 298128 // gas legacyOptimized: 298128

View File

@ -17,7 +17,7 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor() -> // constructor() ->
// gas irOptimized: 177344 // gas irOptimized: 173672
// gas legacy: 250376 // gas legacy: 250376
// gas legacyOptimized: 174522 // gas legacyOptimized: 174522
// deposit(bytes32), 18 wei: 0x1234 -> // deposit(bytes32), 18 wei: 0x1234 ->

View File

@ -17,7 +17,7 @@ contract D {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(): 2 -> // constructor(): 2 ->
// gas irOptimized: 200295 // gas irOptimized: 203967
// gas legacy: 245842 // gas legacy: 245842
// gas legacyOptimized: 195676 // gas legacyOptimized: 195676
// f() -> 2 // f() -> 2

View File

@ -18,7 +18,7 @@ contract D {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(): 2 -> // constructor(): 2 ->
// gas irOptimized: 200458 // gas irOptimized: 204130
// gas legacy: 246202 // gas legacy: 246202
// gas legacyOptimized: 195914 // gas legacyOptimized: 195914
// f() -> 2 // f() -> 2

View File

@ -25,7 +25,7 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 1 ether -> // constructor(), 1 ether ->
// gas irOptimized: 308423 // gas irOptimized: 315341
// gas legacy: 465314 // gas legacy: 465314
// gas legacyOptimized: 304481 // gas legacyOptimized: 304481
// f(uint256): 0 -> FAILURE // f(uint256): 0 -> FAILURE

View File

@ -27,7 +27,7 @@ contract C {
// revertStrings: debug // revertStrings: debug
// ---- // ----
// constructor(), 1 ether -> // constructor(), 1 ether ->
// gas irOptimized: 445767 // gas irOptimized: 452673
// gas legacy: 834272 // gas legacy: 834272
// gas legacyOptimized: 510004 // gas legacyOptimized: 510004
// f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code"

View File

@ -18,7 +18,7 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 20 wei // constructor(), 20 wei
// gas irOptimized: 213663 // gas irOptimized: 219285
// gas legacy: 294569 // gas legacy: 294569
// gas legacyOptimized: 174699 // gas legacyOptimized: 174699
// f(uint256): 20 -> 1370859564726510389319704988634906228201275401179 // f(uint256): 20 -> 1370859564726510389319704988634906228201275401179
@ -26,7 +26,7 @@ contract C {
// f(uint256): 20 -> FAILURE // f(uint256): 20 -> FAILURE
// x() -> 1 // x() -> 1
// stack(uint256): 1023 -> FAILURE // stack(uint256): 1023 -> FAILURE
// gas irOptimized: 304303 // gas irOptimized: 314884
// gas legacy: 483942 // gas legacy: 483942
// gas legacyOptimized: 298807 // gas legacyOptimized: 298807
// x() -> 1 // x() -> 1

View File

@ -41,7 +41,7 @@ contract test {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 20 wei -> // constructor(), 20 wei ->
// gas irOptimized: 274154 // gas irOptimized: 283040
// gas legacy: 402654 // gas legacy: 402654
// gas legacyOptimized: 274470 // gas legacyOptimized: 274470
// sendAmount(uint256): 5 -> 5 // sendAmount(uint256): 5 -> 5

View File

@ -40,7 +40,7 @@ contract test {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 20 wei -> // constructor(), 20 wei ->
// gas irOptimized: 274154 // gas irOptimized: 283040
// gas legacy: 402654 // gas legacy: 402654
// gas legacyOptimized: 274470 // gas legacyOptimized: 274470
// sendAmount(uint256): 5 -> 5 // sendAmount(uint256): 5 -> 5

View File

@ -0,0 +1,31 @@
interface ShortReturn {
function f() external pure returns (bytes32);
}
contract LongReturn {
function f() external pure returns (uint[20] memory) {}
}
contract Test {
function test() public returns (uint) {
LongReturn longReturn = new LongReturn();
uint freeMemoryBefore;
assembly {
freeMemoryBefore := mload(0x40)
}
ShortReturn(address(longReturn)).f();
uint freeMemoryAfter;
assembly {
freeMemoryAfter := mload(0x40)
}
return freeMemoryAfter - freeMemoryBefore;
}
}
// ====
// compileViaYul: true
// ----
// test() -> 0x20
// gas legacy: 131966

View File

@ -0,0 +1,32 @@
interface LongReturn {
function f() external pure returns (uint[20] memory);
}
contract ShortReturn {
function f() external pure returns (bytes32) {}
}
contract Test {
function test() public returns (uint) {
ShortReturn shortReturn = new ShortReturn();
uint freeMemoryBefore;
assembly {
freeMemoryBefore := mload(0x40)
}
LongReturn(address(shortReturn)).f();
uint freeMemoryAfter;
assembly {
freeMemoryAfter := mload(0x40)
}
return freeMemoryAfter - freeMemoryBefore;
}
}
// ====
// EVMVersion: <=homestead
// compileViaYul: true
// ----
// test() -> 0x0500
// gas legacy: 131966

View File

@ -0,0 +1,34 @@
interface LongReturn {
function f() external pure returns (uint[20] memory);
}
contract ShortReturn {
function f() external pure returns (bytes32) {}
}
contract Test {
function test() public returns (uint) {
ShortReturn shortReturn = new ShortReturn();
uint freeMemoryBefore;
assembly {
freeMemoryBefore := mload(0x40)
}
// This reverts. The external call succeeds but ABI decoding fails due to the returned
// `bytes32` being much shorter than the expected `uint[20]`.
LongReturn(address(shortReturn)).f();
uint freeMemoryAfter;
assembly {
freeMemoryAfter := mload(0x40)
}
return freeMemoryAfter - freeMemoryBefore;
}
}
// ====
// EVMVersion: >homestead
// compileViaYul: true
// ----
// test() -> FAILURE
// gas legacy: 131966

View File

@ -29,7 +29,7 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f() -> 3, 7, 5 // f() -> 3, 7, 5
// gas irOptimized: 127302 // gas irOptimized: 127347
// gas legacy: 151334 // gas legacy: 151334
// gas legacyOptimized: 125166 // gas legacyOptimized: 125166
// x() -> 7 // x() -> 7

View File

@ -25,6 +25,6 @@ contract B {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// g() -> 42 // g() -> 42
// gas irOptimized: 111770 // gas irOptimized: 111794
// gas legacy: 185053 // gas legacy: 185053
// gas legacyOptimized: 114598 // gas legacyOptimized: 114598

View File

@ -42,7 +42,7 @@ contract Main {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 22 wei -> // constructor(), 22 wei ->
// gas irOptimized: 276469 // gas irOptimized: 284287
// gas legacy: 402045 // gas legacy: 402045
// gas legacyOptimized: 266772 // gas legacyOptimized: 266772
// getFlag() -> true // getFlag() -> true

View File

@ -18,7 +18,7 @@ contract ClientReceipt {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 2000 wei -> // constructor(), 2000 wei ->
// gas irOptimized: 184076 // gas irOptimized: 188162
// gas legacy: 235195 // gas legacy: 235195
// gas legacyOptimized: 176766 // gas legacyOptimized: 176766
// balance -> 1500 // balance -> 1500

View File

@ -25,6 +25,6 @@ contract Test {
// ---- // ----
// library: Lib // library: Lib
// f() -> 4, 0x11 // f() -> 4, 0x11
// gas irOptimized: 115822 // gas irOptimized: 115874
// gas legacy: 135952 // gas legacy: 135952
// gas legacyOptimized: 119643 // gas legacyOptimized: 119643

View File

@ -22,6 +22,6 @@ contract Test {
// ---- // ----
// library: Lib // library: Lib
// f() -> 1, 0, 0x2a, 0x17, 0, 0x63 // f() -> 1, 0, 0x2a, 0x17, 0, 0x63
// gas irOptimized: 119757 // gas irOptimized: 119561
// gas legacy: 124793 // gas legacy: 124793
// gas legacyOptimized: 119694 // gas legacyOptimized: 119694

View File

@ -20,6 +20,6 @@ contract Test {
// ---- // ----
// library: Lib // library: Lib
// f() -> 1, 0, 0x2a, 0x17, 0, 0x63 // f() -> 1, 0, 0x2a, 0x17, 0, 0x63
// gas irOptimized: 120471 // gas irOptimized: 120572
// gas legacy: 125245 // gas legacy: 125245
// gas legacyOptimized: 120153 // gas legacyOptimized: 120153

View File

@ -23,5 +23,5 @@ contract Test {
// ---- // ----
// library: Lib // library: Lib
// f() -> 7, 8 // f() -> 7, 8
// gas irOptimized: 101869 // gas irOptimized: 101820
// gas legacy: 101504 // gas legacy: 101504

View File

@ -22,6 +22,6 @@ contract A {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f(), 10 ether -> 3007, 3008, 3009 // f(), 10 ether -> 3007, 3008, 3009
// gas irOptimized: 272338 // gas irOptimized: 272413
// gas legacy: 422501 // gas legacy: 422501
// gas legacyOptimized: 287472 // gas legacyOptimized: 287472

View File

@ -51,7 +51,7 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// test_f() -> true // test_f() -> true
// gas irOptimized: 122413 // gas irOptimized: 122364
// gas legacy: 126168 // gas legacy: 126168
// gas legacyOptimized: 123199 // gas legacyOptimized: 123199
// test_g() -> true // test_g() -> true

View File

@ -19,7 +19,7 @@ contract D {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 27 wei -> // constructor(), 27 wei ->
// gas irOptimized: 175261 // gas irOptimized: 178933
// gas legacy: 222977 // gas legacy: 222977
// gas legacyOptimized: 169779 // gas legacyOptimized: 169779
// f() -> 27 // f() -> 27

View File

@ -22,6 +22,6 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// g() -> 2, 6 // g() -> 2, 6
// gas irOptimized: 178822 // gas irOptimized: 178812
// gas legacy: 180762 // gas legacy: 180762
// gas legacyOptimized: 179481 // gas legacyOptimized: 179481

View File

@ -22,7 +22,7 @@ contract test {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 20 wei -> // constructor(), 20 wei ->
// gas irOptimized: 185891 // gas irOptimized: 192113
// gas legacy: 265006 // gas legacy: 265006
// gas legacyOptimized: 182842 // gas legacyOptimized: 182842
// sendAmount(uint256): 5 -> 8 // sendAmount(uint256): 5 -> 8

View File

@ -21,7 +21,7 @@ contract test {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// constructor(), 20 wei -> // constructor(), 20 wei ->
// gas irOptimized: 187835 // gas irOptimized: 194261
// gas legacy: 266728 // gas legacy: 266728
// gas legacyOptimized: 184762 // gas legacyOptimized: 184762
// sendAmount(uint256): 5 -> 8 // sendAmount(uint256): 5 -> 8

View File

@ -23,6 +23,6 @@ contract C {
// compileViaYul: also // compileViaYul: also
// ---- // ----
// f() -> // f() ->
// gas irOptimized: 113096 // gas irOptimized: 112998
// gas legacy: 112937 // gas legacy: 112937
// gas legacyOptimized: 112608 // gas legacyOptimized: 112608