Skip to content

Commit 6502a4b

Browse files
committed
libevmasm: refactor asm-json export & add support for source list.
1 parent 724af73 commit 6502a4b

File tree

4 files changed

+173
-109
lines changed

4 files changed

+173
-109
lines changed

libevmasm/Assembly.cpp

Lines changed: 116 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,21 @@ string Assembly::assemblyString(
222222
return tmp.str();
223223
}
224224

225-
Json::Value Assembly::createJsonValue(string _name, int _source, int _begin, int _end, string _value, string _jumpType)
225+
Json::Value Assembly::createJsonValue(string const& _name, AssemblyItem const& _item, std::string const& _value)
226226
{
227227
Json::Value value{Json::objectValue};
228228
value["name"] = _name;
229-
value["source"] = _source;
230-
value["begin"] = _begin;
231-
value["end"] = _end;
229+
value["begin"] = _item.location().start;
230+
value["end"] = _item.location().end;
231+
if (_item.m_modifierDepth != 0)
232+
value["modifierDepth"] = static_cast<int>(_item.m_modifierDepth);
232233
if (!_value.empty())
233234
value["value"] = _value;
234-
if (!_jumpType.empty())
235-
value["jumpType"] = _jumpType;
235+
if (!_item.getJumpTypeAsString().empty())
236+
{
237+
assertThrow(_name == "JUMP" && value.isMember("value") == false, AssemblyException, "");
238+
value["value"] = _item.getJumpTypeAsString();
239+
}
236240
return value;
237241
}
238242

@@ -242,13 +246,101 @@ string Assembly::toStringInHex(u256 _value)
242246
hexStr << std::uppercase << hex << _value;
243247
return hexStr.str();
244248
}
249+
vector<Json::Value> Assembly::assemblyItemAsJSON(AssemblyItem const& _item) const
250+
{
251+
vector<Json::Value> result;
245252

246-
Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices) const
253+
switch (_item.type())
254+
{
255+
case Operation:
256+
result.emplace_back(createJsonValue(
257+
instructionInfo(_item.instruction()).name,
258+
_item));
259+
break;
260+
case Push:
261+
result.emplace_back(createJsonValue(
262+
"PUSH",
263+
_item,
264+
toStringInHex(_item.data())));
265+
break;
266+
case PushTag:
267+
if (_item.data() == 0)
268+
result.emplace_back(createJsonValue(
269+
"PUSH [ErrorTag]",
270+
_item));
271+
else
272+
result.emplace_back(createJsonValue(
273+
"PUSH [tag]",
274+
_item, toString(_item.data())));
275+
break;
276+
case PushSub:
277+
result.emplace_back(createJsonValue(
278+
"PUSH [$]",
279+
_item,
280+
toString(h256(_item.data()))
281+
));
282+
break;
283+
case PushSubSize:
284+
result.emplace_back(createJsonValue(
285+
"PUSH #[$]",_item, toString(h256(_item.data()))));
286+
break;
287+
case PushProgramSize:
288+
result.emplace_back(createJsonValue(
289+
"PUSHSIZE", _item));
290+
break;
291+
case PushLibraryAddress:
292+
result.emplace_back(createJsonValue(
293+
"PUSHLIB",
294+
_item,
295+
m_libraries.at(h256(_item.data()))));
296+
break;
297+
case PushDeployTimeAddress:
298+
result.emplace_back(createJsonValue(
299+
"PUSHDEPLOYADDRESS", _item));
300+
break;
301+
case PushImmutable:
302+
result.emplace_back(createJsonValue(
303+
"PUSHIMMUTABLE",
304+
_item,
305+
m_immutables.at(h256(_item.data()))));
306+
break;
307+
case AssignImmutable:
308+
result.emplace_back(createJsonValue(
309+
"ASSIGNIMMUTABLE",
310+
_item,
311+
m_immutables.at(h256(_item.data()))));
312+
break;
313+
case Tag:
314+
result.emplace_back(createJsonValue(
315+
"tag",
316+
_item,
317+
toString(_item.data())));
318+
result.emplace_back(createJsonValue(
319+
"JUMPDEST", _item));
320+
break;
321+
case PushData:
322+
result.emplace_back(createJsonValue(
323+
"PUSH data",
324+
_item,
325+
toStringInHex(_item.data())));
326+
break;
327+
case VerbatimBytecode:
328+
result.emplace_back(createJsonValue(
329+
"VERBATIM",
330+
_item,
331+
util::toHex(_item.verbatimData())));
332+
break;
333+
default:
334+
assertThrow(false, InvalidOpcode, "");
335+
}
336+
return result;
337+
}
338+
339+
Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices, bool _includeSourceList) const
247340
{
248341
Json::Value root;
249342
root[".code"] = Json::arrayValue;
250-
251-
Json::Value& collection = root[".code"];
343+
Json::Value& code = root[".code"];
252344
for (AssemblyItem const& i: m_items)
253345
{
254346
int sourceIndex = -1;
@@ -259,86 +351,22 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices)
259351
sourceIndex = static_cast<int>(iter->second);
260352
}
261353

