mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into core_perf
This commit is contained in:
commit
1a673bfb6d
@ -3910,6 +3910,90 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls)
|
|||||||
BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9)));
|
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_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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -83,14 +83,28 @@ public:
|
|||||||
"\nOptimized: " + toHex(optimizedOutput));
|
"\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
|
// add dummy locations to each item so that we can check that they are not deleted
|
||||||
AssemblyItems input = _input;
|
AssemblyItems input = _input;
|
||||||
for (AssemblyItem& item: input)
|
for (AssemblyItem& item: input)
|
||||||
item.setLocation(SourceLocation(1, 3, make_shared<string>("")));
|
item.setLocation(SourceLocation(1, 3, make_shared<string>("")));
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
eth::CommonSubexpressionEliminator cse;
|
eth::KnownState createInitialState(AssemblyItems const& _input)
|
||||||
|
{
|
||||||
|
eth::KnownState 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());
|
BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end());
|
||||||
AssemblyItems output = cse.getOptimizedItems();
|
AssemblyItems output = cse.getOptimizedItems();
|
||||||
|
|
||||||
@ -101,9 +115,13 @@ public:
|
|||||||
return output;
|
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());
|
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +131,12 @@ public:
|
|||||||
// Running it four times should be enough for these tests.
|
// Running it four times should be enough for these tests.
|
||||||
for (unsigned i = 0; i < 4; ++i)
|
for (unsigned i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
eth::ControlFlowGraph cfg(output);
|
ControlFlowGraph cfg(output);
|
||||||
output = cfg.optimisedItems();
|
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());
|
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
||||||
}
|
}
|
||||||
@ -231,7 +253,8 @@ BOOST_AUTO_TEST_CASE(function_calls)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
|
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
|
||||||
{
|
{
|
||||||
eth::CommonSubexpressionEliminator cse;
|
eth::KnownState state;
|
||||||
|
eth::CommonSubexpressionEliminator cse(state);
|
||||||
AssemblyItems input{
|
AssemblyItems input{
|
||||||
Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1,
|
Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1,
|
||||||
Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1,
|
Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1,
|
||||||
@ -754,6 +777,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_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)
|
BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused)
|
||||||
{
|
{
|
||||||
// remove parts of the code that are unused
|
// remove parts of the code that are unused
|
||||||
|
Loading…
Reference in New Issue
Block a user