mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	libevmasm: refactor asm-json export & add support for source list.
This commit is contained in:
		
							parent
							
								
									b35cda5998
								
							
						
					
					
						commit
						1a0988e503
					
				| @ -5,9 +5,11 @@ Language Features: | |||||||
| 
 | 
 | ||||||
| Compiler Features: | Compiler Features: | ||||||
|  * Peephole Optimizer: Remove operations without side effects before simple terminations. |  * Peephole Optimizer: Remove operations without side effects before simple terminations. | ||||||
|  |  * Assembly-Json: Export: Include source list in `sourceList` field. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Bugfixes: | Bugfixes: | ||||||
|  | * Assembly-Json: Fix assembly json export to store jump types of operations in `jumpType` field instead of `value`. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -222,123 +222,59 @@ string Assembly::assemblyString( | |||||||
| 	return tmp.str(); | 	return tmp.str(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Json::Value Assembly::createJsonValue(string _name, int _source, int _begin, int _end, string _value, string _jumpType) | Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices, bool _includeSourceList) const | ||||||
| { |  | ||||||
| 	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<string, unsigned> const& _sourceIndices) const |  | ||||||
| { | { | ||||||
| 	Json::Value root; | 	Json::Value root; | ||||||
| 	root[".code"] = Json::arrayValue; | 	root[".code"] = Json::arrayValue; | ||||||
| 
 | 	Json::Value& code = root[".code"]; | ||||||
| 	Json::Value& collection = root[".code"]; | 	for (AssemblyItem const& item: m_items) | ||||||
| 	for (AssemblyItem const& i: m_items) |  | ||||||
| 	{ | 	{ | ||||||
| 		int sourceIndex = -1; | 		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()) | 			if (iter != _sourceIndices.end()) | ||||||
| 				sourceIndex = static_cast<int>(iter->second); | 				sourceIndex = static_cast<int>(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<int>(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: | 			Json::Value jumpdest; | ||||||
| 			collection.append( | 			jumpdest["name"] = "JUMPDEST"; | ||||||
| 				createJsonValue( | 			jumpdest["begin"] = item.location().start; | ||||||
| 					instructionInfo(i.instruction()).name, | 			jumpdest["end"] = item.location().end; | ||||||
| 					sourceIndex, | 			jumpdest["source"] = sourceIndex; | ||||||
| 					i.location().start, | 			if (item.m_modifierDepth != 0) | ||||||
| 					i.location().end, | 				jumpdest["modifierDepth"] = static_cast<int>(item.m_modifierDepth); | ||||||
| 					i.getJumpTypeAsString()) | 			code.append(move(jumpdest)); | ||||||
| 				); |  | ||||||
| 			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, ""); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	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()) | 	if (!m_data.empty() || !m_subs.empty()) | ||||||
| 	{ | 	{ | ||||||
| @ -346,17 +282,17 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices) | |||||||
| 		Json::Value& data = root[".data"]; | 		Json::Value& data = root[".data"]; | ||||||
| 		for (auto const& i: m_data) | 		for (auto const& i: m_data) | ||||||
| 			if (u256(i.first) >= m_subs.size()) | 			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) | 		for (size_t i = 0; i < m_subs.size(); ++i) | ||||||
| 		{ | 		{ | ||||||
| 			std::stringstream hexStr; | 			std::stringstream hexStr; | ||||||
| 			hexStr << hex << i; | 			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); | 		root[".auxdata"] = util::toHex(m_auxiliaryData); | ||||||
| 
 | 
 | ||||||
| 	return root; | 	return root; | ||||||
|  | |||||||
| @ -39,6 +39,7 @@ | |||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <map> | #include <map> | ||||||
|  | #include <utility> | ||||||
| 
 | 
 | ||||||
| namespace solidity::evmasm | namespace solidity::evmasm | ||||||
| { | { | ||||||
| @ -147,7 +148,8 @@ public: | |||||||
| 
 | 
 | ||||||
| 	/// Create a JSON representation of the assembly.
 | 	/// Create a JSON representation of the assembly.
 | ||||||
| 	Json::Value assemblyJSON( | 	Json::Value assemblyJSON( | ||||||
| 		std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>() | 		std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>(), | ||||||
|  | 		bool _includeSourceList = true | ||||||
| 	) const; | 	) const; | ||||||
| 
 | 
 | ||||||
| 	/// Mark this assembly as invalid. Calling ``assemble`` on it will throw.
 | 	/// Mark this assembly as invalid. Calling ``assemble`` on it will throw.
 | ||||||
| @ -167,16 +169,6 @@ protected: | |||||||
| 	unsigned codeSize(unsigned subTagSize) const; | 	unsigned codeSize(unsigned subTagSize) const; | ||||||
| 
 | 
 | ||||||
| private: | 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; | 	bool m_invalid = false; | ||||||
| 
 | 
 | ||||||
| 	Assembly const* subAssemblyById(size_t _subId) const; | 	Assembly const* subAssemblyById(size_t _subId) const; | ||||||
| @ -222,6 +214,7 @@ protected: | |||||||
| 	std::string m_name; | 	std::string m_name; | ||||||
| 
 | 
 | ||||||
| 	langutil::SourceLocation m_currentSourceLocation; | 	langutil::SourceLocation m_currentSourceLocation; | ||||||
|  | 
 | ||||||
| public: | public: | ||||||
| 	size_t m_currentModifierDepth = 0; | 	size_t m_currentModifierDepth = 0; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ | |||||||
| #include <libevmasm/Assembly.h> | #include <libevmasm/Assembly.h> | ||||||
| 
 | 
 | ||||||
| #include <libsolutil/CommonData.h> | #include <libsolutil/CommonData.h> | ||||||
|  | #include <libsolutil/CommonIO.h> | ||||||
| #include <libsolutil/Numeric.h> | #include <libsolutil/Numeric.h> | ||||||
| #include <libsolutil/StringUtils.h> | #include <libsolutil/StringUtils.h> | ||||||
| #include <libsolutil/FixedHash.h> | #include <libsolutil/FixedHash.h> | ||||||
| @ -36,6 +37,18 @@ using namespace solidity::langutil; | |||||||
| 
 | 
 | ||||||
| static_assert(sizeof(size_t) <= 8, "size_t must be at most 64-bits wide"); | 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 | AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const | ||||||
| { | { | ||||||
| 	assertThrow(data() < (u256(1) << 64), util::Exception, "Tag already has subassembly set."); | 	assertThrow(data() < (u256(1) << 64), util::Exception, "Tag already has subassembly set."); | ||||||
| @ -56,6 +69,44 @@ pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const | |||||||
| 	return make_pair(subId, tag); | 	return make_pair(subId, tag); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pair<string, string> 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) | void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) | ||||||
| { | { | ||||||
| 	assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); | 	assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); | ||||||
|  | |||||||
| @ -106,6 +106,13 @@ public: | |||||||
| 	u256 const& data() const { assertThrow(m_type != Operation, util::Exception, ""); return *m_data; } | 	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<u256>(_data); } | 	void setData(u256 const& _data) { assertThrow(m_type != Operation, util::Exception, ""); m_data = std::make_shared<u256>(_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<std::string, std::string> nameAndData() const; | ||||||
|  | 
 | ||||||
| 	bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); } | 	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)
 | 	/// @returns the instruction of this item (only valid if type() == Operation)
 | ||||||
|  | |||||||
| @ -450,9 +450,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 77, |           "begin": 77, | ||||||
|           "end": 158, |           "end": 158, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 0, |           "source": 0 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 77, |           "begin": 77, | ||||||
| @ -477,9 +477,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 77, |           "begin": 77, | ||||||
|           "end": 158, |           "end": 158, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 0, |           "source": 0 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 77, |           "begin": 77, | ||||||
| @ -555,9 +555,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 118, |           "begin": 118, | ||||||
|           "end": 125, |           "end": 125, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 0, |           "source": 0 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 118, |           "begin": 118, | ||||||
| @ -657,9 +657,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 77, |           "begin": 77, | ||||||
|           "end": 158, |           "end": 158, | ||||||
|  |           "jumpType": "[out]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 0, |           "source": 0 | ||||||
|           "value": "[out]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 88, |           "begin": 88, | ||||||
| @ -752,9 +752,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 334, |           "begin": 334, | ||||||
|           "end": 411, |           "end": 411, | ||||||
|  |           "jumpType": "[out]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[out]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 417, |           "begin": 417, | ||||||
| @ -792,9 +792,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 490, |           "begin": 490, | ||||||
|           "end": 514, |           "end": 514, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 490, |           "begin": 490, | ||||||
| @ -875,9 +875,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 417, |           "begin": 417, | ||||||
|           "end": 539, |           "end": 539, | ||||||
|  |           "jumpType": "[out]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[out]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 545, |           "begin": 545, | ||||||
| @ -946,9 +946,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 645, |           "begin": 645, | ||||||
|           "end": 678, |           "end": 678, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 645, |           "begin": 645, | ||||||
| @ -990,9 +990,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 545, |           "begin": 545, | ||||||
|           "end": 684, |           "end": 684, | ||||||
|  |           "jumpType": "[out]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[out]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 690, |           "begin": 690, | ||||||
| @ -1081,9 +1081,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 804, |           "begin": 804, | ||||||
|           "end": 883, |           "end": 883, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 804, |           "begin": 804, | ||||||
| @ -1159,9 +1159,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 949, |           "begin": 949, | ||||||
|           "end": 1002, |           "end": 1002, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 949, |           "begin": 949, | ||||||
| @ -1221,9 +1221,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 690, |           "begin": 690, | ||||||
|           "end": 1019, |           "end": 1019, | ||||||
|  |           "jumpType": "[out]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[out]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 1025, |           "begin": 1025, | ||||||
| @ -1341,9 +1341,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 1270, |           "begin": 1270, | ||||||
|           "end": 1290, |           "end": 1290, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 1270, |           "begin": 1270, | ||||||
| @ -1393,9 +1393,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 1304, |           "begin": 1304, | ||||||
|           "end": 1324, |           "end": 1324, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 1304, |           "begin": 1304, | ||||||
| @ -1489,9 +1489,9 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 1464, |           "begin": 1464, | ||||||
|           "end": 1482, |           "end": 1482, | ||||||
|  |           "jumpType": "[in]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[in]" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "begin": 1464, |           "begin": 1464, | ||||||
| @ -1576,11 +1576,16 @@ EVM assembly: | |||||||
|         { |         { | ||||||
|           "begin": 1211, |           "begin": 1211, | ||||||
|           "end": 1516, |           "end": 1516, | ||||||
|  |           "jumpType": "[out]", | ||||||
|           "name": "JUMP", |           "name": "JUMP", | ||||||
|           "source": 1, |           "source": 1 | ||||||
|           "value": "[out]" |  | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|     } |     } | ||||||
|   } |   }, | ||||||
|  |   "sourceList": | ||||||
|  |   [ | ||||||
|  |     "asm_json/input.sol", | ||||||
|  |     "#utility.yul" | ||||||
|  |   ] | ||||||
| } | } | ||||||
|  | |||||||
| @ -56,7 +56,8 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) | |||||||
| { | { | ||||||
| 	map<string, unsigned> indices = { | 	map<string, unsigned> indices = { | ||||||
| 		{ "root.asm", 0 }, | 		{ "root.asm", 0 }, | ||||||
| 		{ "sub.asm", 1 } | 		{ "sub.asm", 1 }, | ||||||
|  | 		{ "verbatim.asm", 2 } | ||||||
| 	}; | 	}; | ||||||
| 	Assembly _assembly{false, {}}; | 	Assembly _assembly{false, {}}; | ||||||
| 	auto root_asm = make_shared<string>("root.asm"); | 	auto root_asm = make_shared<string>("root.asm"); | ||||||
| @ -65,11 +66,22 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) | |||||||
| 	Assembly _subAsm{false, {}}; | 	Assembly _subAsm{false, {}}; | ||||||
| 	auto sub_asm = make_shared<string>("sub.asm"); | 	auto sub_asm = make_shared<string>("sub.asm"); | ||||||
| 	_subAsm.setSourceLocation({6, 8, sub_asm}); | 	_subAsm.setSourceLocation({6, 8, sub_asm}); | ||||||
|  | 
 | ||||||
|  | 	Assembly _verbatimAsm(true, ""); | ||||||
|  | 	auto verbatim_asm = make_shared<string>("verbatim.asm"); | ||||||
|  | 	_verbatimAsm.setSourceLocation({8, 18, verbatim_asm}); | ||||||
|  | 
 | ||||||
| 	// PushImmutable
 | 	// PushImmutable
 | ||||||
| 	_subAsm.appendImmutable("someImmutable"); | 	_subAsm.appendImmutable("someImmutable"); | ||||||
|  | 	_subAsm.append(AssemblyItem(PushTag, 0)); | ||||||
| 	_subAsm.append(Instruction::INVALID); | 	_subAsm.append(Instruction::INVALID); | ||||||
| 	shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm); | 	shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm); | ||||||
| 
 | 
 | ||||||
