From 25205cb05b068e0ec116bdc3f8230f9f2f2159f0 Mon Sep 17 00:00:00 2001
From: Liana Husikyan <liana@ethdev.com>
Date: Fri, 15 May 2015 12:23:13 +0200
Subject: added error jump instead of STOP instraction in case of exception

---
 Assembly.cpp         | 28 +++++++++++++++++++++++-----
 Assembly.h           |  6 ++++--
 AssemblyItem.h       |  2 +-
 ControlFlowGraph.cpp |  8 ++++----
 4 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/Assembly.cpp b/Assembly.cpp
index 5cf3b787..f492260a 100644
--- a/Assembly.cpp
+++ b/Assembly.cpp
@@ -127,7 +127,10 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
 			_out << "  PUSH \"" << m_strings.at((h256)i.data()) << "\"";
 			break;
 		case PushTag:
-			_out << "  PUSH [tag" << dec << i.data() << "]";
+			if (i.data() == 0)
+				_out << "  PUSH [ErrorTag]";
+			else
+				_out << "  PUSH [tag" << dec << i.data() << "]";
 			break;
 		case PushSub:
 			_out << "  PUSH [$" << h256(i.data()).abridged() << "]";
@@ -207,6 +210,10 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
 				createJsonValue("PUSH tag", i.getLocation().start, i.getLocation().end, m_strings.at((h256)i.data())));
 			break;
 		case PushTag:
+			if (i.data() == 0)
+				collection.append(
+					createJsonValue("PUSH [ErrorTag]", i.getLocation().start, i.getLocation().end, ""));
+
 			collection.append(
 				createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
 			break;
@@ -226,7 +233,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
 			collection.append(
 				createJsonValue("tag", i.getLocation().start, i.getLocation().end, string(i.data())));
 			collection.append(
-				createJsonValue("JUMDEST", i.getLocation().start, i.getLocation().end));
+				createJsonValue("JUMPDEST", i.getLocation().start, i.getLocation().end));
 			break;
 		case PushData:
 			collection.append(createJsonValue("PUSH data", i.getLocation().start, i.getLocation().end, toStringInHex(i.data())));
@@ -387,6 +394,11 @@ bytes Assembly::assemble() const
 	// m_data must not change from here on
 
 	for (AssemblyItem const& i: m_items)
+	{
+		// store position of the invalid jump destination
+		if (i.type() != Tag && tagPos[0] == 0)
+			tagPos[0] = ret.size();
+
 		switch (i.type())
 		{
 		case Operation:
@@ -448,17 +460,23 @@ bytes Assembly::assemble() const
 		}
 		case Tag:
 			tagPos[(unsigned)i.data()] = ret.size();
+			assertThrow(i.data() != 0, AssemblyException, "");
 			ret.push_back((byte)Instruction::JUMPDEST);
 			break;
 		default:
 			BOOST_THROW_EXCEPTION(InvalidOpcode());
 		}
-
+	}
 	for (auto const& i: tagRef)
 	{
 		bytesRef r(ret.data() + i.first, bytesPerTag);
-		//@todo in the failure case, we could use the position of the invalid jumpdest
-		toBigEndian(i.second < tagPos.size() ? tagPos[i.second] : (1 << (8 * bytesPerTag)) - 1, r);
+		auto tag = i.second;
+		if (tag >= tagPos.size())
+			tag = 0;
+		if (tag == 0)
+			assertThrow(tagPos[tag] != 0, AssemblyException, "");
+
+		toBigEndian(tagPos[tag], r);
 	}
 
 	if (!m_data.empty())
diff --git a/Assembly.h b/Assembly.h
index b4850f7d..4550eb6e 100644
--- a/Assembly.h
+++ b/Assembly.h
@@ -67,6 +67,8 @@ public:
 	AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; }
 	AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; }
 	AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; }
+	AssemblyItem errorTag() { return AssemblyItem(PushTag,  0); }
+
 	template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
 	AssemblyItems const& getItems() const { return m_items; }
 	AssemblyItem const& back() const { return m_items.back(); }
