diff options
author | benjaminion <ben@edginet.org> | 2017-07-22 14:57:38 +0800 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2017-10-02 19:01:15 +0800 |
commit | 326c7887a42a04b9e27e8ddb4d8c8d0715d814e1 (patch) | |
tree | fb0c62a248eed3a20721446986ae88a61f16c0f4 /liblll | |
parent | c61610302aa2bfa029715b534719d25fe3949059 (diff) | |
download | dexon-solidity-326c7887a42a04b9e27e8ddb4d8c8d0715d814e1.tar.gz dexon-solidity-326c7887a42a04b9e27e8ddb4d8c8d0715d814e1.tar.zst dexon-solidity-326c7887a42a04b9e27e8ddb4d8c8d0715d814e1.zip |
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 254f436f..a7cb3699 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); |