From 1a0988e503cd551a8c31e62a30b7194fb3631d00 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 15 Mar 2022 15:25:51 -0500 Subject: [PATCH] libevmasm: refactor asm-json export & add support for source list. --- Changelog.md | 2 + libevmasm/Assembly.cpp | 150 +++++++++--------------------- libevmasm/Assembly.h | 15 +-- libevmasm/AssemblyItem.cpp | 51 ++++++++++ libevmasm/AssemblyItem.h | 7 ++ test/cmdlineTests/asm_json/output | 71 +++++++------- test/libevmasm/Assembler.cpp | 72 +++++++++++--- 7 files changed, 204 insertions(+), 164 deletions(-) diff --git a/Changelog.md b/Changelog.md index 32d76774a..33291c6bc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,9 +5,11 @@ Language Features: Compiler Features: * Peephole Optimizer: Remove operations without side effects before simple terminations. + * Assembly-Json: Export: Include source list in `sourceList` field. Bugfixes: +* Assembly-Json: Fix assembly json export to store jump types of operations in `jumpType` field instead of `value`. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 6d7b97cc4..43e06ef9b 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -222,123 +222,59 @@ string Assembly::assemblyString( return tmp.str(); } -Json::Value Assembly::createJsonValue(string _name, int _source, int _begin, int _end, string _value, string _jumpType) -{ - Json::Value value{Json::objectValue}; - value["name"] = _name; - value["source"] = _source; - value["begin"] = _begin; - value["end"] = _end; - if (!_value.empty()) - value["value"] = _value; - if (!_jumpType.empty()) - value["jumpType"] = _jumpType; - return value; -} - -string Assembly::toStringInHex(u256 _value) -{ - std::stringstream hexStr; - hexStr << std::uppercase << hex << _value; - return hexStr.str(); -} - -Json::Value Assembly::assemblyJSON(map const& _sourceIndices) const +Json::Value Assembly::assemblyJSON(map const& _sourceIndices, bool _includeSourceList) const { Json::Value root; root[".code"] = Json::arrayValue; - - Json::Value& collection = root[".code"]; - for (AssemblyItem const& i: m_items) + Json::Value& code = root[".code"]; + for (AssemblyItem const& item: m_items) { int sourceIndex = -1; - if (i.location().sourceName) + if (item.location().sourceName) { - auto iter = _sourceIndices.find(*i.location().sourceName); + auto iter = _sourceIndices.find(*item.location().sourceName); if (iter != _sourceIndices.end()) sourceIndex = static_cast(iter->second); } - switch (i.type()) + auto [name, data] = item.nameAndData(); + Json::Value jsonItem; + jsonItem["name"] = name; + jsonItem["begin"] = item.location().start; + jsonItem["end"] = item.location().end; + if (item.m_modifierDepth != 0) + jsonItem["modifierDepth"] = static_cast(item.m_modifierDepth); + std::string jumpType = item.getJumpTypeAsString(); + if (!jumpType.empty()) + jsonItem["jumpType"] = jumpType; + if (name == "PUSHLIB") + data = m_libraries.at(h256(data)); + else if (name == "PUSHIMMUTABLE" || name == "ASSIGNIMMUTABLE") + data = m_immutables.at(h256(data)); + if (!data.empty()) + jsonItem["value"] = data; + jsonItem["source"] = sourceIndex; + code.append(move(jsonItem)); + + if (item.type() == AssemblyItemType::Tag) { - case Operation: - collection.append( - createJsonValue( - instructionInfo(i.instruction()).name, - sourceIndex, - i.location().start, - i.location().end, - i.getJumpTypeAsString()) - ); - break; - case Push: - collection.append( - createJsonValue("PUSH", sourceIndex, i.location().start, i.location().end, toStringInHex(i.data()), i.getJumpTypeAsString())); - break; - case PushTag: - if (i.data() == 0) - collection.append( - createJsonValue("PUSH [ErrorTag]", sourceIndex, i.location().start, i.location().end, "")); - else - collection.append( - createJsonValue("PUSH [tag]", sourceIndex, i.location().start, i.location().end, toString(i.data()))); - break; - case PushSub: - collection.append( - createJsonValue("PUSH [$]", sourceIndex, i.location().start, i.location().end, toString(h256(i.data())))); - break; - case PushSubSize: - collection.append( - createJsonValue("PUSH #[$]", sourceIndex, i.location().start, i.location().end, toString(h256(i.data())))); - break; - case PushProgramSize: - collection.append( - createJsonValue("PUSHSIZE", sourceIndex, i.location().start, i.location().end)); - break; - case PushLibraryAddress: - collection.append( - createJsonValue("PUSHLIB", sourceIndex, i.location().start, i.location().end, m_libraries.at(h256(i.data()))) - ); - break; - case PushDeployTimeAddress: - collection.append( - createJsonValue("PUSHDEPLOYADDRESS", sourceIndex, i.location().start, i.location().end) - ); - break; - case PushImmutable: - collection.append(createJsonValue( - "PUSHIMMUTABLE", - sourceIndex, - i.location().start, - i.location().end, - m_immutables.at(h256(i.data())) - )); - break; - case AssignImmutable: - collection.append(createJsonValue( - "ASSIGNIMMUTABLE", - sourceIndex, - i.location().start, - i.location().end, - m_immutables.at(h256(i.data())) - )); - break; - case Tag: - collection.append( - createJsonValue("tag", sourceIndex, i.location().start, i.location().end, toString(i.data()))); - collection.append( - createJsonValue("JUMPDEST", sourceIndex, i.location().start, i.location().end)); - break; - case PushData: - collection.append(createJsonValue("PUSH data", sourceIndex, i.location().start, i.location().end, toStringInHex(i.data()))); - break; - case VerbatimBytecode: - collection.append(createJsonValue("VERBATIM", sourceIndex, i.location().start, i.location().end, util::toHex(i.verbatimData()))); - break; - default: - assertThrow(false, InvalidOpcode, ""); + Json::Value jumpdest; + jumpdest["name"] = "JUMPDEST"; + jumpdest["begin"] = item.location().start; + jumpdest["end"] = item.location().end; + jumpdest["source"] = sourceIndex; + if (item.m_modifierDepth != 0) + jumpdest["modifierDepth"] = static_cast(item.m_modifierDepth); + code.append(move(jumpdest)); } } + if (_includeSourceList) + { + root["sourceList"] = Json::arrayValue; + Json::Value& jsonSourceList = root["sourceList"]; + for (auto const& [name, index]: _sourceIndices) + jsonSourceList[index] = name; + } if (!m_data.empty() || !m_subs.empty()) { @@ -346,17 +282,17 @@ Json::Value Assembly::assemblyJSON(map const& _sourceIndices) Json::Value& data = root[".data"]; for (auto const& i: m_data) if (u256(i.first) >= m_subs.size()) - data[toStringInHex((u256)i.first)] = util::toHex(i.second); + data[util::toHex(toBigEndian((u256)i.first), util::HexPrefix::DontAdd, util::HexCase::Upper)] = util::toHex(i.second); for (size_t i = 0; i < m_subs.size(); ++i) { std::stringstream hexStr; hexStr << hex << i; - data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices); + data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, /*_includeSourceList = */false); } } - if (m_auxiliaryData.size() > 0) + if (!m_auxiliaryData.empty()) root[".auxdata"] = util::toHex(m_auxiliaryData); return root; diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 11bc16662..592119f17 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -39,6 +39,7 @@ #include #include #include +#include namespace solidity::evmasm { @@ -147,7 +148,8 @@ public: /// Create a JSON representation of the assembly. Json::Value assemblyJSON( - std::map const& _sourceIndices = std::map() + std::map const& _sourceIndices = std::map(), + bool _includeSourceList = true ) const; /// Mark this assembly as invalid. Calling ``assemble`` on it will throw. @@ -167,16 +169,6 @@ protected: unsigned codeSize(unsigned subTagSize) const; private: - static Json::Value createJsonValue( - std::string _name, - int _source, - int _begin, - int _end, - std::string _value = std::string(), - std::string _jumpType = std::string() - ); - static std::string toStringInHex(u256 _value); - bool m_invalid = false; Assembly const* subAssemblyById(size_t _subId) const; @@ -222,6 +214,7 @@ protected: std::string m_name; langutil::SourceLocation m_currentSourceLocation; + public: size_t m_currentModifierDepth = 0; }; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 984058765..a36e0ddb1 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,18 @@ using namespace solidity::langutil; static_assert(sizeof(size_t) <= 8, "size_t must be at most 64-bits wide"); +namespace +{ + +string toStringInHex(u256 _value) +{ + std::stringstream hexStr; + hexStr << std::uppercase << hex << _value; + return hexStr.str(); +} + +} + AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const { assertThrow(data() < (u256(1) << 64), util::Exception, "Tag already has subassembly set."); @@ -56,6 +69,44 @@ pair AssemblyItem::splitForeignPushTag() const return make_pair(subId, tag); } +pair AssemblyItem::nameAndData() const +{ + switch (type()) + { + case Operation: + return {instructionInfo(instruction()).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; + case Push: + return {"PUSH", toStringInHex(data())}; + case PushTag: + if (data() == 0) + return {"PUSH [ErrorTag]", ""}; + else + return {"PUSH [tag]", util::toString(data())}; + case PushSub: + return {"PUSH [$]", toString(util::h256(data()))}; + case PushSubSize: + return {"PUSH #[$]", toString(util::h256(data()))}; + case PushProgramSize: + return {"PUSHSIZE", ""}; + case PushLibraryAddress: + return {"PUSHLIB", toString(util::h256(data()))}; + case PushDeployTimeAddress: + return {"PUSHDEPLOYADDRESS", ""}; + case PushImmutable: + return {"PUSHIMMUTABLE", toString(util::h256(data()))}; + case AssignImmutable: + return {"ASSIGNIMMUTABLE", toString(util::h256(data()))}; + case Tag: + return {"tag", util::toString(data())}; + case PushData: + return {"PUSH data", toStringInHex(data())}; + case VerbatimBytecode: + return {"VERBATIM", util::toHex(verbatimData())}; + default: + assertThrow(false, InvalidOpcode, ""); + } +} + void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) { assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 796a792e8..4aef82d8b 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -106,6 +106,13 @@ public: u256 const& data() const { assertThrow(m_type != Operation, util::Exception, ""); return *m_data; } void setData(u256 const& _data) { assertThrow(m_type != Operation, util::Exception, ""); m_data = std::make_shared(_data); } + /// This function is used in `Assembly::assemblyJSON`. + /// It returns the name & data of the current assembly item. + /// @returns a pair, where the first element is the json-assembly + /// item name, where second element is the string representation + /// of it's data. + std::pair nameAndData() const; + bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); } /// @returns the instruction of this item (only valid if type() == Operation) diff --git a/test/cmdlineTests/asm_json/output b/test/cmdlineTests/asm_json/output index 26ab87147..000ad1b75 100644 --- a/test/cmdlineTests/asm_json/output +++ b/test/cmdlineTests/asm_json/output @@ -450,9 +450,9 @@ EVM assembly: { "begin": 77, "end": 158, + "jumpType": "[in]", "name": "JUMP", - "source": 0, - "value": "[in]" + "source": 0 }, { "begin": 77, @@ -477,9 +477,9 @@ EVM assembly: { "begin": 77, "end": 158, + "jumpType": "[in]", "name": "JUMP", - "source": 0, - "value": "[in]" + "source": 0 }, { "begin": 77, @@ -555,9 +555,9 @@ EVM assembly: { "begin": 118, "end": 125, + "jumpType": "[in]", "name": "JUMP", - "source": 0, - "value": "[in]" + "source": 0 }, { "begin": 118, @@ -657,9 +657,9 @@ EVM assembly: { "begin": 77, "end": 158, + "jumpType": "[out]", "name": "JUMP", - "source": 0, - "value": "[out]" + "source": 0 }, { "begin": 88, @@ -752,9 +752,9 @@ EVM assembly: { "begin": 334, "end": 411, + "jumpType": "[out]", "name": "JUMP", - "source": 1, - "value": "[out]" + "source": 1 }, { "begin": 417, @@ -792,9 +792,9 @@ EVM assembly: { "begin": 490, "end": 514, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 490, @@ -875,9 +875,9 @@ EVM assembly: { "begin": 417, "end": 539, + "jumpType": "[out]", "name": "JUMP", - "source": 1, - "value": "[out]" + "source": 1 }, { "begin": 545, @@ -946,9 +946,9 @@ EVM assembly: { "begin": 645, "end": 678, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 645, @@ -990,9 +990,9 @@ EVM assembly: { "begin": 545, "end": 684, + "jumpType": "[out]", "name": "JUMP", - "source": 1, - "value": "[out]" + "source": 1 }, { "begin": 690, @@ -1081,9 +1081,9 @@ EVM assembly: { "begin": 804, "end": 883, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 804, @@ -1159,9 +1159,9 @@ EVM assembly: { "begin": 949, "end": 1002, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 949, @@ -1221,9 +1221,9 @@ EVM assembly: { "begin": 690, "end": 1019, + "jumpType": "[out]", "name": "JUMP", - "source": 1, - "value": "[out]" + "source": 1 }, { "begin": 1025, @@ -1341,9 +1341,9 @@ EVM assembly: { "begin": 1270, "end": 1290, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 1270, @@ -1393,9 +1393,9 @@ EVM assembly: { "begin": 1304, "end": 1324, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 1304, @@ -1489,9 +1489,9 @@ EVM assembly: { "begin": 1464, "end": 1482, + "jumpType": "[in]", "name": "JUMP", - "source": 1, - "value": "[in]" + "source": 1 }, { "begin": 1464, @@ -1576,11 +1576,16 @@ EVM assembly: { "begin": 1211, "end": 1516, + "jumpType": "[out]", "name": "JUMP", - "source": 1, - "value": "[out]" + "source": 1 } ] } - } + }, + "sourceList": + [ + "asm_json/input.sol", + "#utility.yul" + ] } diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 3a3167816..680531799 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -56,7 +56,8 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) { map indices = { { "root.asm", 0 }, - { "sub.asm", 1 } + { "sub.asm", 1 }, + { "verbatim.asm", 2 } }; Assembly _assembly{false, {}}; auto root_asm = make_shared("root.asm"); @@ -65,11 +66,22 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) Assembly _subAsm{false, {}}; auto sub_asm = make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); + + Assembly _verbatimAsm(true, ""); + auto verbatim_asm = make_shared("verbatim.asm"); + _verbatimAsm.setSourceLocation({8, 18, verbatim_asm}); + // PushImmutable _subAsm.appendImmutable("someImmutable"); + _subAsm.append(AssemblyItem(PushTag, 0)); _subAsm.append(Instruction::INVALID); shared_ptr _subAsmPtr = make_shared(_subAsm); + _verbatimAsm.appendVerbatim({0xff,0xff}, 0, 0); + _verbatimAsm.appendVerbatim({0x74, 0x65, 0x73, 0x74}, 0, 1); + _verbatimAsm.append(Instruction::MSTORE); + shared_ptr _verbatimAsmPtr = make_shared(_verbatimAsm); + // Tag auto tag = _assembly.newTag(); _assembly.append(tag); @@ -77,7 +89,10 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) _assembly.append(u256(1)); _assembly.append(u256(2)); // Push - _assembly.append(Instruction::KECCAK256); + auto keccak256 = AssemblyItem(Instruction::KECCAK256); + _assembly.m_currentModifierDepth = 1; + _assembly.append(keccak256); + _assembly.m_currentModifierDepth = 0; // PushProgramSize _assembly.appendProgramSize(); // PushLibraryAddress @@ -90,6 +105,10 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) auto sub = _assembly.appendSubroutine(_subAsmPtr); // PushSub _assembly.pushSubroutineOffset(static_cast(sub.data())); + // PushSubSize + auto verbatim_sub = _assembly.appendSubroutine(_verbatimAsmPtr); + // PushSub + _assembly.pushSubroutineOffset(static_cast(verbatim_sub.data())); // PushDeployTimeAddress _assembly.append(PushDeployTimeAddress); // AssignImmutable. @@ -102,16 +121,21 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) _assembly.appendToAuxiliaryData(bytes{0x42, 0x66}); _assembly.appendToAuxiliaryData(bytes{0xee, 0xaa}); + _assembly.m_currentModifierDepth = 2; + _assembly.appendJump(tag); + _assembly.m_currentModifierDepth = 0; + checkCompilation(_assembly); BOOST_CHECK_EQUAL( _assembly.assemble().toHex(), - "5b6001600220606f73__$bf005014d9d0f534b8fcb268bd84c491a2$__" - "6000566067602260457300000000000000000000000000000000000000005050" + "5b6001600220607f73__$bf005014d9d0f534b8fcb268bd84c491a2$__" + "60005660776024604c600760707300000000000000000000000000000000000000005050" "600260010152" - "00fe" + "006000" + "56fe" "7f0000000000000000000000000000000000000000000000000000000000000000" - "fe010203044266eeaa" + "6000feffff7465737452010203044266eeaa" ); BOOST_CHECK_EQUAL( _assembly.assemblyString(), @@ -124,30 +148,40 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) " data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b\n" " dataSize(sub_0)\n" " dataOffset(sub_0)\n" + " dataSize(sub_1)\n" + " dataOffset(sub_1)\n" " deployTimeAddress()\n" " assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n" " 0x02\n" " assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n" " stop\n" + " jump(tag_1)\n" "stop\n" "data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b 01020304\n" "\n" "sub_0: assembly {\n" " /* \"sub.asm\":6:8 */\n" " immutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n" + " tag_0\n" " invalid\n" "}\n" "\n" + "sub_1: assembly {\n" + " /* \"verbatim.asm\":8:18 */\n" + " verbatimbytecode_ffff\n" + " verbatimbytecode_74657374\n" + " mstore\n" + "}\n" + "\n" "auxdata: 0x4266eeaa\n" ); - BOOST_CHECK_EQUAL( - util::jsonCompactPrint(_assembly.assemblyJSON(indices)), + string json{ "{\".auxdata\":\"4266eeaa\",\".code\":[" "{\"begin\":1,\"end\":3,\"name\":\"tag\",\"source\":0,\"value\":\"1\"}," "{\"begin\":1,\"end\":3,\"name\":\"JUMPDEST\",\"source\":0}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"1\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2\"}," - "{\"begin\":1,\"end\":3,\"name\":\"KECCAK256\",\"source\":0}," + "{\"begin\":1,\"end\":3,\"modifierDepth\":1,\"name\":\"KECCAK256\",\"source\":0}," "{\"begin\":1,\"end\":3,\"name\":\"PUSHSIZE\",\"source\":0}," "{\"begin\":1,\"end\":3,\"name\":\"PUSHLIB\",\"source\":0,\"value\":\"someLibrary\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH [tag]\",\"source\":0,\"value\":\"1\"}," @@ -155,16 +189,28 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) "{\"begin\":1,\"end\":3,\"name\":\"PUSH data\",\"source\":0,\"value\":\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000001\"}," + "{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000001\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSHDEPLOYADDRESS\",\"source\":0}," "{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someOtherImmutable\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2\"}," "{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someImmutable\"}," - "{\"begin\":1,\"end\":3,\"name\":\"STOP\",\"source\":0}" + "{\"begin\":1,\"end\":3,\"name\":\"STOP\",\"source\":0}," + "{\"begin\":1,\"end\":3,\"modifierDepth\":2,\"name\":\"PUSH [tag]\",\"source\":0,\"value\":\"1\"},{\"begin\":1,\"end\":3,\"modifierDepth\":2,\"name\":\"JUMP\",\"source\":0}" "],\".data\":{\"0\":{\".code\":[" "{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}," + "{\"begin\":6,\"end\":8,\"name\":\"PUSH [ErrorTag]\",\"source\":1}," "{\"begin\":6,\"end\":8,\"name\":\"INVALID\",\"source\":1}" - "]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"}}" - ); + "]}," + "\"1\":{\".code\":[" + "{\"begin\":8,\"end\":18,\"name\":\"VERBATIM\",\"source\":2,\"value\":\"ffff\"}," + "{\"begin\":8,\"end\":18,\"name\":\"VERBATIM\",\"source\":2,\"value\":\"74657374\"}," + "{\"begin\":8,\"end\":18,\"name\":\"MSTORE\",\"source\":2}" + "]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}" + }; + Json::Value jsonValue; + BOOST_CHECK(util::jsonParseStrict(json, jsonValue)); + BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue)); } BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) @@ -343,7 +389,7 @@ BOOST_AUTO_TEST_CASE(immutable) "{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}," "{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someOtherImmutable\"}," "{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}" - "]}}}" + "]}},\"sourceList\":[\"root.asm\",\"sub.asm\"]}" ); }