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

pidgeot at users.sourceforge.net pidgeot at users.sourceforge.net
Thu Jul 1 21:40:16 CEST 2010


Revision: 50565
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50565&view=rev
Author:   pidgeot
Date:     2010-07-01 19:40:16 +0000 (Thu, 01 Jul 2010)

Log Message:
-----------
Add short-circuit detection to group generation

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

Modified: tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp	2010-07-01 18:47:27 UTC (rev 50564)
+++ tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp	2010-07-01 19:40:16 UTC (rev 50565)
@@ -100,6 +100,12 @@
 		boost::add_edge(g1, boost::target(*e, _g), _g);
 	}
 
+	// Update _next pointer
+	gr1->_next = gr2->_next;
+	if (gr2->_next != NULL)
+		gr2->_next->_prev = gr2->_prev;
+
+
 	// Remove edges to/from g2
 	boost::clear_vertex(g2, _g);
 	// Remove vertex
@@ -176,6 +182,44 @@
 		// All checks passed, merge groups
 		merge(cur, next);
 	}
+
+	// Short-circuit analysis
+	GraphVertex cur = find(curInst);
+	Group *gr = GET(cur);
+	while (gr->_prev != NULL) {
+		bool doMerge = false;
+		if ((gr->_end->_type == kCondJump || gr->_end->_type == kCondJumpRel) && (gr->_prev->_end->_type == kCondJump || gr->_prev->_end->_type == kCondJumpRel)) {
+			doMerge = true;
+			cur = find(gr->_start);
+			GraphVertex prev = find(gr->_prev->_start);
+			EdgeRange rCur = boost::out_edges(cur, _g);
+			GraphVertex gJump, gSeq;			
+
+			//Find possible target vertices
+			for (OutEdgeIterator it = rCur.first; it != rCur.second; it++) {
+				GraphVertex target = boost::target(*it, _g);
+				Group *targetGroup = GET(target);
+				if (_engine->getDestAddress(gr->_end) == targetGroup->_start->_address)
+					gJump = target;
+				else
+					gSeq = target;
+			}
+
+			//Check if vertex would add new targets - if yes, don't merge
+			EdgeRange rPrev = boost::out_edges(prev, _g);
+			for (OutEdgeIterator it = rPrev.first; it != rPrev.second; it++) {
+				GraphVertex target = boost::target(*it, _g);
+				if (target != gJump && target != gSeq && target != cur)
+					doMerge = false;
+			}
+			if (doMerge) {
+				gr = gr->_prev;				
+				merge(prev, cur);
+				continue;
+			}
+		}
+		gr = gr->_prev;
+	}
 }
 
 const Graph &ControlFlow::analyze() {

Modified: tools/branches/gsoc2010-decompiler/decompiler/graph.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/graph.h	2010-07-01 18:47:27 UTC (rev 50564)
+++ tools/branches/gsoc2010-decompiler/decompiler/graph.h	2010-07-01 19:40:16 UTC (rev 50565)
@@ -54,6 +54,7 @@
 	int _stackLevel;     ///< Level of the stack upon entry.
 	GroupType _type;     ///< Type of the group.
 	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.
 	
 	/**
 	 * Parameterless constructor for Group. Required for use with STL and Boost, should not be called manually.
@@ -75,6 +76,10 @@
 		_end = end;
 		_stackLevel = -1;
 		_type = kNormal;
+		_prev = prev;
+		if (_prev != NULL)
+			_prev->_next = this;
+		_next = NULL;
 	}
 
 	/**
@@ -84,8 +89,8 @@
 	 * @param group  The Group to output.
 	 * @return The std::ostream used for output.
 	 */
-	friend std::ostream &operator<<(std::ostream &output, Group &group) {
-		InstIterator inst = group._start;
+	friend std::ostream &operator<<(std::ostream &output, Group *group) {
+		InstIterator inst = group->_start;
 		do {
 			output << boost::format("%08x: %s") % inst->_address % inst->_name;
 			std::vector<Parameter>::iterator param;
@@ -105,7 +110,7 @@
 				}
 			}
 			output << boost::format(" (%d)") % inst->_stackChange << "\\n";
-		} while (inst++ != group._end);
+		} while (inst++ != group->_end);
 		return output;
 	}
 };


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