diff options
Diffstat (limited to 'liblll/CodeFragment.cpp')
-rw-r--r-- | liblll/CodeFragment.cpp | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 254f436f..4fa2c646 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -103,7 +103,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS { bigint i = *_t.get<bigint*>(); if (i < 0 || i > bigint(u256(0) - 1)) - error<IntegerOutOfRange>(); + error<IntegerOutOfRange>(toString(i)); m_asm.append((u256)i); break; } @@ -157,7 +157,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { auto i = *++_t.begin(); if (i.tag()) - error<InvalidName>(); + error<InvalidName>(toString(i)); if (i.which() == sp::utree_type::string_type) { auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>(); @@ -244,7 +244,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (ii == 1) { if (i.tag()) - error<InvalidName>(); + error<InvalidName>(toString(i)); if (i.which() == sp::utree_type::string_type) { auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>(); @@ -303,11 +303,11 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { pos = CodeFragment(i, _s); if (pos.m_asm.deposit() != 1) - error<InvalidDeposit>(us); + error<InvalidDeposit>(toString(i)); } else if (i.tag() != 0) { - error<InvalidLiteral>(); + error<InvalidLiteral>(toString(i)); } else if (i.which() == sp::utree_type::string_type) { @@ -318,7 +318,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { bigint bi = *i.get<bigint*>(); if (bi < 0) - error<IntegerOutOfRange>(); + error<IntegerOutOfRange>(toString(i)); else { bytes tmp = toCompactBigEndian(bi); @@ -327,7 +327,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } else { - error<InvalidLiteral>(); + error<InvalidLiteral>(toString(i)); } ii++; @@ -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); |