mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9823 from ethereum/develop
Merge develop into breaking.
This commit is contained in:
@@ -124,6 +124,7 @@ function test_solc_behaviour()
|
||||
sed -i.bak -e '/^Warning (3805): This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
|
||||
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1AUXDATA REMOVED/' "$stdout_path"
|
||||
sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path"
|
||||
sed -i.bak -e 's/\(Unimplemented feature error: .* in \).*$/\1FILENAME REMOVED/' "$stderr_path"
|
||||
sed -i.bak -e 's/"version": "[^"]*"/"version": "VERSION REMOVED"/' "$stdout_path"
|
||||
# Remove trailing empty lines. Needs a line break to make OSX sed happy.
|
||||
sed -i.bak -e '1{/^$/d
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
--ir --error-codes
|
||||
@@ -0,0 +1,5 @@
|
||||
Error (1834): Unimplemented feature error: setToZero for type t_struct$_S_$4_storage not yet implemented! in FILENAME REMOVED
|
||||
--> yul_unimplemented/input.sol:9:9:
|
||||
|
|
||||
9 | delete str;
|
||||
| ^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0;
|
||||
contract test {
|
||||
struct S {
|
||||
uint x;
|
||||
}
|
||||
S str;
|
||||
constructor() {
|
||||
delete str;
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,12 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
||||
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
||||
if (!m_compiler.compile())
|
||||
{
|
||||
// The testing framework expects an exception for
|
||||
// "unimplemented" yul IR generation.
|
||||
if (m_compileViaYul)
|
||||
for (auto const& error: m_compiler.errors())
|
||||
if (error->type() == langutil::Error::Type::CodeGenerationError)
|
||||
BOOST_THROW_EXCEPTION(*error);
|
||||
langutil::SourceReferenceFormatter formatter(std::cerr);
|
||||
|
||||
for (auto const& error: m_compiler.errors())
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
contract C {
|
||||
function f(int a, int b) public pure returns (int) {
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(int256,int256): 7, 5 -> 2
|
||||
// f(int256,int256): 7, -5 -> 2
|
||||
// f(int256,int256): -7, 5 -> -2
|
||||
// f(int256,int256): -7, 5 -> -2
|
||||
// f(int256,int256): -5, -5 -> 0
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct S {
|
||||
bool[] b;
|
||||
}
|
||||
|
||||
function f() public returns (uint256, bool[][2] memory, S[2] memory, uint256) {
|
||||
return (
|
||||
5,
|
||||
[new bool[](1), new bool[](2)],
|
||||
[S(new bool[](2)), S(new bool[](5))],
|
||||
6
|
||||
);
|
||||
}
|
||||
|
||||
function g() public returns (uint256, uint256) {
|
||||
(uint256 a, , , uint256 b) = this.f();
|
||||
return (a, b);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// g() -> 5, 6
|
||||
@@ -0,0 +1,28 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
event Nudge();
|
||||
event SomeArgs(uint, uint);
|
||||
event Caller(address, uint);
|
||||
function f() payable external {
|
||||
emit Nudge();
|
||||
emit SomeArgs(134, 567);
|
||||
emit Caller(msg.sender, msg.value);
|
||||
}
|
||||
function g_data() pure internal returns (uint) {
|
||||
assert(true);
|
||||
}
|
||||
function g() external {
|
||||
emit SomeArgs(g_data(), g_data());
|
||||
}
|
||||
bool x = true;
|
||||
function h_data() view internal returns (uint) {
|
||||
assert(x);
|
||||
}
|
||||
function h() external {
|
||||
x = false;
|
||||
emit SomeArgs(h_data(), h_data());
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning 6328: (440-449): Assertion violation happens here.
|
||||
@@ -0,0 +1,39 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
function f() external {
|
||||
bytes32 t1 = bytes32(uint256(0x1234));
|
||||
log0(t1);
|
||||
log1(t1, t1);
|
||||
log2(t1, t1, t1);
|
||||
log3(t1, t1, t1, t1);
|
||||
log4(t1, t1, t1, t1, t1);
|
||||
}
|
||||
function g_data() pure internal returns (bytes32) {
|
||||
assert(true);
|
||||
return bytes32(uint256(0x5678));
|
||||
}
|
||||
function g() external {
|
||||
// To test that the function call is actually visited.
|
||||
log0(g_data());
|
||||
log1(g_data(), g_data());
|
||||
log2(g_data(), g_data(), g_data());
|
||||
log3(g_data(), g_data(), g_data(), g_data());
|
||||
log4(g_data(), g_data(), g_data(), g_data(), g_data());
|
||||
}
|
||||
bool x = true;
|
||||
function h_data() view internal returns (bytes32) {
|
||||
assert(x);
|
||||
}
|
||||
function h() external {
|
||||
// To test that the function call is actually visited.
|
||||
x = false;
|
||||
log0(h_data());
|
||||
log1(h_data(), h_data());
|
||||
log2(h_data(), h_data(), h_data());
|
||||
log3(h_data(), h_data(), h_data(), h_data());
|
||||
log4(h_data(), h_data(), h_data(), h_data(), h_data());
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning 6328: (668-677): Assertion violation happens here.
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
function f() public pure returns(string[5] calldata) {
|
||||
return ["h", "e", "l", "l", "o"];
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 6359: (122-147): Return argument type string memory[5] memory is not implicitly convertible to expected type (type of first return variable) string calldata[5] calldata.
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
contract C {
|
||||
function f1() public pure returns(string calldata) {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
function f2() public pure returns(string calldata) {
|
||||
return unicode"hello";
|
||||
}
|
||||
|
||||
function f3() public pure returns(bytes calldata) {
|
||||
return hex"68656c6c6f";
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 6359: (85-92): Return argument type literal_string "hello" is not implicitly convertible to expected type (type of first return variable) string calldata.
|
||||
// TypeError 6359: (173-187): Return argument type literal_string "hello" is not implicitly convertible to expected type (type of first return variable) string calldata.
|
||||
// TypeError 6359: (267-282): Return argument type literal_string "hello" is not implicitly convertible to expected type (type of first return variable) bytes calldata.
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
contract C {
|
||||
function g(string calldata _s) public {}
|
||||
function h(bytes calldata _b) public {}
|
||||
|
||||
function f() public {
|
||||
g("hello");
|
||||
g(unicode"hello");
|
||||
h(hex"68656c6c6f");
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9553: (139-146): Invalid type for argument in function call. Invalid implicit conversion from literal_string "hello" to string calldata requested.
|
||||
// TypeError 9553: (159-173): Invalid type for argument in function call. Invalid implicit conversion from literal_string "hello" to string calldata requested.
|
||||
// TypeError 9553: (186-201): Invalid type for argument in function call. Invalid implicit conversion from literal_string "hello" to bytes calldata requested.
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <libyul/optimiser/UnusedPruner.h>
|
||||
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||
#include <libyul/optimiser/OptimiserStep.h>
|
||||
#include <libyul/optimiser/ReasoningBasedSimplifier.h>
|
||||
#include <libyul/optimiser/SSAReverser.h>
|
||||
#include <libyul/optimiser/SSATransform.h>
|
||||
#include <libyul/optimiser/Semantics.h>
|
||||
@@ -102,6 +103,9 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename):
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Filename path has to contain a directory: \"" + _filename + "\"."));
|
||||
m_optimizerStep = std::prev(std::prev(path.end()))->string();
|
||||
|
||||
if (m_optimizerStep == "reasoningBasedSimplifier" && solidity::test::CommonOptions::get().disableSMT)
|
||||
m_shouldRun = false;
|
||||
|
||||
m_source = m_reader.source();
|
||||
|
||||
auto dialectName = m_reader.stringSetting("dialect", "evm");
|
||||
@@ -320,6 +324,11 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
|
||||
LiteralRematerialiser::run(*m_context, *m_object->code);
|
||||
StructuralSimplifier::run(*m_context, *m_object->code);
|
||||
}
|
||||
else if (m_optimizerStep == "reasoningBasedSimplifier")
|
||||
{
|
||||
disambiguate();
|
||||
ReasoningBasedSimplifier::run(*m_context, *m_object->code);
|
||||
}
|
||||
else if (m_optimizerStep == "equivalentFunctionCombiner")
|
||||
{
|
||||
disambiguate();
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
let x := calldataload(0)
|
||||
let y := calldataload(32)
|
||||
let z := calldataload(64)
|
||||
let result := addmod(x, y, z)
|
||||
|
||||
// should be zero
|
||||
if gt(result, z) { sstore(0, 1) }
|
||||
|
||||
// addmod is equal to mod of sum for small numbers
|
||||
if and(and(lt(x, 1000), lt(y, 1000)), lt(z, 1000)) {
|
||||
if eq(result, mod(add(x, y), z)) { sstore(0, 9) }
|
||||
}
|
||||
|
||||
// but not in general
|
||||
if and(and(gt(x, sub(0, 5)), gt(y, sub(0, 2))), eq(z, 3)) {
|
||||
if eq(result, mod(add(x, y), z)) { sstore(0, 5) }
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := calldataload(0)
|
||||
// let y := calldataload(32)
|
||||
// let z := calldataload(64)
|
||||
// let result := addmod(x, y, z)
|
||||
// if 0 { }
|
||||
// if and(and(lt(x, 1000), lt(y, 1000)), lt(z, 1000)) { if 1 { sstore(0, 9) } }
|
||||
// if and(and(gt(x, sub(0, 5)), gt(y, sub(0, 2))), eq(z, 3)) { if 0 { } }
|
||||
// }
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
let x := 7
|
||||
let y := 8
|
||||
if eq(add(x, y), 15) { }
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := 7
|
||||
// let y := 8
|
||||
// if 1 { }
|
||||
// }
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
function f() -> z
|
||||
{
|
||||
z := 15
|
||||
}
|
||||
let x := 7
|
||||
let y := 8
|
||||
if eq(add(x, y), f()) { }
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// function f() -> z
|
||||
// { z := 15 }
|
||||
// let x := 7
|
||||
// let y := 8
|
||||
// if eq(add(x, y), f()) { }
|
||||
// }
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
function f() -> z
|
||||
{
|
||||
sstore(1, 15)
|
||||
z := 15
|
||||
}
|
||||
let x := 7
|
||||
let y := 8
|
||||
if eq(add(x, y), f()) { }
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// function f() -> z
|
||||
// {
|
||||
// sstore(1, 15)
|
||||
// z := 15
|
||||
// }
|
||||
// let x := 7
|
||||
// let y := 8
|
||||
// if eq(add(x, y), f()) { }
|
||||
// }
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
let vloc_x := calldataload(0)
|
||||
let vloc_y := calldataload(1)
|
||||
if lt(vloc_x, shl(100, 1)) {
|
||||
if lt(vloc_y, shl(100, 1)) {
|
||||
if iszero(and(iszero(iszero(vloc_x)), gt(vloc_y, div(not(0), vloc_x)))) {
|
||||
let vloc := mul(vloc_x, vloc_y)
|
||||
sstore(0, vloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let vloc_x := calldataload(0)
|
||||
// let vloc_y := calldataload(1)
|
||||
// if lt(vloc_x, shl(100, 1))
|
||||
// {
|
||||
// if lt(vloc_y, shl(100, 1))
|
||||
// {
|
||||
// if 1
|
||||
// {
|
||||
// let vloc := mul(vloc_x, vloc_y)
|
||||
// sstore(0, vloc)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
let x := calldataload(0)
|
||||
let y := calldataload(32)
|
||||
let z := calldataload(64)
|
||||
let result := mulmod(x, y, z)
|
||||
|
||||
// should be zero
|
||||
if gt(result, z) { sstore(0, 1) }
|
||||
|
||||
// mulmod is equal to mod of product for small numbers
|
||||
if and(and(lt(x, 1000), lt(y, 1000)), lt(z, 1000)) {
|
||||
if eq(result, mod(mul(x, y), z)) { sstore(0, 9) }
|
||||
}
|
||||
|
||||
// but not in general
|
||||
if and(and(gt(x, sub(0, 5)), eq(y, 2)), eq(z, 3)) {
|
||||
if eq(result, mod(mul(x, y), z)) { sstore(0, 5) }
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := calldataload(0)
|
||||
// let y := calldataload(32)
|
||||
// let z := calldataload(64)
|
||||
// let result := mulmod(x, y, z)
|
||||
// if 0 { }
|
||||
// if and(and(lt(x, 1000), lt(y, 1000)), lt(z, 1000)) { if 1 { sstore(0, 9) } }
|
||||
// if and(and(gt(x, sub(0, 5)), eq(y, 2)), eq(z, 3)) { if 0 { } }
|
||||
// }
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
let x := sub(0, 7)
|
||||
let y := 2
|
||||
// (-7)/2 == -3 on the evm
|
||||
if iszero(add(sdiv(x, y), 3)) { }
|
||||
if iszero(add(sdiv(x, y), 4)) { }
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := sub(0, 7)
|
||||
// let y := 2
|
||||
// if 1 { }
|
||||
// if 0 { }
|
||||
// }
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
let x := calldataload(2)
|
||||
let t := lt(x, 20)
|
||||
if t {
|
||||
if lt(x, 21) { }
|
||||
if lt(x, 20) { }
|
||||
if lt(x, 19) { }
|
||||
if gt(x, 20) { }
|
||||
if iszero(gt(x, 20)) { }
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := calldataload(2)
|
||||
// let t := lt(x, 20)
|
||||
// if t
|
||||
// {
|
||||
// if 1 { }
|
||||
// if 1 { }
|
||||
// if lt(x, 19) { }
|
||||
// if 0 { }
|
||||
// if 1 { }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
let y := calldataload(0)
|
||||
let t := calldataload(32)
|
||||
|
||||
if sgt(sub(y, 1), y) {
|
||||
// y - 1 > y, i.e. y is the most negative value
|
||||
if eq(sdiv(y, sub(0, 1)), y) {
|
||||
// should be true: y / -1 == y
|
||||
sstore(0, 7)
|
||||
}
|
||||
if iszero(eq(y, t)) {
|
||||
// t is not the most negative value
|
||||
if eq(sdiv(t, sub(0, 1)), sub(0, t)) {
|
||||
// should be true: t / -1 = 0 - t
|
||||
sstore(1, 7)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let y := calldataload(0)
|
||||
// let t := calldataload(32)
|
||||
// if sgt(sub(y, 1), y)
|
||||
// {
|
||||
// if 1 { sstore(0, 7) }
|
||||
// if iszero(eq(y, t)) { if 1 { sstore(1, 7) } }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
// 7 % 5 == 2
|
||||
// 7 % -5 == 2
|
||||
// -7 % 5 == -2
|
||||
// -7 % -5 == -2
|
||||
// -5 % -5 == 0
|
||||
let x := calldataload(0)
|
||||
let y := calldataload(32)
|
||||
let result := smod(x, y)
|
||||
if eq(x, 7) {
|
||||
if eq(y, 5) {
|
||||
if eq(result, 2) { sstore(0, 7)}
|
||||
}
|
||||
if eq(y, sub(0, 5)) {
|
||||
if eq(result, 2) { sstore(0, 7)}
|
||||
}
|
||||
}
|
||||
if eq(x, sub(0, 7)) {
|
||||
if eq(y, 5) {
|
||||
if eq(result, sub(0, 2)) { sstore(0, 7)}
|
||||
}
|
||||
if eq(y, sub(0, 5)) {
|
||||
if eq(result, sub(0, 2)) { sstore(0, 7)}
|
||||
}
|
||||
}
|
||||
if eq(x, sub(0, 5)) {
|
||||
if eq(y, sub(0, 5)) {
|
||||
if eq(result, 0) { sstore(0, 7)}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := calldataload(0)
|
||||
// let y := calldataload(32)
|
||||
// let result := smod(x, y)
|
||||
// if eq(x, 7)
|
||||
// {
|
||||
// if eq(y, 5) { if 1 { sstore(0, 7) } }
|
||||
// if eq(y, sub(0, 5)) { if 1 { sstore(0, 7) } }
|
||||
// }
|
||||
// if eq(x, sub(0, 7))
|
||||
// {
|
||||
// if eq(y, 5) { if 1 { sstore(0, 7) } }
|
||||
// if eq(y, sub(0, 5)) { if 1 { sstore(0, 7) } }
|
||||
// }
|
||||
// if eq(x, sub(0, 5))
|
||||
// {
|
||||
// if eq(y, sub(0, 5)) { if 1 { sstore(0, 7) } }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,5 @@
|
||||
{ }
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// { }
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
let x := 7
|
||||
let y := 8
|
||||
if gt(sub(x, y), 20) { }
|
||||
if eq(sub(x, y), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) {}
|
||||
}
|
||||
// ----
|
||||
// step: reasoningBasedSimplifier
|
||||
//
|
||||
// {
|
||||
// let x := 7
|
||||
// let y := 8
|
||||
// if 1 { }
|
||||
// if 1 { }
|
||||
// }
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <libyul/optimiser/StackCompressor.h>
|
||||
#include <libyul/optimiser/VarNameCleaner.h>
|
||||
#include <libyul/optimiser/Suite.h>
|
||||
#include <libyul/optimiser/ReasoningBasedSimplifier.h>
|
||||
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
@@ -157,7 +158,7 @@ public:
|
||||
map<char, string> const& extraOptions = {
|
||||
{'#', "quit"},
|
||||
{',', "VarNameCleaner"},
|
||||
{';', "StackCompressor"},
|
||||
{';', "StackCompressor"}
|
||||
};
|
||||
|
||||
printUsageBanner(abbreviationMap, extraOptions, 4);
|
||||
|
||||
@@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(output_operator_should_create_concise_and_unambiguous_strin
|
||||
|
||||
BOOST_TEST(chromosome.length() == allSteps.size());
|
||||
BOOST_TEST(chromosome.optimisationSteps() == allSteps);
|
||||
BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighTLMNrmVatpud");
|
||||
BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighTLMNRrmVatpud");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(optimisationSteps_should_translate_chromosomes_genes_to_optimisation_step_names)
|
||||
|
||||
Reference in New Issue
Block a user