|  | 	_verbatimAsm.appendVerbatim({0xff,0xff}, 0, 0); | ||||||
|  | 	_verbatimAsm.appendVerbatim({0x74, 0x65, 0x73, 0x74}, 0, 1); | ||||||
|  | 	_verbatimAsm.append(Instruction::MSTORE); | ||||||
|  | 	shared_ptr<Assembly> _verbatimAsmPtr = make_shared<Assembly>(_verbatimAsm); | ||||||
|  | 
 | ||||||
| 	// Tag
 | 	// Tag
 | ||||||
| 	auto tag = _assembly.newTag(); | 	auto tag = _assembly.newTag(); | ||||||
| 	_assembly.append(tag); | 	_assembly.append(tag); | ||||||
| @ -77,7 +89,10 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) | |||||||
| 	_assembly.append(u256(1)); | 	_assembly.append(u256(1)); | ||||||
| 	_assembly.append(u256(2)); | 	_assembly.append(u256(2)); | ||||||
| 	// Push
 | 	// Push
 | ||||||
| 	_assembly.append(Instruction::KECCAK256); | 	auto keccak256 = AssemblyItem(Instruction::KECCAK256); | ||||||
|  | 	_assembly.m_currentModifierDepth = 1; | ||||||
|  | 	_assembly.append(keccak256); | ||||||
|  | 	_assembly.m_currentModifierDepth = 0; | ||||||
| 	// PushProgramSize
 | 	// PushProgramSize
 | ||||||
