Browse Source

Stack/argument awareness in LLL.

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

145
libethereum/Instruction.cpp

@ -137,7 +137,7 @@ static void appendCode(u256s& o_code, vector<unsigned>& o_locs, u256s _code, vec
o_code.push_back(i);
}
static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256s& o_code, vector<unsigned>& o_locs)
static int compileLispFragment(char const*& d, char const* e, bool _quiet, u256s& o_code, vector<unsigned>& o_locs)
{
std::map<std::string, Instruction> const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD } };
std::map<std::string, Instruction> const c_binary = { { "<", Instruction::LT }, { "<=", Instruction::LE }, { ">", Instruction::GT }, { ">=", Instruction::GE }, { "=", Instruction::EQ }, { "!=", Instruction::NOT } };
@ -145,6 +145,7 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
std::set<char> const c_allowed = { '+', '-', '*', '/', '%', '<', '>', '=', '!' };
bool exec = false;
int outs = 1;
while (d != e)
{
@ -166,11 +167,11 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
if (exec)
{
++d;
return true;
return outs;
}
else
// unexpected - return false as we don't know what to do with it.
return false;
return -1;
default:
{
bool haveLiteral = false;
@ -214,7 +215,7 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
if (compileLispFragment(d, e, _quiet, codes, locs))
{
appendCode(o_code, o_locs, codes, locs);
while (compileLispFragment(d, e, _quiet, codes, locs))
while (compileLispFragment(d, e, _quiet, codes, locs) != -1)
if (!_quiet)
cwarn << "Additional items in bare store. Ignoring.";
bareLoad = false;
@ -234,9 +235,14 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
u256s codes[4];
vector<unsigned> locs[4];
for (int i = 0; i < 3; ++i)
if (!compileLispFragment(d, e, _quiet, codes[i], locs[i]))
return false;
if (compileLispFragment(d, e, _quiet, codes[3], locs[3]))
{
int o = compileLispFragment(d, e, _quiet, codes[i], locs[i]);
if (i == 1)
outs = o;
if ((i == 0 && o != 1) || o == -1 || (i == 2 && o != outs))
return -1;
}
if (compileLispFragment(d, e, _quiet, codes[3], locs[3]) != -1)
return false;
// Push the positive location.
@ -270,13 +276,19 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
}
else if (t == "WHEN" || t == "UNLESS")
{
outs = 0;
// Compile all the code...
u256s codes[3];
vector<unsigned> locs[3];
for (int i = 0; i < 2; ++i)
if (!compileLispFragment(d, e, _quiet, codes[i], locs[i]))
{
int o = compileLispFragment(d, e, _quiet, codes[i], locs[i]);
if (o == -1)
return false;
if (compileLispFragment(d, e, _quiet, codes[2], locs[2]))
for (int i = 0; i < o; ++i)
o_code.push_back(Instruction::POP); // pop additional items off stack for the previous item (final item's returns get left on).
}
if (compileLispFragment(d, e, _quiet, codes[2], locs[2]) != -1)
return false;
// Push the positive location.
@ -301,13 +313,19 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
}
else if (t == "FOR")
{
outs = 0;
// Compile all the code...
u256s codes[3];
vector<unsigned> locs[3];
for (int i = 0; i < 2; ++i)
if (!compileLispFragment(d, e, _quiet, codes[i], locs[i]))
{
int o = compileLispFragment(d, e, _quiet, codes[i], locs[i]);
if (o == -1)
return false;
if (compileLispFragment(d, e, _quiet, codes[2], locs[2]))
for (int i = 0; i < o; ++i)
o_code.push_back(Instruction::POP); // pop additional items off stack for the previous item (final item's returns get left on).
}
if (compileLispFragment(d, e, _quiet, codes[2], locs[2]) != -1)
return false;
unsigned startLocation = (unsigned)o_code.size();
@ -343,8 +361,15 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
{
u256s codes;
vector<unsigned> locs;
if (compileLispFragment(d, e, _quiet, codes, locs))
outs = 0;
int o;
if ((o = compileLispFragment(d, e, _quiet, codes, locs)) > -1)
{
for (int i = 0; i < outs; ++i)
o_code.push_back(Instruction::POP); // pop additional items off stack for the previous item (final item's returns get left on).
outs = o;
appendCode(o_code, o_locs, codes, locs);
}
else
break;
}
@ -357,7 +382,12 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
{
codes.resize(codes.size() + 1);
locs.resize(locs.size() + 1);
if (!compileLispFragment(d, e, _quiet, codes.back(), locs.back()))
{
int o = compileLispFragment(d, e, _quiet, codes.back(), locs.back());
if (o != 1)
return false;
}
if (compileLispFragment(d, e, _quiet, codes.back(), locs.back()) != -1)
break;
}
@ -408,8 +438,11 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
{
codes.resize(codes.size() + 1);
locs.resize(locs.size() + 1);
if (!compileLispFragment(d, e, _quiet, codes.back(), locs.back()))
break;
{
int o = compileLispFragment(d, e, _quiet, codes.back(), locs.back());
if (o != 1)
return false;
}
}
// last one is empty.
@ -458,11 +491,26 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
if (exec)
{
vector<pair<u256s, vector<unsigned>>> codes(1);
while (d != e && compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second))
int totalArgs = 0;
while (d != e)
{
int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second);
if (o < 1)
break;
codes.push_back(pair<u256s, vector<unsigned>>());
totalArgs += o;
}
int ea = c_instructionInfo.at(it->second).args;
if (totalArgs != ea || (ea < 0 && totalArgs < -ea))
{
cwarn << "Expected " << (ea < 0 ? "at least" : "exactly") << abs(ea) << "arguments to binary operator" << t << "; got" << totalArgs << ".";
break;
}
for (auto it = codes.rbegin(); it != codes.rend(); ++it)
appendCode(o_code, o_locs, it->first, it->second);
o_code.push_back((u256)it->second);
outs = c_instructionInfo.at(it->second).ret;
}
else
{
@ -480,15 +528,22 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
{
u256s codes;
vector<unsigned> locs;
if (compileLispFragment(d, e, _quiet, codes, locs))
int o = compileLispFragment(d, e, _quiet, codes, locs);
if (o == -1)
{
appendCode(o_code, o_locs, codes, locs);
if (i)
o_code.push_back((u256)it->second);
++i;
if (!i)
cwarn << "Expected at least one argument to operation" << t;
break;
}
else
if (o == 0)
{
cwarn << "null operation given to " << t;
break;
}
appendCode(o_code, o_locs, codes, locs);
i += o;
for (; i > 1; --i)
o_code.push_back((u256)it->second);
}
}
else
@ -497,15 +552,24 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
if (it != c_binary.end())
{
vector<pair<u256s, vector<unsigned>>> codes(1);
while (d != e && compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second))
int totalArgs = 0;
while (d != e)
{
int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second);
if (o < 1)
break;
codes.push_back(pair<u256s, vector<unsigned>>());
totalArgs += o;
}
codes.pop_back();
int i = (int)codes.size();
if (i > 2)
cwarn << "Greater than two arguments given to binary operator" << t << "; using first two only.";
// int i = (int)codes.size();
if (totalArgs != 2)
{
cwarn << "Expected two arguments to binary operator" << t << "; got" << totalArgs << ".";
break;
}
for (auto it = codes.rbegin(); it != codes.rend(); ++it)
if (--i < 2)
appendCode(o_code, o_locs, it->first, it->second);
appendCode(o_code, o_locs, it->first, it->second);
if (it->second == Instruction::NOT)
o_code.push_back(Instruction::EQ);
o_code.push_back((u256)it->second);
@ -516,15 +580,24 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
if (it != c_unary.end())
{
vector<pair<u256s, vector<unsigned>>> codes(1);
while (d != e && compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second))
int totalArgs = 0;
while (d != e)
{
int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second);
if (o == -1)
break;
totalArgs += o;
codes.push_back(pair<u256s, vector<unsigned>>());
}
codes.pop_back();
int i = (int)codes.size();
if (i > 1)
cwarn << "Greater than one argument given to unary operator" << t << "; using first only.";
// int i = (int)codes.size();
if (totalArgs != 1)
{
cwarn << "Expected one argument to unary operator" << t << "; got" << totalArgs << ".";
break;
}
for (auto it = codes.rbegin(); it != codes.rend(); ++it)
if (--i < 1)
appendCode(o_code, o_locs, it->first, it->second);
appendCode(o_code, o_locs, it->first, it->second);
o_code.push_back(it->second);
}
else if (!_quiet)
@ -536,11 +609,11 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
}
if (!exec)
return true;
return outs;
}
}
}
return false;
return -1;
}
u256s eth::compileLisp(std::string const& _code, bool _quiet)

8
libethereum/Instruction.h

@ -126,10 +126,10 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::BASEFEE, { "BASEFEE", 0, 0, 1 } },
{ Instruction::SHA256, { "SHA256", 0, -1, 1 } },
{ Instruction::RIPEMD160, { "RIPEMD160", 0, -1, 1 } },
{ Instruction::ECMUL, { "ECMUL", 0, 3, 1 } },
{ Instruction::ECADD, { "ECADD", 0, 4, 1 } },
{ Instruction::ECSIGN, { "ECSIGN", 0, 2, 1 } },
{ Instruction::ECRECOVER, { "ECRECOVER", 0, 4, 1 } },
{ Instruction::ECMUL, { "ECMUL", 0, 3, 2 } },
{ Instruction::ECADD, { "ECADD", 0, 4, 2 } },
{ Instruction::ECSIGN, { "ECSIGN", 0, 2, 3 } },
{ Instruction::ECRECOVER, { "ECRECOVER", 0, 4, 2 } },
{ Instruction::ECVALID, { "ECVALID", 0, 2, 1 } },
{ Instruction::SHA3, { "SHA3", 0, -1, 1 } },
{ Instruction::PUSH, { "PUSH", 1, 0, 1 } },

Loading…
Cancel
Save