diff options
author | chriseth <chris@ethereum.org> | 2017-06-22 18:22:28 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-22 18:22:28 +0800 |
commit | 1c54ce2a2caa6c4d91091152ad8a52b7881e8b83 (patch) | |
tree | 3d4e9cc3a050f214bcd7649d0124c7c5f31582d5 | |
parent | 3094e777486c40c91c6cf3432ad60f29b9ada484 (diff) | |
parent | bc95da354d78912f1b2d1a726f072fb855f2c219 (diff) | |
download | dexon-solidity-1c54ce2a2caa6c4d91091152ad8a52b7881e8b83.tar.gz dexon-solidity-1c54ce2a2caa6c4d91091152ad8a52b7881e8b83.tar.zst dexon-solidity-1c54ce2a2caa6c4d91091152ad8a52b7881e8b83.zip |
Merge pull request #2399 from ethereum/lll-if
LLL: Replace obsolete assembly code
-rw-r--r-- | libevmasm/Assembly.cpp | 3 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 9 | ||||
-rw-r--r-- | liblll/CodeFragment.cpp | 19 | ||||
-rw-r--r-- | test/liblll/EndToEndTest.cpp | 62 |
4 files changed, 73 insertions, 20 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 92a4c2a4..606714d2 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -55,9 +55,6 @@ void Assembly::append(Assembly const& _a) m_subs += _a.m_subs; for (auto const& lib: _a.m_libraries) m_libraries.insert(lib); - - assert(!_a.m_baseDeposit); - assert(!_a.m_totalDeposit); } void Assembly::append(Assembly const& _a, int _deposit) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index d1cfc7ef..0d40abcf 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -85,12 +85,6 @@ public: AssemblyItem const& back() const { return m_items.back(); } std::string backString() const { return m_items.size() && m_items.back().type() == PushString ? m_strings.at((h256)m_items.back().data()) : std::string(); } - void onePath() { assertThrow(!m_totalDeposit && !m_baseDeposit, InvalidDeposit, ""); m_baseDeposit = m_deposit; m_totalDeposit = INT_MAX; } - void otherPath() { donePath(); m_totalDeposit = m_deposit; m_deposit = m_baseDeposit; } - void donePaths() { donePath(); m_totalDeposit = m_baseDeposit = 0; } - void ignored() { m_baseDeposit = m_deposit; } - void endIgnored() { m_deposit = m_baseDeposit; m_baseDeposit = 0; } - void injectStart(AssemblyItem const& _i); int deposit() const { return m_deposit; } void adjustDeposit(int _adjustment) { m_deposit += _adjustment; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } @@ -121,7 +115,6 @@ protected: /// returns the replaced tags. std::map<u256, u256> optimiseInternal(bool _enable, bool _isCreation, size_t _runs); - void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } unsigned bytesRequired(unsigned subTagSize) const; private: @@ -144,8 +137,6 @@ protected: mutable std::vector<size_t> m_tagPositionsInBytecode; int m_deposit = 0; - int m_baseDeposit = 0; - int m_totalDeposit = 0; SourceLocation m_currentSourceLocation; }; diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 9f37bc65..afef63e9 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -439,15 +439,21 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) int minDep = min(code[1].m_asm.deposit(), code[2].m_asm.deposit()); m_asm.append(code[0].m_asm); - auto pos = m_asm.appendJumpI(); - m_asm.onePath(); + auto mainBranch = m_asm.appendJumpI(); + + /// The else branch. + int startDeposit = m_asm.deposit(); m_asm.append(code[2].m_asm, minDep); auto end = m_asm.appendJump(); - m_asm.otherPath(); - m_asm << pos.tag(); + int deposit = m_asm.deposit(); + m_asm.setDeposit(startDeposit); + + /// The main branch. + m_asm << mainBranch.tag(); m_asm.append(code[1].m_asm, minDep); m_asm << end.tag(); - m_asm.donePaths(); + if (m_asm.deposit() != deposit) + error<InvalidDeposit>(); } else if (us == "WHEN" || us == "UNLESS") { @@ -458,11 +464,8 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (us == "WHEN") m_asm.append(Instruction::ISZERO); auto end = m_asm.appendJumpI(); - m_asm.onePath(); - m_asm.otherPath(); m_asm.append(code[1].m_asm, 0); m_asm << end.tag(); - m_asm.donePaths(); } else if (us == "WHILE" || us == "UNTIL") { diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 3668038d..a01eaca0 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -57,6 +57,68 @@ BOOST_AUTO_TEST_CASE(panic) BOOST_REQUIRE(m_output.empty()); } +BOOST_AUTO_TEST_CASE(when) +{ + char const* sourceCode = R"( + (returnlll + (seq + (when (= (calldatasize) 0) (return 1)) + (when (!= (calldatasize) 0) (return 2)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); + BOOST_CHECK(callFallback() == toBigEndian(u256(1))); +} + +BOOST_AUTO_TEST_CASE(unless) +{ + char const* sourceCode = R"( + (returnlll + (seq + (unless (!= (calldatasize) 0) (return 1)) + (unless (= (calldatasize) 0) (return 2)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); + BOOST_CHECK(callFallback() == toBigEndian(u256(1))); +} + +BOOST_AUTO_TEST_CASE(conditional_literal) +{ + char const* sourceCode = R"( + (returnlll + (seq + (return (if (= (calldatasize) 0) 1 2)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); + BOOST_CHECK(callFallback() == toBigEndian(u256(1))); +} + +BOOST_AUTO_TEST_CASE(conditional) +{ + char const* sourceCode = R"( + (returnlll + (seq + (if (= (calldatasize) 0) (return 1) (return 2)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); + BOOST_CHECK(callFallback() == toBigEndian(u256(1))); +} + +BOOST_AUTO_TEST_CASE(conditional_seq) +{ + char const* sourceCode = R"( + (returnlll + (seq + (return (if (= (calldatasize) 0) { 0 2 1 } { 0 1 2 })))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); + BOOST_CHECK(callFallback() == toBigEndian(u256(1))); +} + BOOST_AUTO_TEST_CASE(exp_operator_const) { char const* sourceCode = R"( |