dataflow.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. from copy import copy
  2. from statement import Block
  3. class BasicBlock(Block):
  4. def __init__(self, statements=[], dummy=False):
  5. Block.__init__(self, statements)
  6. self.edges_to = []
  7. self.edges_from = []
  8. self.dominates = []
  9. self.dominated_by = []
  10. self.dummy = dummy
  11. def add_edge_to(self, block):
  12. if block not in self.edges_to:
  13. self.edges_to.append(block)
  14. block.edges_from.append(self)
  15. def set_dominates(self, block):
  16. if block not in self.dominates:
  17. self.dominates.append(block)
  18. block.dominated_by.append(self)
  19. def find_leaders(statements, return_jump_targets=False):
  20. """
  21. - Determine the leaders, which are:
  22. 1. The first statement.
  23. 2. Any statement that is the target of a jump.
  24. 3. Any statement that follows directly follows a jump.
  25. - To determine the leaders, a list of known jump targets is created. This
  26. list can also be returned for later use.
  27. """
  28. leaders = [0]
  29. jump_targets = []
  30. # Append statements following jumps and save jump target labels
  31. for i, statement in enumerate(statements[1:]):
  32. if statement.is_jump():
  33. leaders.append(i + 2)
  34. jump_targets.append(statement[-1])
  35. # Append jump targets
  36. for i, statement in enumerate(statements[1:]):
  37. if i + 1 not in leaders \
  38. and statement.is_label() \
  39. and statement.name in jump_targets:
  40. leaders.append(i + 1)
  41. leaders.sort()
  42. return (leaders, jump_targets) if return_jump_targets else leaders
  43. def find_basic_blocks(statements, return_jump_targets=False):
  44. """Divide a statement list into basic blocks. Returns a list of basic
  45. blocks, which are also statement lists."""
  46. leaders, jump_targets = find_leaders(statements, True)
  47. blocks = []
  48. for i in xrange(len(leaders) - 1):
  49. blocks.append(BasicBlock(statements[leaders[i]:leaders[i + 1]]))
  50. blocks.append(BasicBlock(statements[leaders[-1]:]))
  51. # Add a target block for unknown jump targets
  52. #blocks.append(BasicBlock([], dummy=True))
  53. return (blocks, jump_targets) if return_jump_targets else blocks
  54. def generate_flow_graph(blocks):
  55. """Add flow graph edge administration of an ordered sequence of basic
  56. blocks."""
  57. #dummy_block = blocks[-1]
  58. for i, b in enumerate(blocks):
  59. last_statement = b[-1]
  60. if last_statement.is_jump():
  61. target = last_statement.jump_target()
  62. # Compare the target to all leading labels, add an edge if the
  63. # label matches the jump target
  64. #target_found = False
  65. for other in blocks:
  66. if other[0].is_label(target):
  67. b.add_edge_to(other)
  68. #target_found = True
  69. # If the jump target is outside the program, add an edge to the
  70. # dummy block
  71. #if not target_found:
  72. # b.add_edge_to(dummy_block)
  73. # A branch and jump-and-line instruction also creates an edge to
  74. # the next block
  75. if (last_statement.is_branch() or last_statement.name == 'jal') \
  76. and i < len(blocks) - 1:
  77. b.add_edge_to(blocks[i + 1])
  78. elif i < len(blocks) - 1:
  79. b.add_edge_to(blocks[i + 1])
  80. def pred(block, known=[]):
  81. """Recursively find all predecessors of a node."""
  82. direct = filter(lambda b: b != block and b not in known, block.edges_from)
  83. p = copy(direct)
  84. for predecessor in direct:
  85. p += pred(predecessor, known + direct)
  86. return p
  87. return p
  88. def succ(block, known=[]):
  89. """Recursively find all successors of a node."""
  90. direct = filter(lambda b: b != block and b not in known, block.edges_to)
  91. s = copy(direct)
  92. for successor in direct:
  93. s += succ(successor, known + direct)
  94. return s
  95. return s