Browse Source

seq and asm.

cl-refactor
Gav Wood 11 years ago
parent
commit
8d1d14c1b6
  1. 59
      libethereum/Instruction.cpp
  2. 1
      libethereum/Instruction.h

59
libethereum/Instruction.cpp

@ -1163,7 +1163,7 @@ class CodeFragment
friend class CodeLocation; friend class CodeLocation;
public: public:
CodeFragment(sp::utree const& _t, CompileState const& _s = CompileState()); CodeFragment(sp::utree const& _t, CompileState const& _s = CompileState(), bool _allowASM = false);
bytes const& code() const { return m_code; } bytes const& code() const { return m_code; }
@ -1234,14 +1234,18 @@ void CodeLocation::increase(unsigned _val)
void CodeFragment::appendFragment(CodeFragment const& _f) void CodeFragment::appendFragment(CodeFragment const& _f)
{ {
m_locs.reserve(m_locs.size() + _f.m_locs.size()); m_locs.reserve(m_locs.size() + _f.m_locs.size());
for (auto i: _f.m_locs)
{
CodeLocation(this, i).increase((unsigned)m_code.size());
m_locs.push_back(i + (unsigned)m_code.size());
}
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();
for (auto i: _f.m_code) for (auto i: _f.m_code)
m_code.push_back(i); m_code.push_back(i);
for (auto i: _f.m_locs)
{
CodeLocation(this, i + os).increase(os);
m_locs.push_back(i + os);
}
m_deposit += _f.m_deposit;
} }
void CodeFragment::appendFragment(CodeFragment const& _f, unsigned _deposit) void CodeFragment::appendFragment(CodeFragment const& _f, unsigned _deposit)
@ -1301,7 +1305,7 @@ void debugOutAST(ostream& _out, sp::utree const& _this)
} }
} }
CodeFragment::CodeFragment(sp::utree const& _t, CompileState const& _s) CodeFragment::CodeFragment(sp::utree const& _t, CompileState const& _s, bool _allowASM)
{ {
switch (_t.which()) switch (_t.which())
{ {
@ -1322,6 +1326,21 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompileState const& _s)
} }
case sp::utree_type::symbol_type: case sp::utree_type::symbol_type:
{ {
if (_allowASM)
{
auto sr = _t.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
string s(sr.begin(), sr.end());
boost::algorithm::to_upper(s);
if (c_instructions.count(s))
{
auto it = c_instructions.find(s);
m_deposit = c_instructionInfo.at(it->second).ret - c_instructionInfo.at(it->second).args;
m_code.push_back((byte)it->second);
}
else
error<InvalidOpCode>();
}
else
error<SymbolNotFirst>(); error<SymbolNotFirst>();
break; break;
} }
@ -1345,15 +1364,28 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _
error<DataNotExecutable>(); error<DataNotExecutable>();
else else
{ {
auto sr = _t.front().get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
string s(sr.begin(), sr.end());
boost::algorithm::to_upper(s);
if (s == "ASM")
{
int c = 0;
for (auto const& i: _t)
if (c++)
appendFragment(CodeFragment(i, _s, true));
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, 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, Instruction> const c_unary = { { "!", Instruction::NOT } };
vector<CodeFragment> code; vector<CodeFragment> code;
int c = 0; int c = 0;
for (auto const& i: _t) for (auto const& i: _t)
if (c++) if (c++)
code.push_back(CodeFragment(i, _s)); code.push_back(CodeFragment(i, _s));
auto sr = _t.front().get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
string s(sr.begin(), sr.end());
boost::algorithm::to_upper(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 requireDeposit = [&](unsigned i, int s) { if (code[i].m_deposit != s) error<InvalidDeposit>(); }; auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_deposit != s) error<InvalidDeposit>(); };
@ -1400,6 +1432,11 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _
donePaths(); donePaths();
end.anchor(); end.anchor();
} }
else if (s == "SEQ")
{
for (auto const& i: code)
appendFragment(i, 0);
}
} }
} }

1
libethereum/Instruction.h

@ -160,6 +160,7 @@ 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 {};
bytes compileLLL(std::string const& _s, std::vector<std::string>* _errors); bytes compileLLL(std::string const& _s, std::vector<std::string>* _errors);
/// Append an appropriate PUSH instruction together with the literal value onto the given code. /// Append an appropriate PUSH instruction together with the literal value onto the given code.

Loading…
Cancel
Save