Browse Source

Data segment for memory literals.

cl-refactor
Gav Wood 11 years ago
parent
commit
646dfeef84
  1. 153
      libethereum/Instruction.cpp
  2. 11
      libethereum/Instruction.h

153
libethereum/Instruction.cpp

@ -271,6 +271,7 @@ struct Macro
struct CompilerState struct CompilerState
{ {
std::map<std::string, unsigned> vars; std::map<std::string, unsigned> vars;
std::map<std::string, CodeFragment> defs; std::map<std::string, CodeFragment> defs;
std::map<std::string, Macro> macros; std::map<std::string, Macro> macros;
}; };
@ -317,6 +318,7 @@ void CodeFragment::appendFragment(CodeFragment const& _f)
m_code.reserve(m_code.size() + _f.m_code.size()); m_code.reserve(m_code.size() + _f.m_code.size());
unsigned os = m_code.size(); unsigned os = m_code.size();
for (auto i: _f.m_code) for (auto i: _f.m_code)
m_code.push_back(i); m_code.push_back(i);
@ -325,9 +327,30 @@ void CodeFragment::appendFragment(CodeFragment const& _f)
CodeLocation(this, i + os).increase(os); CodeLocation(this, i + os).increase(os);
m_locs.push_back(i + 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; m_deposit += _f.m_deposit;
} }
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) void CodeFragment::appendFragment(CodeFragment const& _f, unsigned _deposit)
{ {
if ((int)_deposit > _f.m_deposit) if ((int)_deposit > _f.m_deposit)
@ -429,8 +452,10 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
m_deposit = c_instructionInfo.at(it->second).ret - c_instructionInfo.at(it->second).args; m_deposit = c_instructionInfo.at(it->second).ret - c_instructionInfo.at(it->second).args;
m_code.push_back((byte)it->second); m_code.push_back((byte)it->second);
} }
else if (_s.defs.count(s))
appendFragment(_s.defs.at(s));
else else
error<InvalidOpCode>(); error<InvalidOperation>();
} }
else if (_s.defs.count(s)) else if (_s.defs.count(s))
appendFragment(_s.defs.at(s)); appendFragment(_s.defs.at(s));
@ -451,7 +476,14 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
} }
} }
// (define plus1 (a) (+ a 1)) 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++;
}
void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
{ {
@ -490,68 +522,82 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
default:; default:;
} }
// Operations who args are not standard stack-pushers.
bool nonStandard = true;
if (us == "ASM") if (us == "ASM")
{ {
int c = 0; int c = 0;
for (auto const& i: _t) for (auto const& i: _t)
if (c++) if (c++)
appendFragment(CodeFragment(i, _s, true)); appendFragment(CodeFragment(i, _s, true));
return;
} }
else if (us == "DEF")
if (us == "MACRO")
{ {
string n; string n;
unsigned ii = 0; unsigned ii = 0;
if (_t.size() != 4) if (_t.size() != 3 && _t.size() != 4)
error<IncorrectParameterCount>(); error<IncorrectParameterCount>();
for (auto const& i: _t) for (auto const& i: _t)
{ {
if (ii == 1) if (ii == 1)
{ {
if (i.tag() != 0 || i.which() != sp::utree_type::symbol_type) if (i.tag() || i.which() != sp::utree_type::symbol_type)
error<InvalidName>(); error<InvalidName>();
auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>(); auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
n = string(sr.begin(), sr.end()); n = string(sr.begin(), sr.end());
} }
else if (ii == 2) else if (ii == 2)
{ if (_t.size() == 3)
for (auto const& j: i) _s.defs[n] = CodeFragment(i, _s);
{ else
if (j.tag() != 0 || j.which() != sp::utree_type::symbol_type) for (auto const& j: i)
error<InvalidMacroArgs>(); {
auto sr = j.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>(); if (j.tag() || j.which() != sp::utree_type::symbol_type)
_s.macros[n].args.push_back(string(sr.begin(), sr.end())); error<InvalidMacroArgs>();
} auto sr = j.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
} _s.macros[n].args.push_back(string(sr.begin(), sr.end()));
}
else if (ii == 3) else if (ii == 3)
_s.macros[n].code = i; _s.macros[n].code = i;
++ii; ++ii;
} }
return;
} }
else if (us == "LIT")
if (us == "DEF")
{ {
string n; if (_t.size() < 3)
unsigned ii = 0;
if (_t.size() != 3)
error<IncorrectParameterCount>(); error<IncorrectParameterCount>();
unsigned ii = 0;
CodeFragment pos;
for (auto const& i: _t) for (auto const& i: _t)
{ {
if (ii == 1) if (ii == 1)
{ {
if (i.tag() != 0 || i.which() != sp::utree_type::symbol_type) pos = CodeFragment(i, _s);
error<InvalidName>(); if (pos.m_deposit != 1)
auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>(); error<InvalidDeposit>();
n = string(sr.begin(), sr.end());
} }
else if (ii == 2) else if (ii == 2 && !i.tag() && i.which() == sp::utree_type::string_type)
_s.defs[n] = CodeFragment(i, _s); {
auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>();
appendPush(sr.end() - sr.begin());
appendInstruction(Instruction::DUP);
appendPushDataLocation(bytes((byte const*)sr.begin(), (byte const*)sr.end()));
appendFragment(pos, 1);
appendInstruction(Instruction::CODECOPY);
}
else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::any_type)
{
}
else if (ii)
error<InvalidLiteral>();
++ii; ++ii;
} }
return;
} }
else
nonStandard = false;
if (nonStandard)
return;
std::map<std::string, Instruction> const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD }, { "&", Instruction::AND }, { "|", Instruction::OR }, { "^", Instruction::XOR } }; std::map<std::string, Instruction> const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD }, { "&", Instruction::AND }, { "|", Instruction::OR }, { "^", Instruction::XOR } };
std::map<std::string, pair<Instruction, bool>> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "S<", { Instruction::SLT, false } }, { "S<=", { Instruction::SGT, true } }, { "S>", { Instruction::SGT, false } }, { "S>=", { Instruction::SLT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } }; std::map<std::string, pair<Instruction, bool>> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "S<", { Instruction::SLT, false } }, { "S<=", { Instruction::SGT, true } }, { "S>", { Instruction::SGT, false } }, { "S>=", { Instruction::SLT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } };
@ -563,7 +609,12 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
int c = _t.tag() ? 1 : 0; int c = _t.tag() ? 1 : 0;
for (auto const& i: _t) for (auto const& i: _t)
if (c++) if (c++)
code.push_back(CodeFragment(i, (us == "LLL" && c == 1) ? ns : _s)); {
if (us == "LLL" && c == 1)
code.push_back(CodeFragment(i, ns));
else
code.push_back(CodeFragment(i, _s));
}
auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(); }; auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(); };
auto requireMinSize = [&](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 requireMaxSize = [&](unsigned s) { if (code.size() > s) error<IncorrectParameterCount>(); };
@ -669,20 +720,6 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
appendJump(begin); appendJump(begin);
end.anchor(); end.anchor();
} }
/*else if (s == "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();
}*/
else if (us == "LLL") else if (us == "LLL")
{ {
requireMinSize(2); requireMinSize(2);
@ -690,11 +727,8 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireDeposit(1, 1); requireDeposit(1, 1);
CodeLocation codeloc(this, m_code.size() + 6); CodeLocation codeloc(this, m_code.size() + 6);
appendJump(codeloc + code[0].size()); bytes const& subcode = code[0].code();
ignored(); appendPush(subcode.size());
appendFragment(code[0]);
endIgnored();
appendPush(code[0].size());
appendInstruction(Instruction::DUP); appendInstruction(Instruction::DUP);
if (code.size() == 3) if (code.size() == 3)
{ {
@ -705,7 +739,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
appendInstruction(Instruction::MUL); appendInstruction(Instruction::MUL);
appendInstruction(Instruction::DUP); appendInstruction(Instruction::DUP);
} }
appendPushLocation(codeloc); appendPushDataLocation(subcode);
appendFragment(code[1], 1); appendFragment(code[1], 1);
appendInstruction(Instruction::CODECOPY); appendInstruction(Instruction::CODECOPY);
} }
@ -768,7 +802,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
} }
appendFragment(CodeFragment(m.code, cs)); appendFragment(CodeFragment(m.code, cs));
} }
else else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890") == string::npos)
{ {
auto it = _s.vars.find(s); auto it = _s.vars.find(s);
if (it == _s.vars.end()) if (it == _s.vars.end())
@ -778,18 +812,27 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
} }
appendPush(it->second); appendPush(it->second);
} }
// else else
// error<InvalidOpCode>(); error<InvalidOperation>();
} }
} }
bytes eth::compileLLL(string const& _s, vector<string>* _errors) bytes eth::compileLLL(string const& _s, vector<string>* _errors)
{ {
bytes ret;
sp::utree o; sp::utree o;
parseLLL(_s, o); try
{
parseLLL(_s, o);
}
catch (...)
{
if (_errors)
_errors->push_back("Syntax error.");
return ret;
}
debugOutAST(cerr, o); debugOutAST(cerr, o);
cerr << endl; cerr << endl;
bytes ret;
if (!o.empty()) if (!o.empty())
try try
{ {

11
libethereum/Instruction.h

@ -152,16 +152,15 @@ std::string disassemble(bytes const& _mem);
/// Compile a Low-level Lisp-like Language program into EVM-code. /// Compile a Low-level Lisp-like Language program into EVM-code.
class CompilerException: public Exception {}; class CompilerException: public Exception {};
class InvalidOperation: public CompilerException {}; class InvalidOperation: public CompilerException {};
class SymbolNotFirst: public CompilerException {};
class IntegerOutOfRange: public CompilerException {}; class IntegerOutOfRange: public CompilerException {};
class StringTooLong: public CompilerException {}; class StringTooLong: public CompilerException {};
class EmptyList: public CompilerException {}; class EmptyList: public CompilerException {};
class DataNotExecutable: public CompilerException {}; class DataNotExecutable: public CompilerException {};
class IncorrectParameterCount: public CompilerException {}; class IncorrectParameterCount: public CompilerException {};
class InvalidDeposit: public CompilerException {}; class InvalidDeposit: public CompilerException {};
class InvalidOpCode: public CompilerException {};
class InvalidName: public CompilerException {}; class InvalidName: public CompilerException {};
class InvalidMacroArgs: public CompilerException {}; class InvalidMacroArgs: public CompilerException {};
class InvalidLiteral: public CompilerException {};
class BareSymbol: public CompilerException {}; class BareSymbol: public CompilerException {};
bytes compileLLL(std::string const& _s, std::vector<std::string>* _errors = nullptr); bytes compileLLL(std::string const& _s, std::vector<std::string>* _errors = nullptr);
@ -199,15 +198,18 @@ public:
CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM = false); CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM = false);
CodeFragment(bytes const& _c = bytes()): m_code(_c) {} CodeFragment(bytes const& _c = bytes()): m_code(_c) {}
bytes const& code() const { return m_code; } /// Consolidates data and returns code.
bytes const& code() { consolidateData(); return m_code; }
unsigned appendPush(u256 _l); unsigned appendPush(u256 _l);
void appendFragment(CodeFragment const& _f); void appendFragment(CodeFragment const& _f);
void appendFragment(CodeFragment const& _f, unsigned _i); void appendFragment(CodeFragment const& _f, unsigned _i);
void appendInstruction(Instruction _i); void appendInstruction(Instruction _i);
void appendString(std::string const& _s) { for (auto i: _s) m_code.push_back((char)i); }
CodeLocation appendPushLocation(unsigned _l = 0); CodeLocation appendPushLocation(unsigned _l = 0);
void appendPushLocation(CodeLocation _l) { assert(_l.m_f == this); appendPushLocation(_l.m_pos); } void appendPushLocation(CodeLocation _l) { assert(_l.m_f == this); appendPushLocation(_l.m_pos); }
void appendPushDataLocation(bytes const& _data);
CodeLocation appendJump() { auto ret = appendPushLocation(0); appendInstruction(Instruction::JUMP); return ret; } CodeLocation appendJump() { auto ret = appendPushLocation(0); appendInstruction(Instruction::JUMP); return ret; }
CodeLocation appendJumpI() { auto ret = appendPushLocation(0); appendInstruction(Instruction::JUMPI); return ret; } CodeLocation appendJumpI() { auto ret = appendPushLocation(0); appendInstruction(Instruction::JUMPI); return ret; }
@ -222,6 +224,8 @@ public:
unsigned size() const { return m_code.size(); } unsigned size() const { return m_code.size(); }
void consolidateData();
private: private:
template <class T> void error() { throw T(); } template <class T> void error() { throw T(); }
void constructOperation(sp::utree const& _t, CompilerState& _s); void constructOperation(sp::utree const& _t, CompilerState& _s);
@ -233,6 +237,7 @@ private:
int m_totalDeposit = 0; int m_totalDeposit = 0;
bytes m_code; bytes m_code;
std::vector<unsigned> m_locs; std::vector<unsigned> m_locs;
std::multimap<bytes, unsigned> m_data;
}; };
} }

Loading…
Cancel
Save