[Scummvm-cvs-logs] SF.net SVN: scummvm: [28677] tools/branches/gsoc2007-decompiler/finalD

brixxie at users.sourceforge.net brixxie at users.sourceforge.net
Mon Aug 20 16:15:20 CEST 2007


Revision: 28677
          http://scummvm.svn.sourceforge.net/scummvm/?rev=28677&view=rev
Author:   brixxie
Date:     2007-08-20 07:15:20 -0700 (Mon, 20 Aug 2007)

Log Message:
-----------
fixed finite length loop bugs
(notably post-tested loop to two-conditional bug);
added instr offset output to if and while statements

Modified Paths:
--------------
    tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py
    tools/branches/gsoc2007-decompiler/finalD/cfg.py

Modified: tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py	2007-08-20 10:43:07 UTC (rev 28676)
+++ tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py	2007-08-20 14:15:20 UTC (rev 28677)
@@ -1,6 +1,6 @@
 """Pseudo code formatting from control flow graphs."""
 
-from cfg import BT, LT, get_then_else
+from cfg import BT, LT, get_then_else, node_to_revpo
 from iformat import is_jump
 
 
@@ -61,17 +61,23 @@
         """
         self.traversed.append(bbn)
         bb = self.cfg.node_data(bbn)
+        head_is_if = False
         # write loop header
         if bb.loop_type == LT.pre_tested:
             self._write_bb(bbn, i)
             t, e = get_then_else(self.cfg, bbn)
             if e == bb.loop_follow:
-                self._write("while (%s) {" % bb.type_info[2], i)
+                fmt = "while (%s) {"
             else:
-                self._write("while (!(%s)) {" % bb.type_info[2], i)
+                fmt = "while (!(%s)) {"
+            self._write(fmt % bb.type_info[2], i, "[%.4X]" % bb.get_last())
         elif bb.loop_type == LT.post_tested:
             self._write("do {", i)
-            self._write_bb(bbn, i+1)
+            if bbn != bb.loop_latch and bb.btype == BT.two_way:
+                self._write_two_way(bbn, i+1, latch, ifollow, True)
+                head_is_if = True
+            else:
+                self._write_bb(bbn, i+1)
         else:
             self._write("for (;;) {", i)
             self._write_bb(bbn, i+1)
@@ -79,19 +85,34 @@
             return
         if bb.loop_latch != bbn:
             # loop is several basic blocks
-            for s in self.cfg.out_nbrs(bbn):
-                if bb.loop_type != LT.pre_tested or s != bb.loop_follow:
-                    if s not in self.traversed:
+            if not head_is_if:
+                succs_asc = self.cfg.out_nbrs(bbn)
+                succs_asc.sort(key=node_to_revpo(self.cfg))
+                for s in succs_asc:
+                    if bb.loop_type != LT.pre_tested or s != bb.loop_follow:
+                        if s not in self.traversed:
+                            self._write_code(s, i+1, bb.loop_latch, ifollow)
+                        else:
+                            # s already traversed
+                            self._emit_goto(s, i+1)
+            else:
+                succs_asc = self.cfg.out_nbrs(bb.if_follow)
+                succs_asc.sort(key=node_to_revpo(self.cfg))
+                for s in succs_asc:
+                    if s != bb.loop_follow:
                         self._write_code(s, i+1, bb.loop_latch, ifollow)
-                    else:
-                        # s already traversed
-                        self._emit_goto(s, i+1)
         # write loop trailer
         if bb.loop_type == LT.pre_tested:
             self._write_bb(bbn, i+1)
             self._write("}", i)
         elif bb.loop_type == LT.post_tested:
-            self._write("} while (%s);" % bb.type_info[2], i)
+            lbb = self.cfg.node_data(bb.loop_latch)
+            positive, _, condition = lbb.type_info
+            if positive:
+                fmt = "} while (%s);"
+            else:
+                fmt = "} while (!(%s));"
+            self._write(fmt % condition, i, "[%.4X]" % lbb.get_last())
         else:
             self._write("}", i)
         if bb.loop_follow not in self.traversed:
@@ -100,7 +121,7 @@
             # loop follow already traversed
             self._emit_goto(bb.loop_follow, i)
 
-    def _write_two_way(self, bbn, i, latch, ifollow):
+    def _write_two_way(self, bbn, i, latch, ifollow, nofollow=False):
         """
         Write code for tree rooted at bbn.
 
