diff options
author | Gav Wood <i@gavwood.com> | 2014-07-27 19:09:36 +0800 |
---|---|---|
committer | Gav Wood <i@gavwood.com> | 2014-07-27 19:09:36 +0800 |
commit | ed0209fefc50ab59b43b7f781410699c49445aab (patch) | |
tree | f82f1e4fee307efb67a16d9fb82e37c78e16b5b1 /Assembly.cpp | |
parent | 510abc0997c248a1a767ceade6749f426ae3a968 (diff) | |
download | dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.tar dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.tar.gz dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.tar.bz2 dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.tar.lz dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.tar.xz dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.tar.zst dexon-solidity-ed0209fefc50ab59b43b7f781410699c49445aab.zip |
Updates to assembler - see the sub-codes.
Diffstat (limited to 'Assembly.cpp')
-rw-r--r-- | Assembly.cpp | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/Assembly.cpp b/Assembly.cpp index 3abdf66f..78552f3c 100644 --- a/Assembly.cpp +++ b/Assembly.cpp @@ -32,7 +32,7 @@ int AssemblyItem::deposit() const { case Operation: return c_instructionInfo.at((Instruction)(byte)m_data).ret - c_instructionInfo.at((Instruction)(byte)m_data).args; - case Push: case PushString: case PushTag: case PushData: + case Push: case PushString: case PushTag: case PushData: case PushSub: case PushSubSize: return 1; case Tag: return 0; @@ -61,8 +61,12 @@ unsigned Assembly::bytesRequired() const case Push: ret += 1 + max<unsigned>(1, eth::bytesRequired(i.m_data)); break; + case PushSubSize: + ret += 4; // worst case: a 16MB program + break; case PushTag: case PushData: + case PushSub: ret += 1 + br; case Tag:; default:; @@ -87,6 +91,8 @@ void Assembly::append(Assembly const& _a) m_data.insert(i); for (auto const& i: _a.m_strings) m_strings.insert(i); + for (auto const& i: _a.m_subs) + m_subs.insert(i); assert(!_a.m_baseDeposit); assert(!_a.m_totalDeposit); @@ -127,6 +133,12 @@ ostream& eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) 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 UndefinedItem: _out << " ???"; default:; @@ -134,38 +146,50 @@ ostream& eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) return _out; } -ostream& Assembly::streamOut(ostream& _out) const +ostream& Assembly::streamOut(ostream& _out, string const& _prefix) const { - _out << ".code:" << endl; + _out << _prefix << ".code:" << endl; for (AssemblyItem const& i: m_items) switch (i.m_type) { case Operation: - _out << " " << c_instructionInfo.at((Instruction)(byte)i.m_data).name << endl; + _out << _prefix << " " << c_instructionInfo.at((Instruction)(byte)i.m_data).name << endl; break; case Push: - _out << " PUSH " << i.m_data << endl; + _out << _prefix << " PUSH " << i.m_data << endl; break; case PushString: - _out << " PUSH \"" << m_strings.at((h256)i.m_data) << "\"" << endl; + _out << _prefix << " PUSH \"" << m_strings.at((h256)i.m_data) << "\"" << endl; break; case PushTag: - _out << " PUSH [tag" << i.m_data << "]" << endl; + _out << _prefix << " PUSH [tag" << i.m_data << "]" << endl; + break; + case PushSub: + _out << _prefix << " PUSH [$" << h256(i.m_data).abridged() << "]" << endl; + break; + case PushSubSize: + _out << _prefix << " PUSH #[$" << h256(i.m_data).abridged() << "]" << endl; break; case Tag: - _out << "tag" << i.m_data << ": " << endl; + _out << _prefix << "tag" << i.m_data << ": " << endl; break; case PushData: - _out << " PUSH [" << hex << (unsigned)i.m_data << "]" << endl; + _out << _prefix << " PUSH [" << hex << (unsigned)i.m_data << "]" << endl; break; default:; } - if (m_data.size()) + if (m_data.size() || m_subs.size()) { - _out << ".data:" << endl; + _out << _prefix << ".data:" << endl; for (auto const& i: m_data) - _out << " " << hex << (unsigned)(u256)i.first << ": " << toHex(i.second) << endl; + if (!m_subs.count(i.first)) + _out << _prefix << " " << hex << (unsigned)(u256)i.first << ": " << toHex(i.second) << endl; + for (auto const& i: m_subs) + { + _out << _prefix << " " << hex << (unsigned)(u256)i.first << ": " << endl; + i.second.streamOut(_out, _prefix + " "); + } } return _out; } @@ -195,8 +219,10 @@ inline bool matches(AssemblyItemsConstRef _a, AssemblyItemsConstRef _b) struct OptimiserChannel: public LogChannel { static const char* name() { return "OPT"; } static const int verbosity = 12; }; #define copt eth::LogOutputStream<OptimiserChannel, true>() -void Assembly::optimise() +Assembly& Assembly::optimise(bool _enable) { + if (!_enable) + return *this; map<Instruction, function<u256(u256, u256)>> c_simple = { { Instruction::SUB, [](u256 a, u256 b)->u256{return a - b;} }, @@ -221,6 +247,8 @@ void Assembly::optimise() { { Push, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, { { PushTag, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, { { PushString, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, + { { PushSub, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, + { { PushSubSize, Instruction::POP }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, { { Push, PushTag, Instruction::JUMPI }, [](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].data()) return { m[1], Instruction::JUMP }; else return {}; } }, { { Instruction::NOT, Instruction::NOT }, [](AssemblyItemsConstRef) -> AssemblyItems { return {}; } }, }; @@ -309,6 +337,11 @@ void Assembly::optimise() } copt << total << " optimisations done."; + + for (auto& i: m_subs) + i.second.optimise(true); + + return *this; } bytes Assembly::assemble() const @@ -323,6 +356,9 @@ bytes Assembly::assemble() const unsigned bytesPerTag = eth::bytesRequired(totalBytes); byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag; + for (auto const& i: m_subs) + m_data[i.first] = i.second.assemble(); + for (AssemblyItem const& i: m_items) switch (i.m_type) { @@ -358,13 +394,23 @@ bytes Assembly::assemble() const ret.resize(ret.size() + bytesPerTag); break; } - case PushData: + case PushData: case PushSub: { ret.push_back(tagPush); dataRef.insert(make_pair((h256)i.m_data, ret.size())); ret.resize(ret.size() + bytesPerTag); break; } + case PushSubSize: + { + auto s = m_data[i.m_data].size(); + byte b = max<unsigned>(1, eth::bytesRequired(s)); + ret.push_back((byte)Instruction::PUSH1 - 1 + b); + ret.resize(ret.size() + b); + bytesRef byr(&ret.back() + 1 - b, b); + toBigEndian(s, byr); + break; + } case Tag: tagPos[(unsigned)i.m_data] = ret.size(); break; |