@@ -97,7 +99,6 @@ public:
 		const StringMap &_sourceCodes = StringMap(),
 		bool _inJsonFormat = false
 	) const;
-
 protected:
 	std::string getLocationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const;
 	void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
@@ -109,7 +110,8 @@ private:
 	Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const;
 
 protected:
-	unsigned m_usedTags = 0;
+	// 0 is reserved for exception
+	unsigned m_usedTags = 1;
 	AssemblyItems m_items;
 	mutable std::map<h256, bytes> m_data;
 	std::vector<Assembly> m_subs;
diff --git a/AssemblyItem.h b/AssemblyItem.h
index 7d8f3d9a..9eca0a7d 100644
--- a/AssemblyItem.h
+++ b/AssemblyItem.h
@@ -65,7 +65,7 @@ public:
 	/// @returns the instruction of this item (only valid if type() == Operation)
 	Instruction instruction() const { return Instruction(byte(m_data)); }
 
-	/// @returns true iff the type and data of the items are equal.
+	/// @returns true if the type and data of the items are equal.
 	bool operator==(AssemblyItem const& _other) const { return m_type == _other.m_type && m_data == _other.m_data; }
 	bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); }
 	/// Less-than operator compatible with operator==.
diff --git a/ControlFlowGraph.cpp b/ControlFlowGraph.cpp
index 3566bdb1..41a53aa8 100644
--- a/ControlFlowGraph.cpp
+++ b/ControlFlowGraph.cpp
@@ -226,7 +226,10 @@ void ControlFlowGraph::gatherKnowledge()
 		//@todo we might have to do something like incrementing the sequence number for each JUMPDEST
 		assertThrow(!!workQueue.back().first, OptimizerException, "");
 		if (!m_blocks.count(workQueue.back().first))
+		{
+			workQueue.pop_back();
 			continue; // too bad, we do not know the tag, probably an invalid jump
+		}
 		BasicBlock& block = m_blocks.at(workQueue.back().first);
 		KnownStatePointer state = workQueue.back().second;
 		workQueue.pop_back();
@@ -257,10 +260,7 @@ void ControlFlowGraph::gatherKnowledge()
 			);
 			state->feedItem(m_items.at(pc++));
 
-			if (tags.empty() || std::any_of(tags.begin(), tags.end(), [&](u256 const& _tag)
-			{
-				return !m_blocks.count(BlockId(_tag));
-			}))
+			if (tags.empty())
 			{
 				if (!unknownJumpEncountered)
 				{
-- 
cgit v1.2.3


From 735535d9609ed35b1037ed7128f795df162909ca Mon Sep 17 00:00:00 2001
From: Liana Husikyan <liana@ethdev.com>
Date: Tue, 19 May 2015 15:44:58 +0200
Subject: style fixes

---
 Assembly.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Assembly.h b/Assembly.h
index 4550eb6e..3c82125a 100644
--- a/Assembly.h
+++ b/Assembly.h
@@ -67,7 +67,7 @@ public:
 	AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; }
 	AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; }
 	AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; }
-	AssemblyItem errorTag() { return AssemblyItem(PushTag,  0); }
+	AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); }
 
 	template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
 	AssemblyItems const& getItems() const { return m_items; }
-- 
cgit v1.2.3


From da4cd45a85c1b3fe7b72ca53ba4263a309d40ed1 Mon Sep 17 00:00:00 2001
From: Liana Husikyan <liana@ethdev.com>
Date: Wed, 20 May 2015 13:15:01 +0200
Subject: corrected asm-json output

---
 Assembly.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Assembly.cpp b/Assembly.cpp
index f492260a..dabf646c 100644
--- a/Assembly.cpp
+++ b/Assembly.cpp
@@ -213,9 +213,9 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
 			if (i.data() == 0)
 				collection.append(
 					createJsonValue("PUSH [ErrorTag]", i.getLocation().start, i.getLocation().end, ""));
-
-			collection.append(
-				createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
+			else
+				collection.append(
+					createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
 			break;
 		case PushSub:
 			collection.append(
-- 
cgit v1.2.3