aboutsummaryrefslogtreecommitdiffstats
path: root/CodeFragment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CodeFragment.cpp')
-rw-r--r--CodeFragment.cpp338
1 files changed, 106 insertions, 232 deletions
diff --git a/CodeFragment.cpp b/CodeFragment.cpp
index c4b7ae0b..59ff729e 100644
--- a/CodeFragment.cpp
+++ b/CodeFragment.cpp
@@ -34,100 +34,6 @@ namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
namespace sp = boost::spirit;
-void CodeFragment::appendFragment(CodeFragment const& _f)
-{
- m_locs.reserve(m_locs.size() + _f.m_locs.size());
- m_code.reserve(m_code.size() + _f.m_code.size());
-
- unsigned os = m_code.size();
-
- for (auto i: _f.m_code)
- m_code.push_back(i);
-
- for (auto i: _f.m_locs)
- {
- CodeLocation(this, i + os).increase(os);
- m_locs.push_back(i + os);
- }
-
- for (auto i: _f.m_data)
- m_data.insert(make_pair(i.first, i.second + os));
-
- m_deposit += _f.m_deposit;
-}
-
-CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s)
-{
- CodeFragment ret;
- sp::utree o;
- parseTreeLLL(_src, o);
- if (!o.empty())
- ret = CodeFragment(o, _s);
- _s.treesToKill.push_back(o);
- return ret;
-}
-
-void CodeFragment::consolidateData()
-{
- m_code.push_back(0);
- bytes ld;
- for (auto const& i: m_data)
- {
- if (ld != i.first)
- {
- ld = i.first;
- for (auto j: ld)
- m_code.push_back(j);
- }
- CodeLocation(this, i.second).set(m_code.size() - ld.size());
- }
- m_data.clear();
-}
-
-void CodeFragment::appendFragment(CodeFragment const& _f, unsigned _deposit)
-{
- if ((int)_deposit > _f.m_deposit)
- error<InvalidDeposit>();
- else
- {
- appendFragment(_f);
- while (_deposit++ < (unsigned)_f.m_deposit)
- appendInstruction(Instruction::POP);
- }
-}
-
-CodeLocation CodeFragment::appendPushLocation(unsigned _locationValue)
-{
- m_code.push_back((byte)Instruction::PUSH4);
- CodeLocation ret(this, m_code.size());
- m_locs.push_back(m_code.size());
- m_code.resize(m_code.size() + 4);
- bytesRef r(&m_code[m_code.size() - 4], 4);
- toBigEndian(_locationValue, r);
- m_deposit++;
- return ret;
-}
-
-unsigned CodeFragment::appendPush(u256 _literalValue)
-{
- unsigned br = max<unsigned>(1, bytesRequired(_literalValue));
- m_code.push_back((byte)Instruction::PUSH1 + br - 1);
- m_code.resize(m_code.size() + br);
- for (unsigned i = 0; i < br; ++i)
- {
- m_code[m_code.size() - 1 - i] = (byte)(_literalValue & 0xff);
- _literalValue >>= 8;
- }
- m_deposit++;
- return br + 1;
-}
-
-void CodeFragment::appendInstruction(Instruction _i)
-{
- m_code.push_back((byte)_i);
- m_deposit += c_instructionInfo.at(_i).ret - c_instructionInfo.at(_i).args;
-}
-
CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM)
{
/* cdebug << "CodeFragment. Locals:";
@@ -151,12 +57,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
{
auto sr = _t.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>();
string s(sr.begin(), sr.end());
- if (s.size() > 32)
- error<StringTooLong>();
- h256 valHash;
- memcpy(valHash.data(), s.data(), s.size());
- memset(valHash.data() + s.size(), 0, 32 - s.size());
- appendPush(valHash);
+ m_asm.append(s);
break;
}
case sp::utree_type::symbol_type:
@@ -164,21 +65,14 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
auto sr = _t.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
string s(sr.begin(), sr.end());
string us = boost::algorithm::to_upper_copy(s);
- if (_allowASM)
- {
- if (c_instructions.count(us))
- {
- auto it = c_instructions.find(us);
- m_deposit = c_instructionInfo.at(it->second).ret - c_instructionInfo.at(it->second).args;
- m_code.push_back((byte)it->second);
- }
- }
+ if (_allowASM && c_instructions.count(us))
+ m_asm.append(c_instructions.at(us));
if (_s.defs.count(s))
- appendFragment(_s.defs.at(s));
+ m_asm.append(_s.defs.at(s).m_asm);
else if (_s.args.count(s))
- appendFragment(_s.args.at(s));
+ m_asm.append(_s.args.at(s).m_asm);
else if (_s.outers.count(s))
- appendFragment(_s.outers.at(s));
+ m_asm.append(_s.outers.at(s).m_asm);
else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_") == string::npos)
{
auto it = _s.vars.find(s);
@@ -187,7 +81,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
bool ok;
tie(it, ok) = _s.vars.insert(make_pair(s, _s.vars.size() * 32));
}
- appendPush(it->second);
+ m_asm.append((u256)it->second);
}
else
error<BareSymbol>();
@@ -199,44 +93,13 @@ 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>();
- appendPush((u256)i);
+ m_asm.append((u256)i);
break;
}
default: break;
}
}
-void CodeFragment::appendPushDataLocation(bytes const& _data)
-{
- m_code.push_back((byte)Instruction::PUSH4);
- m_data.insert(make_pair(_data, m_code.size()));
- m_code.resize(m_code.size() + 4);
- memset(&m_code.back() - 3, 0, 4);
- m_deposit++;
-}
-
-std::string CodeFragment::asPushedString() const
-{
- string ret;
- if (m_code.size())
- {
- unsigned bc = m_code[0] - (byte)Instruction::PUSH1 + 1;
- if (m_code[0] >= (byte)Instruction::PUSH1 && m_code[0] <= (byte)Instruction::PUSH32)
- {
- for (unsigned s = 0; s < bc && m_code[1 + s]; ++s)
- ret.push_back(m_code[1 + s]);
- return ret;
- }
- }
- error<ExpectedLiteral>();
- return ret;
-}
-
-void CodeFragment::optimise()
-{
-// map<string, function<bytes(vector<u256> const&)>> pattern = { { "PUSH,PUSH,ADD", [](vector<u256> const& v) { return CodeFragment(appendPush(v[0] + v[1])); } } };
-}
-
void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
{
if (_t.empty())
@@ -281,7 +144,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
int c = 0;
for (auto const& i: _t)
if (c++)
- appendFragment(CodeFragment(i, _s, true));
+ m_asm.append(CodeFragment(i, _s, true).m_asm);
}
else if (us == "INCLUDE")
{
@@ -299,9 +162,9 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (i.which() == sp::utree_type::symbol_type)
{
auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
- n = _s.getDef(string(sr.begin(), sr.end())).asPushedString();
+ n = _s.getDef(string(sr.begin(), sr.end())).m_asm.backString();
}
- appendFragment(CodeFragment::compile(asString(contents(n)), _s));
+ m_asm.append(CodeFragment::compile(asString(contents(n)), _s).m_asm);
}
else if (us == "DEF")
{
@@ -323,7 +186,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (i.which() == sp::utree_type::symbol_type)
{
auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
- n = _s.getDef(string(sr.begin(), sr.end())).asPushedString();
+ n = _s.getDef(string(sr.begin(), sr.end())).m_asm.backString();
}
}
else if (ii == 2)
@@ -362,7 +225,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
if (ii == 1)
{
pos = CodeFragment(i, _s);
- if (pos.m_deposit != 1)
+ if (pos.m_asm.deposit() != 1)
error<InvalidDeposit>();
}
else if (ii == 2 && !i.tag() && i.which() == sp::utree_type::string_type)
@@ -396,11 +259,11 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
error<InvalidLiteral>();
++ii;
}
- appendPush(data.size());
- appendInstruction(Instruction::DUP);
- appendPushDataLocation(data);
- appendFragment(pos, 1);
- appendInstruction(Instruction::CODECOPY);
+ m_asm.append((u256)data.size());
+ m_asm.append(Instruction::DUP);
+ m_asm.append(data);
+ m_asm.append(pos.m_asm, 1);
+ m_asm.append(Instruction::CODECOPY);
}
else
nonStandard = false;
@@ -427,7 +290,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(); };
auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(); };
auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error<IncorrectParameterCount>(); };
- auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_deposit != s) error<InvalidDeposit>(); };
+ auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_asm.deposit() != s) error<InvalidDeposit>(); };
if (_s.macros.count(s) && _s.macros.at(s).args.size() == code.size())
{
@@ -443,7 +306,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireDeposit(i, 1);
cs.args[m.args[i]] = code[i];
}
- appendFragment(CodeFragment(m.code, cs));
+ m_asm.append(CodeFragment(m.code, cs).m_asm);
for (auto const& i: cs.defs)
_s.defs[i.first] = i.second;
for (auto const& i: cs.macros)
@@ -459,8 +322,8 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireMinSize(-ea);
for (unsigned i = code.size(); i; --i)
- appendFragment(code[i - 1], 1);
- appendInstruction(it->second);
+ m_asm.append(code[i - 1].m_asm, 1);
+ m_asm.append(it->second);
}
else if (c_arith.count(us))
{
@@ -469,10 +332,10 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
for (unsigned i = code.size(); i; --i)
{
requireDeposit(i - 1, 1);
- appendFragment(code[i - 1], 1);
+ m_asm.append(code[i - 1].m_asm, 1);
}
for (unsigned i = 1; i < code.size(); ++i)
- appendInstruction(it->second);
+ m_asm.append(it->second);
}
else if (c_binary.count(us))
{
@@ -480,74 +343,75 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireSize(2);
requireDeposit(0, 1);
requireDeposit(1, 1);
- appendFragment(code[1], 1);
- appendFragment(code[0], 1);
- appendInstruction(it->second.first);
+ m_asm.append(code[1].m_asm, 1);
+ m_asm.append(code[0].m_asm, 1);
+ m_asm.append(it->second.first);
if (it->second.second)
- appendInstruction(Instruction::NOT);
+ m_asm.append(Instruction::NOT);
}
else if (c_unary.count(us))
{
auto it = c_unary.find(us);
requireSize(1);
requireDeposit(0, 1);
- appendFragment(code[0], 1);
- appendInstruction(it->second);
+ m_asm.append(code[0].m_asm, 1);
+ m_asm.append(it->second);
}
else if (us == "IF")
{
requireSize(3);
requireDeposit(0, 1);
- appendFragment(code[0]);
- auto pos = appendJumpI();
- onePath();
- appendFragment(code[2]);
- auto end = appendJump();
- otherPath();
- pos.anchor();
- appendFragment(code[1]);
- donePaths();
- end.anchor();
+
+ m_asm.append(code[0].m_asm);
+ auto pos = m_asm.appendJumpI();
+ m_asm.onePath();
+ m_asm << code[2].m_asm;
+ auto end = m_asm.appendJump();
+ m_asm.otherPath();
+ m_asm << pos.tag() << code[1].m_asm << end.tag();
+ m_asm.donePaths();
}
else if (us == "WHEN" || us == "UNLESS")
{
requireSize(2);
requireDeposit(0, 1);
- appendFragment(code[0]);
+
+ m_asm.append(code[0].m_asm);
if (us == "WHEN")
- appendInstruction(Instruction::NOT);
- auto end = appendJumpI();
- onePath();
- otherPath();
- appendFragment(code[1], 0);
- donePaths();
- end.anchor();
+ m_asm.append(Instruction::NOT);
+ auto end = m_asm.appendJumpI();
+ m_asm.onePath();
+ m_asm.otherPath();
+ m_asm << code[1].m_asm << end.tag();
+ m_asm.donePaths();
}
else if (us == "WHILE")
{
requireSize(2);
requireDeposit(0, 1);
- auto begin = CodeLocation(this);
- appendFragment(code[0], 1);
- appendInstruction(Instruction::NOT);
- auto end = appendJumpI();
- appendFragment(code[1], 0);
- appendJump(begin);
- end.anchor();
+
+ auto begin = m_asm.append();
+ m_asm.append(code[0].m_asm);
+ m_asm.append(Instruction::NOT);
+ auto end = m_asm.appendJumpI();
+ m_asm.append(code[1].m_asm, 0);
+ m_asm.appendJump(begin);
+ m_asm << end.tag();
}
else if (us == "FOR")
{
requireSize(4);
requireDeposit(1, 1);
- appendFragment(code[0], 0);
- auto begin = CodeLocation(this);
- appendFragment(code[1], 1);
- appendInstruction(Instruction::NOT);
- auto end = appendJumpI();
- appendFragment(code[3], 0);
- appendFragment(code[2], 0);
- appendJump(begin);
- end.anchor();
+
+ m_asm.append(code[0].m_asm, 0);
+ auto begin = m_asm.append();
+ m_asm.append(code[1].m_asm);
+ m_asm.append(Instruction::NOT);
+ auto end = m_asm.appendJumpI();
+ m_asm.append(code[3].m_asm, 0);
+ m_asm.append(code[2].m_asm, 0);
+ m_asm.appendJump(begin);
+ m_asm << end.tag();
}
else if (us == "LLL")
{
@@ -555,22 +419,22 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireMaxSize(3);
requireDeposit(1, 1);
- CodeLocation codeloc(this, m_code.size() + 6);
bytes const& subcode = code[0].code();
- appendPush(subcode.size());
- appendInstruction(Instruction::DUP);
+
+ m_asm.append((u256)subcode.size());
+ m_asm.append(Instruction::DUP);
if (code.size() == 3)
{
requireDeposit(2, 1);
- appendFragment(code[2], 1);
- appendInstruction(Instruction::LT);
- appendInstruction(Instruction::NOT);
- appendInstruction(Instruction::MUL);
- appendInstruction(Instruction::DUP);
+ m_asm.append(code[2].m_asm, 1);
+ m_asm.append(Instruction::LT);
+ m_asm.append(Instruction::NOT);
+ m_asm.append(Instruction::MUL);
+ m_asm.append(Instruction::DUP);
}
- appendPushDataLocation(subcode);
- appendFragment(code[1], 1);
- appendInstruction(Instruction::CODECOPY);
+ m_asm.append(subcode);
+ m_asm.append(code[1].m_asm, 1);
+ m_asm.append(Instruction::CODECOPY);
}
else if (us == "&&" || us == "||")
{
@@ -578,53 +442,52 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
for (unsigned i = 0; i < code.size(); ++i)
requireDeposit(i, 1);
- vector<CodeLocation> ends;
+ auto end = m_asm.newTag();
if (code.size() > 1)
{
- appendPush(us == "||" ? 1 : 0);
+ m_asm.append((u256)(us == "||" ? 1 : 0));
for (unsigned i = 1; i < code.size(); ++i)
{
// Check if true - predicate
- appendFragment(code[i - 1], 1);
+ m_asm.append(code[i - 1].m_asm, 1);
if (us == "&&")
- appendInstruction(Instruction::NOT);
- ends.push_back(appendJumpI());
+ m_asm.append(Instruction::NOT);
+ m_asm.appendJumpI(end);
}
- appendInstruction(Instruction::POP);
+ m_asm.append(Instruction::POP);
}
// Check if true - predicate
- appendFragment(code.back(), 1);
+ m_asm.append(code.back().m_asm, 1);
// At end now.
- for (auto& i: ends)
- i.anchor();
+ m_asm.append(end);
}
else if (us == "~")
{
requireSize(1);
requireDeposit(0, 1);
- appendFragment(code[0], 1);
- appendPush(1);
- appendPush(0);
- appendInstruction(Instruction::SUB);
- appendInstruction(Instruction::SUB);
+
+ m_asm.append(code[0].m_asm, 1);
+ m_asm.append((u256)1);
+ m_asm.append((u256)0);
+ m_asm.append(Instruction::SUB);
+ m_asm.append(Instruction::SUB);
}
else if (us == "SEQ")
{
unsigned ii = 0;
for (auto const& i: code)
if (++ii < code.size())
- appendFragment(i, 0);
+ m_asm.append(i.m_asm, 0);
else
- appendFragment(i);
+ m_asm.append(i.m_asm);
}
else if (us == "RAW")
{
for (auto const& i: code)
- appendFragment(i);
- while (m_deposit > 1)
- appendInstruction(Instruction::POP);
+ m_asm.append(i.m_asm);
+ m_asm.popTo(1);
}
else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_") == string::npos)
{
@@ -634,9 +497,20 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
bool ok;
tie(it, ok) = _s.vars.insert(make_pair(s, _s.vars.size() * 32));
}
- appendPush(it->second);
+ m_asm.append((u256)it->second);
}
else
error<InvalidOperation>();
}
}
+
+CodeFragment CodeFragment::compile(string const& _src, CompilerState& _s)
+{
+ CodeFragment ret;
+ sp::utree o;
+ parseTreeLLL(_src, o);
+ if (!o.empty())
+ ret = CodeFragment(o, _s);
+ _s.treesToKill.push_back(o);
+ return ret;
+}