| 	_assembly.appendProgramSize(); | 	_assembly.appendProgramSize(); | ||||||
| 	// PushLibraryAddress
 | 	// PushLibraryAddress
 | ||||||
| @ -90,6 +105,10 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) | |||||||
| 	auto sub = _assembly.appendSubroutine(_subAsmPtr); | 	auto sub = _assembly.appendSubroutine(_subAsmPtr); | ||||||
| 	// PushSub
 | 	// PushSub
 | ||||||
| 	_assembly.pushSubroutineOffset(static_cast<size_t>(sub.data())); | 	_assembly.pushSubroutineOffset(static_cast<size_t>(sub.data())); | ||||||
|  | 	// PushSubSize
 | ||||||
|  | 	auto verbatim_sub = _assembly.appendSubroutine(_verbatimAsmPtr); | ||||||
|  | 	// PushSub
 | ||||||
|  | 	_assembly.pushSubroutineOffset(static_cast<size_t>(verbatim_sub.data())); | ||||||
| 	// PushDeployTimeAddress
 | 	// PushDeployTimeAddress
 | ||||||
| 	_assembly.append(PushDeployTimeAddress); | 	_assembly.append(PushDeployTimeAddress); | ||||||
| 	// AssignImmutable.
 | 	// AssignImmutable.
 | ||||||
