| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- from copy import copy
- from statement import Block
- class BasicBlock(Block):
- edges_to = []
- edges_from = []
- dominates = []
- dominated_by = []
- def add_edge_to(self, block):
- self.edges_to.append(block)
- block.edges_from.append(self)
- def set_dominates(self, block):
- self.dominates.append(block)
- block.dominated_by.append(self)
- def get_gen(self):
- pass
- def get_kill(self):
- pass
- def get_in(self):
- pass
- def get_out(self):
- pass
- def find_leaders(statements):
- """Determine the leaders, which are:
- 1. The first statement.
- 2. Any statement that is the target of a jump.
- 3. Any statement that follows directly follows a jump."""
- leaders = [0]
- jump_target_labels = []
- # Append statements following jumps and save jump target labels
- for i, statement in enumerate(statements[1:]):
- if statement.is_jump():
- leaders.append(i + 2)
- jump_target_labels.append(statement[-1])
- # Append jump targets
- for i, statement in enumerate(statements[1:]):
- if i + 1 not in leaders \
- and statement.is_label() \
- and statement.name in jump_target_labels:
- leaders.append(i + 1)
- leaders.sort()
- return leaders
- def find_basic_blocks(statements):
- """Divide a statement list into basic blocks. Returns a list of basic
- blocks, which are also statement lists."""
- leaders = find_leaders(statements)
- blocks = []
- for i in range(len(leaders) - 1):
- blocks.append(BasicBlock(statements[leaders[i]:leaders[i + 1]]))
- blocks.append(BasicBlock(statements[leaders[-1]:]))
- return blocks
- def generate_flow_graph(blocks):
- """Add flow graph edge administration of an ordered sequence of basic
- blocks."""
- for b in blocks:
- last_statement = b[-1]
- if last_statement.is_jump():
- target = last_statement.jump_target()
- # Compare the target to all leading labels, add an edge if the
- # label matches the jump target
- for other in blocks:
- if other[0].is_label(target):
- b.add_edge_to(other)
- def generate_dominator_tree(nodes):
- """Add dominator administration to the given flow graph nodes."""
- # Dominator of the start node is the start itself
- nodes[0].dom = set([nodes[0]])
- # For all other nodes, set all nodes as the dominators
- for n in nodes[1:]:
- n.dom = set(copy(nodes))
- def pred(n, known=[]):
- """Recursively find all predecessors of a node."""
- direct = filter(lambda x: x not in known, n.edges_from)
- p = copy(direct)
- for ancestor in direct:
- p += pred(ancestor, direct)
- return p
- # Iteratively eliminate nodes that are not dominators
- changed = True
- while changed:
- changed = False
- for n in nodes[1:]:
- old_dom = n.dom
- intersection = lambda p1, p2: p1.dom & p2.dom
- n.dom = set([n]) | reduce(intersection, pred(n), set([]))
- if n.dom != old_dom:
- changed = True
- def idom(d, n):
- """Check if d immediately dominates n."""
- for b in n.dom:
- if b != d and b != n and b in n.dom:
- return False
- return True
- # Build tree using immediate dominators
- for n in nodes:
- for d in n.dom:
- if idom(d, n):
- d.set_dominates(n)
- break
- # statements = parse_file(...)
- # b = find_basic_blocks(statements)
- # generate_flow_graph(b) # nodes now have edges
- # generate_dominator_tree(b) # nodes now have dominators
|