Browse Source

Merge pull request #1345 from chriseth/assemblyCleanup

Assembly cleanup
cl-refactor
Gav Wood 10 years ago
parent
commit
b3f2af98f1
  1. 114
      libevmcore/Assembly.cpp
  2. 11
      libevmcore/Assembly.h

114
libevmcore/Assembly.cpp

@ -47,9 +47,6 @@ unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const
case PushData:
case PushSub:
return 1 + _addressLength;
case NoOptimizeBegin:
case NoOptimizeEnd:
return 0;
default:
break;
}
@ -61,7 +58,7 @@ int AssemblyItem::deposit() const
switch (m_type)
{
case Operation:
return instructionInfo((Instruction)(byte)m_data).ret - instructionInfo((Instruction)(byte)m_data).args;
return instructionInfo(instruction()).ret - instructionInfo(instruction()).args;
case Push:
case PushString:
case PushTag:
@ -91,6 +88,48 @@ string AssemblyItem::getJumpTypeAsString() const
}
}
ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
{
switch (_item.type())
{
case Operation:
_out << " " << instructionInfo(_item.instruction()).name;
if (_item.instruction() == eth::Instruction::JUMP || _item.instruction() == eth::Instruction::JUMPI)
_out << "\t" << _item.getJumpTypeAsString();
break;
case Push:
_out << " PUSH " << hex << _item.data();
break;
case PushString:
_out << " PushString" << hex << (unsigned)_item.data();
break;
case PushTag:
_out << " PushTag " << _item.data();
break;
case Tag:
_out << " Tag " << _item.data();
break;
case PushData:
_out << " PushData " << hex << (unsigned)_item.data();
break;
case PushSub:
_out << " PushSub " << hex << h256(_item.data()).abridged();
break;
case PushSubSize:
_out << " PushSubSize " << hex << h256(_item.data()).abridged();
break;
case PushProgramSize:
_out << " PushProgramSize";
break;
case UndefinedItem:
_out << " ???";
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}
return _out;
}
unsigned Assembly::bytesRequired() const
{
for (unsigned br = 1;; ++br)
@ -145,47 +184,7 @@ void Assembly::append(Assembly const& _a, int _deposit)
ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i)
{
for (AssemblyItem const& i: _i)
switch (i.type())
{
case Operation:
_out << " " << instructionInfo((Instruction)(byte)i.data()).name;
break;
case Push:
_out << " PUSH" << i.data();
break;
case PushString:
_out << " PUSH'[" << hex << (unsigned)i.data() << "]";
break;
case PushTag:
_out << " PUSH[tag" << i.data() << "]";
break;
case Tag:
_out << " tag" << i.data() << ": JUMPDEST";
break;
case PushData:
_out << " PUSH*[" << hex << (unsigned)i.data() << "]";
break;
case PushSub:
_out << " PUSHs[" << hex << h256(i.data()).abridged() << "]";
break;
case PushSubSize:
_out << " PUSHss[" << hex << h256(i.data()).abridged() << "]";
break;
case PushProgramSize:
_out << " PUSHSIZE";
break;
case NoOptimizeBegin:
_out << " DoNotOptimze{{";
break;
case NoOptimizeEnd:
_out << " DoNotOptimze}}";
break;
case UndefinedItem:
_out << " ???";
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}
_out << i;
return _out;
}
@ -219,7 +218,7 @@ ostream& Assembly::stream(ostream& _out, string const& _prefix, StringMap const&
switch (i.m_type)
{
case Operation:
_out << " " << instructionInfo((Instruction)(byte)i.m_data).name << "\t" << i.getJumpTypeAsString();
_out << " " << instructionInfo(i.instruction()).name << "\t" << i.getJumpTypeAsString();
break;
case Push:
_out << " PUSH " << i.m_data;
@ -245,12 +244,6 @@ ostream& Assembly::stream(ostream& _out, string const& _prefix, StringMap const&
case PushData:
_out << " PUSH [" << hex << (unsigned)i.m_data << "]";
break;
case NoOptimizeBegin:
_out << "DoNotOptimze{{";
break;
case NoOptimizeEnd:
_out << "DoNotOptimze}}";
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}
@ -384,7 +377,7 @@ Assembly& Assembly::optimise(bool _enable)
{
if (m[0].type() != Operation)
return m.toVector();
Instruction instr = Instruction(byte(m[0].data()));
Instruction instr = m[0].instruction();
if (Instruction::DUP1 <= instr && instr <= Instruction::DUP16)
return {};
InstructionInfo info = instructionInfo(instr);
@ -424,12 +417,6 @@ Assembly& Assembly::optimise(bool _enable)
count = 0;
for (unsigned i = 0; i < m_items.size(); ++i)
{
if (m_items[i].type() == NoOptimizeBegin)
{
while (i < m_items.size() && m_items[i].type() != NoOptimizeEnd)
++i;
continue;
}
for (auto const& r: rules)
{
auto vr = AssemblyItemsConstRef(&m_items).cropped(i, r.first.size());
@ -459,13 +446,11 @@ Assembly& Assembly::optimise(bool _enable)
}
}
}
if (m_items[i].type() == Operation && m_items[i].data() == (byte)Instruction::JUMP)
if (m_items[i].type() == Operation && m_items[i].instruction() == Instruction::JUMP)
{
bool o = false;
while (m_items.size() > i + 1 && m_items[i + 1].type() != Tag)
{
if (m_items[i + 1].type() == NoOptimizeBegin)
break;
m_items.erase(m_items.begin() + i + 1);
o = true;
}
@ -490,7 +475,7 @@ Assembly& Assembly::optimise(bool _enable)
{
auto t = *tags.begin();
unsigned i = t.second;
if (i && m_items[i - 1].type() == Operation && m_items[i - 1].data() == (byte)Instruction::JUMP)
if (i && m_items[i - 1].type() == Operation && m_items[i - 1].instruction() == Instruction::JUMP)
while (i < m_items.size() && (m_items[i].type() != Tag || tags.count(m_items[i].data())))
{
if (m_items[i].type() == Tag && tags.count(m_items[i].data()))
@ -599,9 +584,6 @@ bytes Assembly::assemble() const
tagPos[(unsigned)i.m_data] = ret.size();
ret.push_back((byte)Instruction::JUMPDEST);
break;
case NoOptimizeBegin:
case NoOptimizeEnd:
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}

11
libevmcore/Assembly.h

@ -34,7 +34,7 @@ namespace dev
namespace eth
{
enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, PushProgramSize, Tag, PushData, NoOptimizeBegin, NoOptimizeEnd };
enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, PushProgramSize, Tag, PushData };
class Assembly;
@ -53,7 +53,13 @@ public:
AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); }
AssemblyItemType type() const { return m_type; }
u256 data() const { return m_data; }
u256 const& data() const { return m_data; }
/// @returns the instruction of this item (only valid if type() == Operation)
Instruction instruction() const { return Instruction(byte(m_data)); }
/// @returns true iff the type and data of the items are equal.
bool operator==(AssemblyItem const& _other) const { return m_type == _other.m_type && m_data == _other.m_data; }
bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); }
/// @returns an upper bound for the number of bytes required by this item, assuming that
/// the value of a jump tag takes @a _addressLength bytes.
@ -78,6 +84,7 @@ private:
using AssemblyItems = std::vector<AssemblyItem>;
using AssemblyItemsConstRef = vector_ref<AssemblyItem const>;
std::ostream& operator<<(std::ostream& _out, AssemblyItem const& _item);
std::ostream& operator<<(std::ostream& _out, AssemblyItemsConstRef _i);
inline std::ostream& operator<<(std::ostream& _out, AssemblyItems const& _i) { return operator<<(_out, AssemblyItemsConstRef(&_i)); }

Loading…
Cancel
Save