[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