1818
1919#include < libevmasm/Ethdebug.h>
2020
21+ #include < libevmasm/EthdebugSchema.h>
22+
2123#include < range/v3/algorithm/any_of.hpp>
2224
2325using namespace solidity ;
@@ -27,14 +29,66 @@ using namespace solidity::evmasm::ethdebug;
2729namespace
2830{
2931
30- std::vector<Json> codeSectionInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned _sourceId, size_t const _codeSectionIndex)
32+ schema::program::Instruction::Operation instructionOperation (Assembly const & _assembly, LinkerObject const & _linkerObject, size_t const _start, size_t const _end)
33+ {
34+ solAssert (_end <= _linkerObject.bytecode .size ());
35+ solAssert (_start < _end);
36+ schema::program::Instruction::Operation operation;
37+ operation.mnemonic = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [_start]), _assembly.evmVersion ()).name ;
38+ static size_t constexpr instructionSize = 1 ;
39+ if (_start + instructionSize < _end)
40+ {
41+ bytes const argumentData (
42+ _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(_start) + instructionSize,
43+ _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(_end)
44+ );
45+ solAssert (!argumentData.empty ());
46+ operation.arguments = {{schema::data::HexValue{argumentData}}};
47+ }
48+ return operation;
49+ }
50+
51+ schema::materials::SourceRange::Range locationRange (langutil::SourceLocation const & _location)
52+ {
53+ return {
54+ .length = schema::data::Unsigned{_location.end - _location.start },
55+ .offset = schema::data::Unsigned{_location.start }
56+ };
57+ }
58+
59+ schema::materials::Reference sourceReference (unsigned _sourceID)
60+ {
61+ return {
62+ .id = schema::materials::ID{_sourceID},
63+ .type = std::nullopt
64+ };
65+ }
66+
67+ std::optional<schema::program::Context> instructionContext (Assembly::CodeSection const & _codeSection, size_t _assemblyItemIndex, unsigned _sourceID)
68+ {
69+ solAssert (_assemblyItemIndex < _codeSection.items .size ());
70+ langutil::SourceLocation const & location = _codeSection.items .at (_assemblyItemIndex).location ();
71+ if (!location.isValid ())
72+ return std::nullopt ;
73+
74+ return schema::program::Context{
75+ schema::materials::SourceRange{
76+ .source = sourceReference (_sourceID),
77+ .range = locationRange (location)
78+ },
79+ std::nullopt ,
80+ std::nullopt
81+ };
82+ }
83+
84+ std::vector<schema::program::Instruction> codeSectionInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned const _sourceID, size_t const _codeSectionIndex)
3185{
3286 solAssert (_codeSectionIndex < _linkerObject.codeSectionLocations .size ());
3387 solAssert (_codeSectionIndex < _assembly.codeSections ().size ());
3488 auto const & locations = _linkerObject.codeSectionLocations [_codeSectionIndex];
3589 auto const & codeSection = _assembly.codeSections ().at (_codeSectionIndex);
3690
37- std::vector<Json > instructions;
91+ std::vector<schema::program::Instruction > instructions;
3892 instructions.reserve (codeSection.items .size ());
3993
4094 bool const codeSectionContainsVerbatim = ranges::any_of (
@@ -52,72 +106,47 @@ std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObjec
52106 if (start == end)
53107 continue ;
54108
55- size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex ;
56- solAssert (end <= _linkerObject.bytecode .size ());
57- solAssert (start < end);
58- solAssert (assemblyItemIndex < codeSection.items .size ());
59- Json operation = Json::object ();
60- operation[" mnemonic" ] = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [start]), _assembly.evmVersion ()).name ;
61- static size_t constexpr instructionSize = 1 ;
62- if (start + instructionSize < end)
63- {
64- bytes const argumentData (
65- _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(start) + instructionSize,
66- _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(end)
67- );
68- solAssert (!argumentData.empty ());
69- operation[" arguments" ] = Json::array ({util::toHex (argumentData, util::HexPrefix::Add)});
70- }
71- langutil::SourceLocation const & location = codeSection.items .at (assemblyItemIndex).location ();
72- instructions.emplace_back (Json{
73- { " offset" , start },
74- {" operation" , operation },
75- {
76- " context" , {
77- " code" , {
78- " source" , {
79- { " id" , static_cast <int >(_sourceId) },
80- },
81- " range" , {
82- { " offset" , location.start },
83- { " length" , location.end - location.start }
84- }
85- }
86- }
87- }
109+ instructions.emplace_back (schema::program::Instruction{
110+ .offset = schema::data::Unsigned{start},
111+ .operation = instructionOperation (_assembly, _linkerObject, start, end),
112+ .context = instructionContext (codeSection, currentInstruction.assemblyItemIndex , _sourceID)
88113 });
89114 }
90115
91116 return instructions;
92117}
93118
94- Json programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned _sourceId )
119+ std::vector<schema::program::Instruction> programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned const _sourceID )
95120{
96121 auto const numCodeSections = _assembly.codeSections ().size ();
97122 solAssert (numCodeSections == _linkerObject.codeSectionLocations .size ());
98123
99- std::vector<Json > instructionInfo;
124+ std::vector<schema::program::Instruction > instructionInfo;
100125 for (size_t codeSectionIndex = 0 ; codeSectionIndex < numCodeSections; ++codeSectionIndex)
101- instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceId , codeSectionIndex);
126+ instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceID , codeSectionIndex);
102127 return instructionInfo;
103128}
104129
105130} // anonymous namespace
106131
107- Json ethdebug::program (std::string_view _name, unsigned _sourceId , Assembly const & _assembly, LinkerObject const & _linkerObject)
132+ Json ethdebug::program (std::string_view _name, unsigned _sourceID , Assembly const & _assembly, LinkerObject const & _linkerObject)
108133{
109- Json result = Json::object ();
110- result[" contract" ] = Json::object ();
111- result[" contract" ][" name" ] = _name;
112- result[" contract" ][" definition" ] = Json::object ();
113- result[" contract" ][" definition" ][" source" ] = Json::object ();
114- result[" contract" ][" definition" ][" source" ][" id" ] = _sourceId;
115- if (_assembly)
116- {
117- result[" environment" ] = _assembly->isCreation () ? " create" : " call" ;
118- result[" instructions" ] = programInstructions (*_assembly, _linkerObject, _sourceId);
119- }
120- return result;
134+ return schema::Program{
135+ .compilation = std::nullopt ,
136+ .contract = {
137+ .name = std::string{_name},
138+ .definition = {
139+ .source = {
140+ .id = {_sourceID},
141+ .type = std::nullopt
142+ },
143+ .range = std::nullopt
144+ }
145+ },
146+ .environment = _assembly.isCreation () ? schema::Program::Environment::CREATE : schema::Program::Environment::CALL,
147+ .context = std::nullopt ,
148+ .instructions = programInstructions (_assembly, _linkerObject, _sourceID)
149+ };
121150}
122151
123152Json ethdebug::resources (std::vector<std::string> const & _sources, std::string const & _version)
0 commit comments