aboutsummaryrefslogtreecommitdiffstats
path: root/liblll
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2017-10-02 20:38:21 +0800
committerGitHub <noreply@github.com>2017-10-02 20:38:21 +0800
commit6cbb726fb8970c6cb98e9b6a2928ef612ad9d760 (patch)
treefcf65dc5db8179404b60a0332ad740cf24ab9a73 /liblll
parent2a8e965bb135a806aaaab9aa5df24da6d7def1ba (diff)
parentd010d6300c667bbe81469a23e6bf76015623e76b (diff)
downloaddexon-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.cpp38
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);