Merge remote-tracking branch 'upstream/develop' into evmjit-develop

Conflicts:
	test/TestHelper.cpp
This commit is contained in:
Paweł Bylica 2015-05-13 13:09:20 +02:00
commit 0ba738994c
3 changed files with 141 additions and 34 deletions

View File

@ -552,6 +552,9 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e
void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests)
{
if (!Options::get().singleTest)
return;
if (Options::get().singleTestFile.empty() || Options::get().singleTestName.empty())
{
cnote << "Missing user test specification\nUsage: testeth --singletest <filename> <testname>\n";
return;
@ -731,11 +734,23 @@ Options::Options()
inputLimits = true;
bigData = true;
}
else if (arg == "--singletest" && i + 2 < argc)
else if (arg == "--singletest" && i + 1 < argc)
{
singleTest = true;
singleTestFile = argv[i + 1];
singleTestName = argv[i + 2];
auto name1 = std::string{argv[i + 1]};
if (i + 1 < argc) // two params
{
auto name2 = std::string{argv[i + 2]};
if (name2[0] == '-') // not param, another option
singleTestName = std::move(name1);
else
{
singleTestFile = std::move(name1);
singleTestName = std::move(name2);
}
}
else
singleTestName = std::move(name1);
}
}
}

View File

@ -116,36 +116,35 @@ BOOST_AUTO_TEST_CASE(ifStatement)
bytes code = compileContract(sourceCode);
unsigned shift = 60;
unsigned boilerplateSize = 73;
bytes expectation({byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x0,
byte(Instruction::DUP1),
byte(Instruction::PUSH1), byte(0x1b + shift), // "true" target
byte(Instruction::JUMPI),
// new check "else if" condition
byte(Instruction::DUP1),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), byte(0x13 + shift),
byte(Instruction::JUMPI),
// "else" body
byte(Instruction::PUSH1), 0x4f,
byte(Instruction::POP),
byte(Instruction::PUSH1), byte(0x17 + shift), // exit path of second part
byte(Instruction::JUMP),
// "else if" body
byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x4e,
byte(Instruction::POP),
byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), byte(0x1f + shift),
byte(Instruction::JUMP),
// "if" body
byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x4d,
byte(Instruction::POP),
byte(Instruction::JUMPDEST),
byte(Instruction::JUMPDEST),
byte(Instruction::POP),
byte(Instruction::JUMP)});
bytes expectation({
byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x0,
byte(Instruction::DUP1),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), byte(0x0f + shift), // "false" target
byte(Instruction::JUMPI),
// "if" body
byte(Instruction::PUSH1), 0x4d,
byte(Instruction::POP),
byte(Instruction::PUSH1), byte(0x21 + shift),
byte(Instruction::JUMP),
// new check "else if" condition
byte(Instruction::JUMPDEST),
byte(Instruction::DUP1),
byte(Instruction::ISZERO),
byte(Instruction::ISZERO),
byte(Instruction::PUSH1), byte(0x1c + shift),
byte(Instruction::JUMPI),
// "else if" body
byte(Instruction::PUSH1), 0x4e,
byte(Instruction::POP),
byte(Instruction::PUSH1), byte(0x20 + shift),
byte(Instruction::JUMP),
// "else" body
byte(Instruction::JUMPDEST),
byte(Instruction::PUSH1), 0x4f,
byte(Instruction::POP),
});
checkCodePresentAt(code, expectation, boilerplateSize);
}

View File

@ -29,6 +29,7 @@
#include <libevmasm/CommonSubexpressionEliminator.h>
#include <libevmasm/ControlFlowGraph.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/BlockDeduplicator.h>
using namespace std;
using namespace dev::eth;
@ -125,7 +126,7 @@ public:
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
}
void checkCFG(AssemblyItems const& _input, AssemblyItems const& _expectation)
AssemblyItems getCFG(AssemblyItems const& _input)
{
AssemblyItems output = _input;
// Running it four times should be enough for these tests.
@ -138,6 +139,12 @@ public:
back_inserter(optItems));
output = move(optItems);
}
return output;
}
void checkCFG(AssemblyItems const& _input, AssemblyItems const& _expectation)
{
AssemblyItems output = getCFG(_input);
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
}
@ -251,6 +258,63 @@ BOOST_AUTO_TEST_CASE(function_calls)
compareVersions("f(uint256)", 36);
}
BOOST_AUTO_TEST_CASE(storage_write_in_loops)
{
char const* sourceCode = R"(
contract test {
uint d;
function f(uint a) returns (uint r) {
var x = d;
for (uint i = 1; i < a * a; i++) {
r = d;
d = i;
}
}
}
)";
compileBothVersions(sourceCode);
compareVersions("f(uint256)", 0);
compareVersions("f(uint256)", 10);
compareVersions("f(uint256)", 36);
}
BOOST_AUTO_TEST_CASE(retain_information_in_branches)
{
// This tests that the optimizer knows that we already have "z == sha3(y)" inside both branches.
char const* sourceCode = R"(
contract c {
bytes32 d;
uint a;
function f(uint x, bytes32 y) returns (uint r_a, bytes32 r_d) {
bytes32 z = sha3(y);
if (x > 8) {
z = sha3(y);
a = x;
} else {
z = sha3(y);
a = x;
}
r_a = a;
r_d = d;
}
}
)";
compileBothVersions(sourceCode);
compareVersions("f(uint256,bytes32)", 0, "abc");
compareVersions("f(uint256,bytes32)", 8, "def");
compareVersions("f(uint256,bytes32)", 10, "ghi");
m_optimize = true;
bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c");
size_t numSHA3s = 0;
eth::eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
if (_instr == eth::Instruction::SHA3)
numSHA3s++;
});
BOOST_CHECK_EQUAL(1, numSHA3s);
}
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
{
eth::KnownState state;
@ -868,6 +932,35 @@ BOOST_AUTO_TEST_CASE(control_flow_graph_do_not_remove_returned_to)
checkCFG(input, {u256(2)});
}
BOOST_AUTO_TEST_CASE(block_deduplicator)
{
AssemblyItems input{
AssemblyItem(PushTag, 2),
AssemblyItem(PushTag, 1),
AssemblyItem(PushTag, 3),
u256(6),
eth::Instruction::SWAP3,
eth::Instruction::JUMP,
AssemblyItem(Tag, 1),
u256(6),
eth::Instruction::SWAP3,
eth::Instruction::JUMP,
AssemblyItem(Tag, 2),
u256(6),
eth::Instruction::SWAP3,
eth::Instruction::JUMP,
AssemblyItem(Tag, 3)
};
BlockDeduplicator dedup(input);
dedup.deduplicate();
set<u256> pushTags;
for (AssemblyItem const& item: input)
if (item.type() == PushTag)
pushTags.insert(item.data());
BOOST_CHECK_EQUAL(pushTags.size(), 2);
}
BOOST_AUTO_TEST_SUITE_END()
}