diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2017-10-02 20:38:21 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-02 20:38:21 +0800 |
commit | 6cbb726fb8970c6cb98e9b6a2928ef612ad9d760 (patch) | |
tree | fcf65dc5db8179404b60a0332ad740cf24ab9a73 /liblll | |
parent | 2a8e965bb135a806aaaab9aa5df24da6d7def1ba (diff) | |
parent | d010d6300c667bbe81469a23e6bf76015623e76b (diff) | |
download | dexon-solidity-6cbb726fb8970c6cb98e9b6a2928ef612ad9d760.tar.gz dexon-solidity-6cbb726fb8970c6cb98e9b6a2928ef612ad9d760.tar.zst dexon-solidity-6cbb726fb8970c6cb98e9b6a2928ef612ad9d760.zip |
Merge pull request #2622 from benjaminion/lll-switch
LLL: Implement a "switch" expression
Diffstat (limited to 'liblll')
-rw-r--r-- | liblll/CodeFragment.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 5e60f964..4fa2c646 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -514,6 +514,44 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) m_asm.appendJump(begin); m_asm << end.tag(); } + else if (us == "SWITCH") + { + requireMinSize(1); + + bool hasDefault = (code.size() % 2 == 1); + int startDeposit = m_asm.deposit(); + int targetDeposit = hasDefault ? code[code.size() - 1].m_asm.deposit() : 0; + + // The conditions + AssemblyItems jumpTags; + for (unsigned i = 0; i < code.size() - 1; i += 2) + { + requireDeposit(i, 1); + m_asm.append(code[i].m_asm); + jumpTags.push_back(m_asm.appendJumpI()); + } + + // The default, if present + if (hasDefault) + m_asm.append(code[code.size() - 1].m_asm); + + // The targets - appending in reverse makes the top case the most efficient. + if (code.size() > 1) + { + auto end = m_asm.appendJump(); + for (int i = 2 * (code.size() / 2 - 1); i >= 0; i -= 2) + { + m_asm << jumpTags[i / 2].tag(); + requireDeposit(i + 1, targetDeposit); + m_asm.append(code[i + 1].m_asm); + if (i != 0) + m_asm.appendJump(end); + } + m_asm << end.tag(); + } + + m_asm.setDeposit(startDeposit + targetDeposit); + } else if (us == "ALLOC") { requireSize(1); |