[Scummvm-cvs-logs] SF.net SVN: scummvm:[50635] tools/branches/gsoc2010-decompiler/decompiler

pidgeot at users.sourceforge.net pidgeot at users.sourceforge.net
Sat Jul 3 23:57:56 CEST 2010


Revision: 50635
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50635&view=rev
Author:   pidgeot
Date:     2010-07-03 21:57:56 +0000 (Sat, 03 Jul 2010)

Log Message:
-----------
Add detection of if and else, including test
Still need to find a proper way of detecting when an else ends
Fix incorrect while detection

Modified Paths:
--------------
    tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
    tools/branches/gsoc2010-decompiler/decompiler/graph.h
    tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h

Modified: tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp	2010-07-03 21:41:08 UTC (rev 50634)
+++ tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp	2010-07-03 21:57:56 UTC (rev 50635)
@@ -232,12 +232,15 @@
 		// Undetermined block that ends with conditional jump
 		if (out_degree(*v, _g) == 2 && gr->_type == kNormal) {
 			InEdgeRange ier = boost::in_edges(*v, _g);
+			bool isWhile = false;
 			for (InEdgeIterator e = ier.first; e != ier.second; ++e) {
 				Group *sourceGr = GET(boost::source(*e, _g));
 				// Block has ingoing edge from block later in the code that isn't a do-while condition
 				if (sourceGr->_start->_address > gr->_start->_address && sourceGr->_type != kDoWhileCond)
-					gr->_type = kWhileCond;
+					isWhile = true;
 			}
+			if (isWhile)
+				gr->_type = kWhileCond;
 		}
 	}
 }
@@ -301,5 +304,35 @@
 }
 
 void ControlFlow::detectIf() {
+	VertexRange vr = boost::vertices(_g);
+	for (VertexIterator v = vr.first; v != vr.second; ++v) {
+		Group *gr = GET(*v);
+		// if: Undetermined block with conditional jump
+		if (gr->_type == kNormal && out_degree(*v, _g) == 2) {
+			gr->_type = kIfCond;
+
+			OutEdgeRange oer = boost::out_edges(*v, _g);
+			GraphVertex target;
+			uint32 maxAddress = 0;
+			Group *targetGr;
+			// Find jump target
+			for (OutEdgeIterator oe = oer.first; oe != oer.second; ++oe) {
+				targetGr = GET(boost::target(*oe, _g));
+				if (targetGr->_start->_address > maxAddress) {
+					target = boost::target(*oe, _g);
+					maxAddress = targetGr->_start->_address;
+				}
+			}
+			targetGr = GET(target);
+			// else: Jump target of if immediately preceded by an unconditional jump...
+			if (targetGr->_prev->_end->_type != kJump && targetGr->_prev->_end->_type != kJumpRel)
+				continue;
+			// ...to later in the code
+			OutEdgeIterator toe = boost::out_edges(find(targetGr->_prev->_start->_address), _g).first;
+			Group *targetTargetGr = GET(boost::target(*toe, _g));
+			if (targetTargetGr->_start->_address > targetGr->_prev->_end->_address) {
+				targetGr->_else = true;
+			}
+		}
+	}
 }
-

Modified: tools/branches/gsoc2010-decompiler/decompiler/graph.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/graph.h	2010-07-03 21:41:08 UTC (rev 50634)
+++ tools/branches/gsoc2010-decompiler/decompiler/graph.h	2010-07-03 21:57:56 UTC (rev 50635)
@@ -53,7 +53,7 @@
 	InstIterator _end;   ///< Last instruction in the group.
 	int _stackLevel;     ///< Level of the stack upon entry.
 	GroupType _type;     ///< Type of the group.
-	bool _else;          ///< Group is start of an else.
+	bool _else;          ///< Group is start of an else block.
 	Group *_prev;        ///< Pointer to the previous group, when ordered by address. Used for short-circuit analysis.
 	Group *_next;        ///< Pointer to the next group, when ordered by address.
 	

Modified: tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h	2010-07-03 21:41:08 UTC (rev 50634)
+++ tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h	2010-07-03 21:57:56 UTC (rev 50635)
@@ -280,4 +280,83 @@
 		delete c;
 		delete engine;
 	}
+
+	void testIfDetection() {
+		Scumm::v6::Engine *engine = new Scumm::v6::Engine();
+		Disassembler *d = engine->getDisassembler();
+		d->open("decompiler/test/if.dmp");
+		std::vector<Instruction> insts = d->disassemble();
+		delete d;
+		ControlFlow *c = new ControlFlow(insts, engine);
+		c->createGroups();
+		Graph g = c->analyze();
+		VertexRange range = boost::vertices(g);
+		for (VertexIterator it = range.first; it != range.second; ++it) {
+			Group *gr = GET(*it);
+			if (gr->_start->_address == 0x0)
+				TS_ASSERT(gr->_type == kIfCond);
+		}
+		delete c;
+
+		d = engine->getDisassembler();
+		d->open("decompiler/test/break-do-while.dmp");
+		insts = d->disassemble();
+		delete d;
+		c = new ControlFlow(insts, engine);
+		c->createGroups();
+		g = c->analyze();
+		range = boost::vertices(g);
+		for (VertexIterator it = range.first; it != range.second; ++it) {
+			Group *gr = GET(*it);
+			if (gr->_start->_address == 0x0)
+				TS_ASSERT(gr->_type == kIfCond);
+		}
+		delete c;
+
+		d = engine->getDisassembler();
+		d->open("decompiler/test/break-do-while2.dmp");
+		insts = d->disassemble();
+		delete d;
+		c = new ControlFlow(insts, engine);
+		c->createGroups();
+		g = c->analyze();
+		range = boost::vertices(g);
+		for (VertexIterator it = range.first; it != range.second; ++it) {
+			Group *gr = GET(*it);
+			if (gr->_start->_address == 0x3)
+				TS_ASSERT(gr->_type == kIfCond);
+		}
+		delete c;
+
+		d = engine->getDisassembler();
+		d->open("decompiler/test/continue-do-while.dmp");
+		insts = d->disassemble();
+		delete d;
+		c = new ControlFlow(insts, engine);
+		c->createGroups();
+		g = c->analyze();
+		range = boost::vertices(g);
+		for (VertexIterator it = range.first; it != range.second; ++it) {
+			Group *gr = GET(*it);
+			if (gr->_start->_address == 0x0)
+				TS_ASSERT(gr->_type == kIfCond);
+		}
+		delete c;
+
+		d = engine->getDisassembler();
+		d->open("decompiler/test/continue-do-while2.dmp");
+		insts = d->disassemble();
+		delete d;
+		c = new ControlFlow(insts, engine);
+		c->createGroups();
+		g = c->analyze();
+		range = boost::vertices(g);
+		for (VertexIterator it = range.first; it != range.second; ++it) {
+			Group *gr = GET(*it);
+			if (gr->_start->_address == 0x3)
+				TS_ASSERT(gr->_type == kIfCond);
+		}
+		delete c;
+		delete engine;
+	}
 };


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list