@@ -118,11 +139,15 @@
             if t not in self.traversed:
                 # process then clause
                 if t != bb.if_follow:
-                    self._write("if (%s) {" % bb.type_info[2], i)
+                    self._write("if (%s) {" % bb.type_info[2],
+                                i,
+                                "[%.4X]" % bb.get_last())
                     self._write_code(t, i+1, latch, bb.if_follow)
                 else:
                     # then clause empty, negate condition
-                    self._write("if (!(%s)) {" % bb.type_info[2], i)
+                    self._write("if (!(%s)) {" % bb.type_info[2],
+                                i,
+                                "[%.4X]" % bb.get_last())
                     self._write_code(e, i+1, latch, bb.if_follow)
                     empty_then = True
             else:
@@ -136,11 +161,13 @@
                 self._write("} else {", i)
                 self._emit_goto(e, i+1)
             self._write("}", i)
-            if bb.if_follow not in self.traversed:
+            if not nofollow and bb.if_follow not in self.traversed:
                 self._write_code(bb.if_follow, i, latch, ifollow)
         else:
             # no follow..
-            self._write("if (%s) {" % bb.type_info[2], i)
+            self._write("if (%s) {" % bb.type_info[2],
+                        i,
+                        "[%.4X]" % bb.get_last())
             self._write_code(t, i+1, latch, ifollow)
             self._write("} else {", i)
             self._write_code(e, i+1, latch, ifollow)

Modified: tools/branches/gsoc2007-decompiler/finalD/cfg.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/cfg.py	2007-08-20 10:43:07 UTC (rev 28676)
+++ tools/branches/gsoc2007-decompiler/finalD/cfg.py	2007-08-20 14:15:20 UTC (rev 28677)
@@ -117,6 +117,10 @@
         blocks.append(BasicBlock(block_instrs, BT.fall))
     return blocks
 
+def node_to_revpo(g):
+    """Return lambda for Node ID -> reverse post-order number."""
+    return lambda n: g.node_data(n).rev_postorder
+
 def get_then_else(g, n):
     """Return (t, e) of two-way node n in graph g."""
     block = g.node_data(n)
@@ -341,7 +345,9 @@
     lblock = g.node_data(latch)
     hblock = g.node_data(head)
     if lblock.btype == BT.two_way:
-        if hblock.btype == BT.two_way:
+        if head == latch:
+            lt = LT.post_tested
+        elif hblock.btype == BT.two_way:
             if all(hsucc in nodes_in_loop for hsucc in g.out_nbrs(head)):
                 lt = LT.post_tested
             else:
@@ -359,7 +365,8 @@
     """Find loop follow node."""
     hblock = g.node_data(head)
     if hblock.loop_type == LT.pre_tested:
-        if g.out_nbrs(head)[0] in nodes_in_loop:
+        if g.out_nbrs(head)[0] in nodes_in_loop: #\
+#                and g.out_nbrs(head)[1] >= latch:
             lf = g.out_nbrs(head)[1]
         else:
             lf = g.out_nbrs(head)[0]
@@ -471,18 +478,16 @@
 
 def two_way_struct(g):
     """Structure two-way conditionals in g."""
-    def node_to_revpo(n):
-        """Node ID -> reverse post-order number."""
-        return g.node_data(n).rev_postorder
-    def in_head_latch(block):
-        """Return True if block is a loop header or latching node."""
-        return block.loop_latch == block or block.loop_head == block
+    def in_head_latch(n):
+        """Return True if n is a loop header or latching node."""
+        block = g.node_data(n)
+        return block.loop_latch == n or block.loop_head == n
     nodes_desc = g.node_list()[:]
-    nodes_desc.sort(key=node_to_revpo, reverse=True)
+    nodes_desc.sort(key=node_to_revpo(g), reverse=True)
     unresolved = []
     for m in nodes_desc:
         block = g.node_data(m)
-        if block.btype == BT.two_way and not in_head_latch(block):
+        if block.btype == BT.two_way: # and not in_head_latch(m):
             # nodes_desc already sorted, no need for max() below
             dominated_nways = [i for i in g.node_list()
                                if g.node_data(i).idom == m


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