| @ -102,16 +121,21 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) | |||||||
| 	_assembly.appendToAuxiliaryData(bytes{0x42, 0x66}); | 	_assembly.appendToAuxiliaryData(bytes{0x42, 0x66}); | ||||||
| 	_assembly.appendToAuxiliaryData(bytes{0xee, 0xaa}); | 	_assembly.appendToAuxiliaryData(bytes{0xee, 0xaa}); | ||||||
| 
 | 
 | ||||||
|  | 	_assembly.m_currentModifierDepth = 2; | ||||||
|  | 	_assembly.appendJump(tag); | ||||||
|  | 	_assembly.m_currentModifierDepth = 0; | ||||||
|  | 
 | ||||||
| 	checkCompilation(_assembly); | 	checkCompilation(_assembly); | ||||||
| 
 | 
 | ||||||
| 	BOOST_CHECK_EQUAL( | 	BOOST_CHECK_EQUAL( | ||||||
| 		_assembly.assemble().toHex(), | 		_assembly.assemble().toHex(), | ||||||
| 		"5b6001600220606f73__$bf005014d9d0f534b8fcb268bd84c491a2$__" | 		"5b6001600220607f73__$bf005014d9d0f534b8fcb268bd84c491a2$__" | ||||||
| 		"6000566067602260457300000000000000000000000000000000000000005050" | 		"60005660776024604c600760707300000000000000000000000000000000000000005050" | ||||||
| 		"600260010152" | 		"600260010152" | ||||||
| 		"00fe" | 		"006000" | ||||||
|  | 		"56fe" | ||||||
| 		"7f0000000000000000000000000000000000000000000000000000000000000000" | 		"7f0000000000000000000000000000000000000000000000000000000000000000" | ||||||
| 		"fe010203044266eeaa" | 		"6000feffff7465737452010203044266eeaa" | ||||||
| 	); | 	); | ||||||
| 	BOOST_CHECK_EQUAL( | 	BOOST_CHECK_EQUAL( | ||||||
| 		_assembly.assemblyString(), | 		_assembly.assemblyString(), | ||||||
| @ -124,30 +148,40 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) | |||||||
| 		"  data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b\n" | 		"  data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b\n" | ||||||
| 		"  dataSize(sub_0)\n" | 		"  dataSize(sub_0)\n" | ||||||
| 		"  dataOffset(sub_0)\n" | 		"  dataOffset(sub_0)\n" | ||||||
|  | 		"  dataSize(sub_1)\n" | ||||||
|  | 		"  dataOffset(sub_1)\n" | ||||||
| 		"  deployTimeAddress()\n" | 		"  deployTimeAddress()\n" | ||||||
| 		"  assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n" | 		"  assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n" | ||||||
| 		"  0x02\n" | 		"  0x02\n" | ||||||
| 		"  assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n" | 		"  assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n" | ||||||
| 		"  stop\n" | 		"  stop\n" | ||||||
|  | 		"  jump(tag_1)\n" | ||||||
| 		"stop\n" | 		"stop\n" | ||||||
| 		"data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b 01020304\n" | 		"data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b 01020304\n" | ||||||
| 		"\n" | 		"\n" | ||||||
| 		"sub_0: assembly {\n" | 		"sub_0: assembly {\n" | ||||||
| 		"        /* \"sub.asm\":6:8   */\n" | 		"        /* \"sub.asm\":6:8   */\n" | ||||||
| 		"      immutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n" | 		"      immutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n" | ||||||
|  | 		"      tag_0\n" | ||||||
| 		"      invalid\n" | 		"      invalid\n" | ||||||
| 		"}\n" | 		"}\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" | 		"auxdata: 0x4266eeaa\n" | ||||||
| 	); | 	); | ||||||
| 	BOOST_CHECK_EQUAL( | 	string json{ | ||||||
| 		util::jsonCompactPrint(_assembly.assemblyJSON(indices)), |  | ||||||
| 		"{\".auxdata\":\"4266eeaa\",\".code\":[" | 		"{\".auxdata\":\"4266eeaa\",\".code\":[" | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"tag\",\"source\":0,\"value\":\"1\"}," | 		"{\"begin\":1,\"end\":3,\"name\":\"tag\",\"source\":0,\"value\":\"1\"}," | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"JUMPDEST\",\"source\":0}," | 		"{\"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\":\"1\"}," | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2\"}," | 		"{\"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\":\"PUSHSIZE\",\"source\":0}," | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"PUSHLIB\",\"source\":0,\"value\":\"someLibrary\"}," | 		"{\"begin\":1,\"end\":3,\"name\":\"PUSHLIB\",\"source\":0,\"value\":\"someLibrary\"}," | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"PUSH [tag]\",\"source\":0,\"value\":\"1\"}," | 		"{\"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 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\":\"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\":\"PUSHDEPLOYADDRESS\",\"source\":0}," | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someOtherImmutable\"}," | 		"{\"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\":\"PUSH\",\"source\":0,\"value\":\"2\"}," | ||||||
| 		"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someImmutable\"}," | 		"{\"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\":[" | 		"],\".data\":{\"0\":{\".code\":[" | ||||||
| 		"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}," | 		"{\"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}" | 		"{\"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) | 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\":\"someImmutable\"}," | ||||||
| 		"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someOtherImmutable\"}," | 		"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someOtherImmutable\"}," | ||||||
| 		"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}" | 		"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}" | ||||||
| 		"]}}}" | 		"]}},\"sourceList\":[\"root.asm\",\"sub.asm\"]}" | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user