aboutsummaryrefslogtreecommitdiffstats
path: root/libevmasm/Assembly.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libevmasm/Assembly.cpp')
-rw-r--r--libevmasm/Assembly.cpp170
1 files changed, 101 insertions, 69 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index a9ca24dc..597fdae1 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -55,28 +55,15 @@ void Assembly::append(Assembly const& _a)
m_subs += _a.m_subs;
for (auto const& lib: _a.m_libraries)
m_libraries.insert(lib);
-
- assert(!_a.m_baseDeposit);
- assert(!_a.m_totalDeposit);
}
void Assembly::append(Assembly const& _a, int _deposit)
{
- if (_deposit > _a.m_deposit)
- BOOST_THROW_EXCEPTION(InvalidDeposit());
- else
- {
- append(_a);
- while (_deposit++ < _a.m_deposit)
- append(Instruction::POP);
- }
-}
+ assertThrow(_deposit <= _a.m_deposit, InvalidDeposit, "");
-string Assembly::out() const
-{
- stringstream ret;
- stream(ret);
- return ret.str();
+ append(_a);
+ while (_deposit++ < _a.m_deposit)
+ append(Instruction::POP);
}
unsigned Assembly::bytesRequired(unsigned subTagSize) const
@@ -94,7 +81,10 @@ unsigned Assembly::bytesRequired(unsigned subTagSize) const
}
}
-string Assembly::locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const
+namespace
+{
+
+string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location)
{
if (_location.isEmpty() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0)
return "";
@@ -115,71 +105,107 @@ string Assembly::locationFromSources(StringMap const& _sourceCodes, SourceLocati
return cut;
}
-ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
+class Functionalizer
{
- _out << _prefix << ".code:" << endl;
- for (AssemblyItem const& i: m_items)
+public:
+ Functionalizer (ostream& _out, string const& _prefix, StringMap const& _sourceCodes):
+ m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes)
+ {}
+
+ void feed(AssemblyItem const& _item)
{
- _out << _prefix;
- switch (i.type())
+ if (!_item.location().isEmpty() && _item.location() != m_location)
{
- case Operation:
- _out << " " << instructionInfo(i.instruction()).name << "\t" << i.getJumpTypeAsString();
- break;
- case Push:
- _out << " PUSH" << dec << max<unsigned>(1, dev::bytesRequired(i.data())) << " 0x" << hex << i.data();
- break;
- case PushString:
- _out << " PUSH \"" << m_strings.at((h256)i.data()) << "\"";
- break;
- case PushTag:
- if (i.data() == 0)
- _out << " PUSH [ErrorTag]";
- else
+ flush();
+ m_location = _item.location();
+ printLocation();
+ }
+ if (!(
+ _item.canBeFunctional() &&
+ _item.returnValues() <= 1 &&
+ _item.arguments() <= int(m_pending.size())
+ ))
+ {
+ flush();
+ m_out << m_prefix << (_item.type() == Tag ? "" : " ") << _item.toAssemblyText() << endl;
+ return;
+ }
+ string expression = _item.toAssemblyText();
+ if (_item.arguments() > 0)
+ {
+ expression += "(";
+ for (int i = 0; i < _item.arguments(); ++i)
{
- size_t subId = i.splitForeignPushTag().first;
- if (subId == size_t(-1))
- _out << " PUSH [tag" << dec << i.splitForeignPushTag().second << "]";
- else
- _out << " PUSH [tag" << dec << subId << ":" << i.splitForeignPushTag().second << "]";
+ expression += m_pending.back();
+ m_pending.pop_back();
+ if (i + 1 < _item.arguments())
+ expression += ", ";
}
- break;
- case PushSub:
- _out << " PUSH [$" << size_t(i.data()) << "]";
- break;
- case PushSubSize:
- _out << " PUSH #[$" << size_t(i.data()) << "]";
- break;
- case PushProgramSize:
- _out << " PUSHSIZE";
- break;
- case PushLibraryAddress:
- _out << " PUSHLIB \"" << m_libraries.at(h256(i.data())) << "\"";
- break;
- case Tag:
- _out << "tag" << dec << i.data() << ": " << endl << _prefix << " JUMPDEST";
- break;
- case PushData:
- _out << " PUSH [" << hex << (unsigned)i.data() << "]";
- break;
- default:
- BOOST_THROW_EXCEPTION(InvalidOpcode());
+ expression += ")";
}
- _out << "\t\t" << locationFromSources(_sourceCodes, i.location()) << endl;
+
+ m_pending.push_back(expression);
+ if (_item.returnValues() != 1)
+ flush();
+ }
+
+ void flush()
+ {
+ for (string const& expression: m_pending)
+ m_out << m_prefix << " " << expression << endl;
+ m_pending.clear();
}
+ void printLocation()
+ {
+ if (!m_location.sourceName && m_location.isEmpty())
+ return;
+ m_out << m_prefix << " /*";
+ if (m_location.sourceName)
+ m_out << " \"" + *m_location.sourceName + "\"";
+ if (!m_location.isEmpty())
+ m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end);
+ m_out << " " << locationFromSources(m_sourceCodes, m_location);
+ m_out << " */" << endl;
+ }
+
+private:
+ strings m_pending;
+ SourceLocation m_location;
+
+ ostream& m_out;
+ string const& m_prefix;
+ StringMap const& m_sourceCodes;
+};
+
+}
+
+ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
+{
+ Functionalizer f(_out, _prefix, _sourceCodes);
+
+ for (auto const& i: m_items)
+ f.feed(i);
+ f.flush();
+
if (!m_data.empty() || !m_subs.empty())
{
- _out << _prefix << ".data:" << endl;
+ _out << _prefix << "stop" << endl;
for (auto const& i: m_data)
if (u256(i.first) >= m_subs.size())
- _out << _prefix << " " << hex << (unsigned)(u256)i.first << ": " << dev::toHex(i.second) << endl;
+ _out << _prefix << "data_" << toHex(u256(i.first)) << " " << toHex(i.second) << endl;
+
for (size_t i = 0; i < m_subs.size(); ++i)
{
- _out << _prefix << " " << hex << i << ": " << endl;
- m_subs[i]->stream(_out, _prefix + " ", _sourceCodes);
+ _out << endl << _prefix << "sub_" << i << ": assembly {\n";
+ m_subs[i]->streamAsm(_out, _prefix + " ", _sourceCodes);
+ _out << _prefix << "}" << endl;
}
}
+
+ if (m_auxiliaryData.size() > 0)
+ _out << endl << _prefix << "auxdata: 0x" << toHex(m_auxiliaryData) << endl;
+
return _out;
}
@@ -279,8 +305,13 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true);
}
root[".data"] = data;
- _out << root;
}
+
+ if (m_auxiliaryData.size() > 0)
+ root[".auxdata"] = toHex(m_auxiliaryData);
+
+ _out << root;
+
return root;
}
@@ -297,6 +328,7 @@ Json::Value Assembly::stream(ostream& _out, string const& _prefix, StringMap con
AssemblyItem const& Assembly::append(AssemblyItem const& _i)
{
+ assertThrow(m_deposit >= 0, AssemblyException, "");
m_deposit += _i.deposit();
m_items.push_back(_i);
if (m_items.back().location().isEmpty() && !m_currentSourceLocation.isEmpty())
@@ -449,7 +481,7 @@ LinkerObject const& Assembly::assemble() const
switch (i.type())
{
case Operation:
- ret.bytecode.push_back((byte)i.data());
+ ret.bytecode.push_back((byte)i.instruction());
break;
case PushString:
{