| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- from copy import copy
- from statement import Block
- class BasicBlock(Block):
- def __init__(self, statements=[]):
- Block.__init__(self, statements)
- self.edges_to = []
- self.edges_from = []
- self.dominates = []
- self.dominated_by = []
- def add_edge_to(self, block):
- if block not in self.edges_to:
- self.edges_to.append(block)
- block.edges_from.append(self)
- def set_dominates(self, block):
- if block not in self.dominates:
- 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 i, b in enumerate(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)
- # A branch instruction also creates an edge to the next block
- if last_statement.is_branch() and i < len(blocks) - 1:
- b.add_edge_to(blocks[i + 1])
- elif i < len(blocks) - 1:
- b.add_edge_to(blocks[i + 1])
- #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
- class Dag:
- def __init__(self, block):
- """Create the Directed Acyclic Graph of all binary operations in a
- basic block."""
- self.nodes = []
- for s in block:
- if s.is_command('move') or s.is_monop():
- rd, rs = s
- y = self.find_reg_node(rs)
- self.find_op_node(s.name, rd, y)
- elif s.is_binop():
- rd, rs, rt = s
- y = self.find_reg_node(rs)
- z = self.find_reg_node(rt)
- self.find_op_node(s.name, rd, y, z)
- def find_reg_node(self, reg):
- for n in self.nodes:
- if reg in n.reg:
- return n
- node = DagLeaf(reg)
- self.nodes.append(node)
- return node
- def find_op_node(self, op, rd, *args):
- for n in self.nodes:
- if n.op == op and n.nodes == args:
- n.labels.append(rd)
- return n
- node = DagNode(op, rd, *args)
- self.nodes.append(node)
- return node
- class DagNode:
- def __init__(self, op, label, *args):
- self.op = op
- self.labels = [label]
- self.nodes = args
- class DagLeaf:
- def __init__(self, reg):
- self.reg = reg
|