From 8416a6260f3545ae7109091a09bef9291db59179 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 29 Apr 2015 18:16:05 +0200 Subject: [PATCH 1/7] Split known state from common subexpression eliminator. --- libsolidity/SolidityOptimizer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsolidity/SolidityOptimizer.cpp b/libsolidity/SolidityOptimizer.cpp index 9cdaa5886..71463f919 100644 --- a/libsolidity/SolidityOptimizer.cpp +++ b/libsolidity/SolidityOptimizer.cpp @@ -90,7 +90,8 @@ public: for (AssemblyItem& item: input) item.setLocation(SourceLocation(1, 3, make_shared(""))); - eth::CommonSubexpressionEliminator cse; + eth::KnownState state; + eth::CommonSubexpressionEliminator cse(state); BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); AssemblyItems output = cse.getOptimizedItems(); @@ -231,7 +232,8 @@ BOOST_AUTO_TEST_CASE(function_calls) BOOST_AUTO_TEST_CASE(cse_intermediate_swap) { - eth::CommonSubexpressionEliminator cse; + eth::KnownState state; + eth::CommonSubexpressionEliminator cse(state); AssemblyItems input{ Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1, Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1, From 3649c1fc60bf64171f843ec1cb73697b9f0ebd3f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 30 Apr 2015 14:41:55 +0200 Subject: [PATCH 2/7] Common subexpression elimination ready for using pre-known state. --- libsolidity/SolidityOptimizer.cpp | 49 ++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/libsolidity/SolidityOptimizer.cpp b/libsolidity/SolidityOptimizer.cpp index 71463f919..59e8f04a8 100644 --- a/libsolidity/SolidityOptimizer.cpp +++ b/libsolidity/SolidityOptimizer.cpp @@ -83,15 +83,28 @@ public: "\nOptimized: " + toHex(optimizedOutput)); } - AssemblyItems getCSE(AssemblyItems const& _input) + AssemblyItems addDummyLocations(AssemblyItems const& _input) { // add dummy locations to each item so that we can check that they are not deleted AssemblyItems input = _input; for (AssemblyItem& item: input) item.setLocation(SourceLocation(1, 3, make_shared(""))); + return input; + } + eth::KnownState createInitialState(AssemblyItems const& _input) + { eth::KnownState state; - eth::CommonSubexpressionEliminator cse(state); + for (auto const& item: addDummyLocations(_input)) + state.feedItem(item); + return state; + } + + AssemblyItems getCSE(AssemblyItems const& _input, eth::KnownState const& _state = eth::KnownState()) + { + AssemblyItems input = addDummyLocations(_input); + + eth::CommonSubexpressionEliminator cse(_state); BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); AssemblyItems output = cse.getOptimizedItems(); @@ -102,9 +115,13 @@ public: return output; } - void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation) + void checkCSE( + AssemblyItems const& _input, + AssemblyItems const& _expectation, + KnownState const& _state = eth::KnownState() + ) { - AssemblyItems output = getCSE(_input); + AssemblyItems output = getCSE(_input, _state); BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } @@ -756,6 +773,30 @@ BOOST_AUTO_TEST_CASE(cse_sha3_twice_same_content_noninterfering_store_in_between BOOST_CHECK_EQUAL(1, count(output.begin(), output.end(), AssemblyItem(Instruction::SHA3))); } +BOOST_AUTO_TEST_CASE(cse_with_initially_known_stack) +{ + eth::KnownState state = createInitialState(AssemblyItems{ + u256(0x12), + u256(0x20), + Instruction::ADD + }); + AssemblyItems input{ + u256(0x12 + 0x20) + }; + checkCSE(input, AssemblyItems{Instruction::DUP1}, state); +} + +BOOST_AUTO_TEST_CASE(cse_equality_on_initially_known_stack) +{ + eth::KnownState state = createInitialState(AssemblyItems{Instruction::DUP1}); + AssemblyItems input{ + Instruction::EQ + }; + AssemblyItems output = getCSE(input, state); + // check that it directly pushes 1 (true) + BOOST_CHECK(find(output.begin(), output.end(), AssemblyItem(u256(1))) != output.end()); +} + BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused) { // remove parts of the code that are unused From a0cc8abb2a162f883b5afd4757f52d926cf6df0b Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 5 May 2015 17:45:58 +0200 Subject: [PATCH 3/7] CFG returns vector of blocks instead of assembly items. --- libsolidity/SolidityOptimizer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libsolidity/SolidityOptimizer.cpp b/libsolidity/SolidityOptimizer.cpp index 59e8f04a8..3cb6a536a 100644 --- a/libsolidity/SolidityOptimizer.cpp +++ b/libsolidity/SolidityOptimizer.cpp @@ -131,8 +131,12 @@ public: // Running it four times should be enough for these tests. for (unsigned i = 0; i < 4; ++i) { - eth::ControlFlowGraph cfg(output); - output = cfg.optimisedItems(); + ControlFlowGraph cfg(output); + AssemblyItems optItems; + for (BasicBlock const& block: cfg.optimisedBlocks()) + copy(output.begin() + block.begin, output.begin() + block.end, + back_inserter(optItems)); + output = move(optItems); } BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } From ccf48882c9387bf153dca17777e1788de2277bca Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 8 May 2015 11:13:36 +0200 Subject: [PATCH 4/7] Basic key manager. From 757972b4e35ab30774355a4868b6bc5a49dda3d9 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Tue, 5 May 2015 12:33:41 +0200 Subject: [PATCH 5/7] added test --- libsolidity/SolidityNameAndTypeResolution.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libsolidity/SolidityNameAndTypeResolution.cpp b/libsolidity/SolidityNameAndTypeResolution.cpp index c317dad97..9616777ab 100644 --- a/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1761,6 +1761,25 @@ BOOST_AUTO_TEST_CASE(uninitialized_var) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } +BOOST_AUTO_TEST_CASE(deny_overwriting_of_attributes_when_deriving) +{ + // bug #1798 + char const* sourceCode = R"( + contract owned { + address owner; + } + + contract reg { + function owner(bytes32 x) returns (address) {} + } + + contract x is owned, reg { + } + )"; + ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode), "Parsing and Name Resolving Failed"); + //BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } From 960033de6bea1e436656ccc71b5152efd4314036 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Thu, 7 May 2015 18:12:58 +0200 Subject: [PATCH 6/7] fixed the test --- libsolidity/SolidityEndToEndTest.cpp | 29 +++++++++++++++++++ libsolidity/SolidityNameAndTypeResolution.cpp | 19 ------------ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/libsolidity/SolidityEndToEndTest.cpp b/libsolidity/SolidityEndToEndTest.cpp index f168ad454..2fd1e2ec2 100644 --- a/libsolidity/SolidityEndToEndTest.cpp +++ b/libsolidity/SolidityEndToEndTest.cpp @@ -3910,6 +3910,35 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls) BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9))); } +BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) +{ + // bug #1798 + char const* sourceCode = R"( + contract init { + function isOk() returns (bool) { return false; } + bool public ok = false; + } + contract fix { + function isOk() returns (bool) { return true; } + bool public ok = true; + } + + contract init_fix is init, fix { + function checkOk() returns (bool) { return ok; } + } + contract fix_init is fix, init { + function checkOk() returns (bool) { return ok; } + } + )"; + compileAndRun(sourceCode, 0, "init_fix"); + BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); + + compileAndRun(sourceCode, 0, "fix_init"); + BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(false)); + BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/libsolidity/SolidityNameAndTypeResolution.cpp b/libsolidity/SolidityNameAndTypeResolution.cpp index 9616777ab..c317dad97 100644 --- a/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1761,25 +1761,6 @@ BOOST_AUTO_TEST_CASE(uninitialized_var) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } -BOOST_AUTO_TEST_CASE(deny_overwriting_of_attributes_when_deriving) -{ - // bug #1798 - char const* sourceCode = R"( - contract owned { - address owner; - } - - contract reg { - function owner(bytes32 x) returns (address) {} - } - - contract x is owned, reg { - } - )"; - ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode), "Parsing and Name Resolving Failed"); - //BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); -} - BOOST_AUTO_TEST_SUITE_END() } From 37fbf06c98c263052082a8a843e26b4cae69531c Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 8 May 2015 17:50:44 +0200 Subject: [PATCH 7/7] added one more test --- libsolidity/SolidityEndToEndTest.cpp | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/libsolidity/SolidityEndToEndTest.cpp b/libsolidity/SolidityEndToEndTest.cpp index 2fd1e2ec2..f32439a27 100644 --- a/libsolidity/SolidityEndToEndTest.cpp +++ b/libsolidity/SolidityEndToEndTest.cpp @@ -3939,6 +3939,61 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false)); } +BOOST_AUTO_TEST_CASE(proper_overwriting_accessor_by_function) +{ + // bug #1798 + char const* sourceCode = R"( + contract attribute { + bool ok = false; + } + contract func { + function ok() returns (bool) { return true; } + } + + contract attr_func is attribute, func { + function checkOk() returns (bool) { return ok(); } + } + contract func_attr is func, attribute { + function checkOk() returns (bool) { return ok; } + } + )"; + compileAndRun(sourceCode, 0, "attr_func"); + BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); + compileAndRun(sourceCode, 0, "func_attr"); + BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(false)); +} + + +BOOST_AUTO_TEST_CASE(overwriting_inheritance) +{ + // bug #1798 + char const* sourceCode = R"( + contract A { + function ok() returns (uint) { return 1; } + } + contract B { + function ok() returns (uint) { return 2; } + } + contract C { + uint ok = 6; + } + contract AB is A, B { + function ok() returns (uint) { return 4; } + } + contract reversedE is C, AB { + function checkOk() returns (uint) { return ok(); } + } + contract E is AB, C { + function checkOk() returns (uint) { return ok; } + } + )"; + compileAndRun(sourceCode, 0, "reversedE"); + BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(4)); + compileAndRun(sourceCode, 0, "E"); + BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(6)); +} + + BOOST_AUTO_TEST_SUITE_END() }