[Scummvm-cvs-logs] SF.net SVN: scummvm: [28659] tools/branches/gsoc2007-decompiler/finalD
brixxie at users.sourceforge.net
brixxie at users.sourceforge.net
Sun Aug 19 07:12:26 CEST 2007
Revision: 28659
http://scummvm.svn.sourceforge.net/scummvm/?rev=28659&view=rev
Author: brixxie
Date: 2007-08-18 22:12:26 -0700 (Sat, 18 Aug 2007)
Log Message:
-----------
added structured output, buggy branching output
Modified Paths:
--------------
tools/branches/gsoc2007-decompiler/finalD/cfg.py
tools/branches/gsoc2007-decompiler/finalD/decompiler.py
Added Paths:
-----------
tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py
Added: tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py (rev 0)
+++ tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py 2007-08-19 05:12:26 UTC (rev 28659)
@@ -0,0 +1,192 @@
+"""Pseudo code formatting from control flow graphs."""
+
+from cfg import BT, LT, get_then_else
+from iformat import is_jump
+
+
+class PseudoCode:
+ """Control flow graph -> pseudo code translation."""
+
+ def __init__(self, cfg, decoded, indent=2):
+ """
+ Initialize PseudoCode object.
+
+ Arguments:
+ cfg -- a control flow graph with structuring information
+ decoded -- a dictionary of offset -> Instr
+ indent -- indentation by indent spaces each (default 4)
+ """
+ self.cfg = cfg
+ self.decoded = decoded
+ self.indent = indent
+
+ self.traversed = []
+ """Hold nodes we already traversed."""
+
+ def generate_code(self):
+ """Generate code for cfg."""
+ self._write_code(0, 0, None, None)
+
+ def _write(self, code, i, pre="[****]"):
+ """Write code at indentation level i."""
+ print "%s %s%s" % (pre, " "*(i*self.indent), code)
+
+ def _write_bb(self, bbn, i):
+ """
+ Write code for bbn.
+
+ Arguments:
+ bbn -- node in the control flow graph
+ i -- current indentation level
+ """
+ for instr_off in self.cfg.node_data(bbn).instrs:
+ instr = self.decoded[instr_off]
+ if not is_jump(instr):
+ self._write("%s;" % instr, i, "[%.4X]" % instr_off)
+
+ def _emit_goto(self, n, i):
+ """Emit goto to n."""
+ off = self.cfg.node_data(n).get_first()
+ self._write("goto %.4X;" % off, i)
+
+ def _write_loop(self, bbn, i, latch, ifollow):
+ """
+ Write code for loop structure rooted at bb.
+
+ Arguments:
+ bbn -- node in the control flow graph
+ i -- current indentation level
+ latch -- latching node of enclosing loop structure (or None)
+ ifollow -- follow node of the enclosing if structure (or None)
+ """
+ self.traversed.append(bbn)
+ bb = self.cfg.node_data(bbn)
+ # 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)
+ else:
+ self._write("while (!(%s)) {" % bb.type_info[2], i)
+ elif bb.loop_type == LT.post_tested:
+ self._write("do {", i)
+ self._write_bb(bbn, i+1)
+ else:
+ self._write("for (;;) {", i)
+ self._write_bb(bbn, i+1)
+ if bb == latch:
+ 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:
+ 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)
+ else:
+ self._write("}", i)
+ if bb.loop_follow not in self.traversed:
+ self._write_code(bb.loop_follow, i, latch, ifollow)
+ else:
+ # loop follow already traversed
+ self._emit_goto(bb.loop_follow, i)
+
+ # TODO: buggy deluxe
+ def _write_two_way(self, bbn, i, latch, ifollow):
+ """
+ Write code for tree rooted at bbn.
+
+ Arguments:
+ bbn -- node in the control flow graph
+ i -- current indentation level
+ latch -- latching node of enclosing loop structure (or None)
+ ifollow -- follow node of the enclosing if structure (or None)
+ """
+ bb = self.cfg.node_data(bbn)
+ t, e = get_then_else(self.cfg, bbn)
+ self._write_bb(bbn, i)
+ if bb.if_follow:
+ empty_then = False
+ 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_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_code(e, i+1, latch, bb.if_follow)
+ empty_then = True
+ else:
+ # t already traversed, emit goto
+ self._emit_goto(t, i)
+ if e not in self.traversed:
+ if e != bb.if_follow:
+ self._write("} else {", i)
+ self._write_code(e, i+1, latch, bb.if_follow)
+ elif not empty_then:
+ self._write("} else {", i)
+ self._emit_goto(e, i+1)
+ self._write("}", i)
+ if 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_code(t, i+1, latch, ifollow)
+ self._write("} else {", i)
+ self._write_code(e, i+1, latch, ifollow)
+ self._write("}", i)
+
+ def _write_one_way(self, bbn, i, latch, ifollow):
+ """
+ Write code for graph rooted at bbn.
+
+ Arguments:
+ bbn -- node in the control flow graph
+ i -- current indentation level
+ latch -- latching node of enclosing loop structure (or None)
+ ifollow -- follow node of the enclosing if structure (or None)
+ """
+ self._write_bb(bbn, i)
+ succs = self.cfg.out_nbrs(bbn)
+ if not succs:
+ return
+ s = succs[0]
+ if s not in self.traversed:
+ self._write_code(s, i, latch, ifollow)
+ else:
+ self._emit_goto(s, i)
+
+ def _write_code(self, bbn, i, latch, ifollow):
+ """
+ Write code for graph rooted at bbn.
+
+ Arguments:
+ bbn -- node in the control flow graph
+ i -- current indentation level
+ latch -- latching node of enclosing loop structure (or None)
+ ifollow -- follow node of the enclosing if structure (or None)
+ """
+ if bbn == None:
+ return
+ bb = self.cfg.node_data(bbn)
+ if bb == ifollow or bbn in self.traversed:
+ return
+ self.traversed.append(bbn)
+ if bb.loop_head == bbn:
+ # bbn is a loop header
+ self._write_loop(bbn, i, latch, ifollow)
+ elif bb.btype == BT.two_way:
+ self._write_two_way(bbn, i, latch, ifollow)
+ else:
+ self._write_one_way(bbn, i, latch, ifollow)
Property changes on: tools/branches/gsoc2007-decompiler/finalD/PseudoCode.py
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Modified: tools/branches/gsoc2007-decompiler/finalD/cfg.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/cfg.py 2007-08-18 21:02:30 UTC (rev 28658)
+++ tools/branches/gsoc2007-decompiler/finalD/cfg.py 2007-08-19 05:12:26 UTC (rev 28659)
@@ -474,7 +474,7 @@
block.idom = 0
def two_way_struct(g):
- """Structure two-way conditionals."""
+ """Structure two-way conditionals in g."""
def node_to_revpo(n):
"""Node ID -> reverse post-order number."""
return g.node_data(n).rev_postorder
Modified: tools/branches/gsoc2007-decompiler/finalD/decompiler.py
===================================================================
--- tools/branches/gsoc2007-decompiler/finalD/decompiler.py 2007-08-18 21:02:30 UTC (rev 28658)
+++ tools/branches/gsoc2007-decompiler/finalD/decompiler.py 2007-08-19 05:12:26 UTC (rev 28659)
@@ -2,9 +2,11 @@
import disasm
import scumm
-import bytecode
+#import bytecode
import cfg
+from PseudoCode import PseudoCode
+
import array
from optparse import OptionParser
@@ -50,11 +52,13 @@
cfg.loop_struct(dseq)
cfg.two_way_struct(graph)
cfg.comp_conds_struct(graph)
- for nid in graph.node_list():
- block = graph.node_data(nid)
- print block
- for instr in block.instrs:
- print decoded[instr]
+# for nid in graph.node_list():
+# block = graph.node_data(nid)
+# print block
+# for instr in block.instrs:
+# print decoded[instr]
+ pc = PseudoCode(graph, decoded)
+ pc.generate_code()
else:
decoded_tuples = decoded.items()
decoded_tuples.sort(key=lambda t: t[0])
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