aboutsummaryrefslogtreecommitdiffstats
path: root/liblll/CodeFragment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'liblll/CodeFragment.cpp')
-rw-r--r--liblll/CodeFragment.cpp52
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);