Browse Source

initial output for asm-json flag.

Conflicts:
	libevmcore/Assembly.cpp
cl-refactor
Liana Husikyan 10 years ago
parent
commit
1305502fc9
  1. 162
      libevmcore/Assembly.cpp
  2. 6
      libevmcore/Assembly.h
  3. 1
      libevmcore/CMakeLists.txt
  4. 4
      solc/CommandLineInterface.cpp

162
libevmcore/Assembly.cpp

@ -24,6 +24,7 @@
#include <libdevcore/Log.h>
#include <libevmcore/CommonSubexpressionEliminator.h>
#include <libevmcore/ControlFlowGraph.h>
#include <json/json.h>
using namespace std;
using namespace dev;
@ -101,9 +102,8 @@ string Assembly::getLocationFromSources(StringMap const& _sourceCodes, SourceLoc
return move(cut);
}
ostream& Assembly::stream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes, bool _inJsonFormat) const
ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
{
(void)_inJsonFormat;
_out << _prefix << ".code:" << endl;
for (AssemblyItem const& i: m_items)
{
@ -158,6 +158,164 @@ ostream& Assembly::stream(ostream& _out, string const& _prefix, StringMap const&
return _out;
}
ostream& Assembly::streamAsmJson(ostream& _out, string const& _prefix, StringMap const& _sourceCodes, bool _inJsonFormat) const
{
Json::Value root;
string currentArrayName = ".code";
std::vector<Json::Value> currentCollection;
for (AssemblyItem const& i: m_items)
{
//todo check and remove where location.isEmpty()
switch (i.type())
{
case Operation:
{
Json::Value op;
op["name"] = instructionInfo(i.instruction()).name;
op["jumpType"] = i.getJumpTypeAsString();
op["locationX"] = i.getLocation().start;
op["locationY"] = i.getLocation().end;
currentCollection.push_back(op);
//_out << " " << instructionInfo(i.instruction()).name << "\t" << i.getJumpTypeAsString();
}
break;
case Push:
{
Json::Value pushitem;
pushitem["name"] = "PUSH";
pushitem["value"] = string(i.data());
pushitem["locationX"] = boost::lexical_cast<std::string>(i.getLocation().start);
pushitem["locationY"] = boost::lexical_cast<std::string>(i.getLocation().end);
currentCollection.push_back(pushitem);
//_out << " PUSH " << i.data();
}
break;
case PushString:
{
Json::Value pushString;
pushString["name"] = "PUSH tag";
pushString["value"] = m_strings.at((h256)i.data());
pushString["locationX"] = i.getLocation().start;
pushString["locationY"] = i.getLocation().end;
currentCollection.push_back(pushString);
//_out << " PUSH \"" << m_strings.at((h256)i.data()) << "\"";
}
break;
case PushTag:
{
Json::Value pushTag;
pushTag["name"] = "PUSH [tag]";
pushTag["value"] = string(i.data());
pushTag["locationX"] = boost::lexical_cast<std::string>(i.getLocation().start);
pushTag["locationY"] = boost::lexical_cast<std::string>(i.getLocation().end);
currentCollection.push_back(pushTag);
}
//_out << " PUSH [tag" << i.data() << "]";
break;
case PushSub:
{
Json::Value pushSub;
pushSub["name"] = "PUSH [$]";
pushSub["value"] = h256(i.data()).abridged() ;
pushSub["locationX"] = boost::lexical_cast<std::string>(i.getLocation().start);
pushSub["locationY"] = boost::lexical_cast<std::string>(i.getLocation().end);
currentCollection.push_back(pushSub);
}
//_out << " PUSH [$" << h256(i.data()).abridged() << "]";
break;
case PushSubSize:
{
Json::Value pushSubSize;
pushSubSize["name"] = "PUSH #[$]";
pushSubSize["value"] = h256(i.data()).abridged();
pushSubSize["locationX"] = boost::lexical_cast<std::string>(i.getLocation().start);
pushSubSize["locationY"] = boost::lexical_cast<std::string>(i.getLocation().end);
currentCollection.push_back(pushSubSize);
}
//_out << " PUSH #[$" << h256(i.data()).abridged() << "]";
break;
case PushProgramSize:
{
Json::Value pushSize;
pushSize["name"] = "PUSHSIZE";
pushSize["locationX"] = boost::lexical_cast<std::string>(i.getLocation().start);
pushSize["locationY"] = boost::lexical_cast<std::string>(i.getLocation().end);
currentCollection.push_back(pushSize);
}
//_out << " PUSHSIZE";
break;
case Tag:
{
Json::Value collection(Json::arrayValue);
for(auto it: currentCollection)
collection.append(it);
currentCollection.clear();
root[currentArrayName] = collection;
currentArrayName = "tag" + string(i.data());
}
//_out << "tag" << i.data() << ": " << endl << _prefix << " JUMPDEST";
break;
case PushData:
{
Json::Value pushData;
pushData["name"] = "PUSH hex";
std::stringstream hexStr;
hexStr << hex << (unsigned)i.data();
pushData["value"] = hexStr.str();
pushData["locationX"] = boost::lexical_cast<std::string>(i.getLocation().start);
pushData["locationY"] = boost::lexical_cast<std::string>(i.getLocation().end);
currentCollection.push_back(pushData);
}
//_out << " PUSH [" << hex << (unsigned)i.data() << "]";
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}
}
//todo check if the last was tag
Json::Value collection(Json::arrayValue);
for(auto it: currentCollection)
collection.append(it);
root[currentArrayName] = collection;
if (!m_data.empty() || !m_subs.empty())
{
Json::Value dataCollection(Json::arrayValue);
for (auto const& i: m_data)
if (u256(i.first) >= m_subs.size())
{
std::stringstream hexStr;
hexStr << _prefix << hex << (unsigned)(u256)i.first << ": " << toHex(i.second);
Json::Value data;
data["value"] = hexStr.str();
dataCollection.append(data);
}
root[_prefix + ".data"] = collection;
for (size_t i = 0; i < m_subs.size(); ++i)
{
std::stringstream hexStr;
hexStr << _prefix << hex << i << ": ";
//_out << _prefix << " " << hex << i << ": " << endl;
//todo check recursion
m_subs[i].stream(_out, _prefix + " ", _sourceCodes, _inJsonFormat);
}
}
_out << root;
return _out;
}
ostream& Assembly::stream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes, bool _inJsonFormat) const
{
if (!_inJsonFormat)
return streamAsm(_out, _prefix, _sourceCodes);
else
return streamAsmJson(_out, _prefix, _sourceCodes, _inJsonFormat);
}
AssemblyItem const& Assembly::append(AssemblyItem const& _i)
{
m_deposit += _i.deposit();

6
libevmcore/Assembly.h

@ -93,6 +93,10 @@ protected:
void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
unsigned bytesRequired() const;
private:
std::ostream& streamAsmJson(std::ostream& _out, const std::string &_prefix, const StringMap &_sourceCodes, bool _inJsonFormat) const;
std::ostream& streamAsm(std::ostream& _out, std::string const& _prefix, StringMap const& _sourceCodes) const;
protected:
unsigned m_usedTags = 0;
AssemblyItems m_items;
mutable std::map<h256, bytes> m_data;
@ -104,8 +108,10 @@ protected:
int m_totalDeposit = 0;
SourceLocation m_currentSourceLocation;
};
inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)
{
_a.stream(_out);

1
libevmcore/CMakeLists.txt

@ -11,6 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})

4
solc/CommandLineInterface.cpp

@ -419,9 +419,9 @@ void CommandLineInterface::actOnInput()
cout << endl << "======= " << contract << " =======" << endl;
// do we need EVM assembly?
if (m_args.count(g_argAsmStr))
if (m_args.count(g_argAsmStr) || m_args.count(g_argAsmJsonStr))
{
auto choice = m_args[g_argAsmStr].as<OutputType>();
auto choice = m_args.count(g_argAsmStr) ? m_args[g_argAsmStr].as<OutputType>() : m_args[g_argAsmJsonStr].as<OutputType>();
if (outputToStdout(choice))
{
cout << "EVM assembly:" << endl;

Loading…
Cancel
Save