262-
switch (i.type())
354+
for (Json::Value& item: assemblyItemAsJSON(i))
263355
{
264-
case Operation:
265-
collection.append(
266-
createJsonValue(
267-
instructionInfo(i.instruction()).name,
268-
sourceIndex,
269-
i.location().start,
270-
i.location().end,
271-
i.getJumpTypeAsString())
272-
);
273-
break;
274-
case Push:
275-
collection.append(
276-
createJsonValue("PUSH", sourceIndex, i.location().start, i.location().end, toStringInHex(i.data()), i.getJumpTypeAsString()));
277-
break;
278-
case PushTag:
279-
if (i.data() == 0)
280-
collection.append(
281-
createJsonValue("PUSH [ErrorTag]", sourceIndex, i.location().start, i.location().end, ""));
282-
else
283-
collection.append(
284-
createJsonValue("PUSH [tag]", sourceIndex, i.location().start, i.location().end, toString(i.data())));
285-
break;
286-
case PushSub:
287-
collection.append(
288-
createJsonValue("PUSH [$]", sourceIndex, i.location().start, i.location().end, toString(h256(i.data()))));
289-
break;
290-
case PushSubSize:
291-
collection.append(
292-
createJsonValue("PUSH #[$]", sourceIndex, i.location().start, i.location().end, toString(h256(i.data()))));
293-
break;
294-
case PushProgramSize:
295-
collection.append(
296-
createJsonValue("PUSHSIZE", sourceIndex, i.location().start, i.location().end));
297-
break;
298-
case PushLibraryAddress:
299-
collection.append(
300-
createJsonValue("PUSHLIB", sourceIndex, i.location().start, i.location().end, m_libraries.at(h256(i.data())))
301-
);
302-
break;
303-
case PushDeployTimeAddress:
304-
collection.append(
305-
createJsonValue("PUSHDEPLOYADDRESS", sourceIndex, i.location().start, i.location().end)
306-
);
307-
break;
308-
case PushImmutable:
309-
collection.append(createJsonValue(
310-
"PUSHIMMUTABLE",
311-
sourceIndex,
312-
i.location().start,
313-
i.location().end,
314-
m_immutables.at(h256(i.data()))
315-
));
316-
break;
317-
case AssignImmutable:
318-
collection.append(createJsonValue(
319-
"ASSIGNIMMUTABLE",
320-
sourceIndex,
321-
i.location().start,
322-
i.location().end,
323-
m_immutables.at(h256(i.data()))
324-
));
325-
break;
326-
case Tag:
327-
collection.append(
328-
createJsonValue("tag", sourceIndex, i.location().start, i.location().end, toString(i.data())));
329-
collection.append(
330-
createJsonValue("JUMPDEST", sourceIndex, i.location().start, i.location().end));
331-
break;
332-
case PushData:
333-
collection.append(createJsonValue("PUSH data", sourceIndex, i.location().start, i.location().end, toStringInHex(i.data())));
334-
break;
335-
case VerbatimBytecode:
336-
collection.append(createJsonValue("VERBATIM", sourceIndex, i.location().start, i.location().end, util::toHex(i.verbatimData())));
337-
break;
338-
default:
339-
assertThrow(false, InvalidOpcode, "");
356+
item["source"] = sourceIndex;
357+
code.append(item);
340358
}
341359
}
360+
if (_includeSourceList)
361+
{
362+
root["sourceList"] = Json::arrayValue;
363+
Json::Value& sourceList = root["sourceList"];
364+
vector<string> sources(_sourceIndices.size());
365+
for (auto const& item: _sourceIndices)
366+
sources[item.second] = item.first;
367+
for (auto const& item: sources)
368+
sourceList.append(item);
369+
}
342370

343371
if (!m_data.empty() || !m_subs.empty())
344372
{
@@ -352,11 +380,11 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices)
352380
{
353381
std::stringstream hexStr;
354382
hexStr << hex << i;
355-
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices);
383+
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, false);
356384
}
357385
}
358386

359-
if (m_auxiliaryData.size() > 0)
387+
if (!m_auxiliaryData.empty())
360388
root[".auxdata"] = util::toHex(m_auxiliaryData);
361389

362390
return root;

libevmasm/Assembly.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <sstream>
4040
#include <memory>
4141
#include <map>
42+
#include <utility>
4243

4344
namespace solidity::evmasm
4445
{
@@ -146,9 +147,7 @@ class Assembly
146147
) const;
147148

148149
/// Create a JSON representation of the assembly.
149-
Json::Value assemblyJSON(
150-
std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>()
151-
) const;
150+
Json::Value assemblyJSON(std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>(), bool _includeSourceList = true) const;
152151

153152
/// Mark this assembly as invalid. Calling ``assemble`` on it will throw.
154153
void markAsInvalid() { m_invalid = true; }
@@ -166,15 +165,10 @@ class Assembly
166165

167166
unsigned codeSize(unsigned subTagSize) const;
168167

168+
std::vector<Json::Value> assemblyItemAsJSON(AssemblyItem const& _item) const;
169+
169170
private:
170-
static Json::Value createJsonValue(
171-
std::string _name,
172-
int _source,
173-
int _begin,
174-
int _end,
175-
std::string _value = std::string(),
176-
std::string _jumpType = std::string()
177-
);
171+
static Json::Value createJsonValue(std::string const& _name, AssemblyItem const& _item, std::string const& _value = "");
178172
static std::string toStringInHex(u256 _value);
179173

180174
bool m_invalid = false;
@@ -222,6 +216,7 @@ class Assembly
222216
std::string m_name;
223217

224218
langutil::SourceLocation m_currentSourceLocation;
219+
225220
public:
226221
size_t m_currentModifierDepth = 0;
227222
};

test/cmdlineTests/asm_json/output

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1582,5 +1582,10 @@ EVM assembly:
15821582
}
15831583
]
15841584
}
1585-
}
1585+
},
1586+
"sourceList":
1587+
[
1588+
"asm_json/input.sol",
1589+
"#utility.yul"
1590+
]
15861591
}

0 commit comments

Comments
 (0)