Ejemplo n.º 1
0
def program_to_text(program):
  """Generate a text (CFG nodes + assignments) version of a program.

  For debugging only.

  Args:
    program: An instance of cfg.Program

  Returns:
    A string representing all of the data for this program.
  """
  s = StringIO.StringIO()
  seen = set()
  for node in utils.order_nodes(program.cfg_nodes):
    seen.add(node)
    s.write("%s\n" % node.Label())
    s.write("  From: %s\n" % ", ".join(n.Label() for n in node.incoming))
    s.write("  To: %s\n" % ", ".join(n.Label() for n in node.outgoing))
    s.write("\n")
    variables = set(value.variable for value in node.bindings)
    for var in sorted(variables, key=lambda v: v.id):
      # If a variable is bound in more than one node then it will be listed
      # redundantly multiple times.  One alternative would be to only list the
      # values that occur in the given node, and then also list the other nodes
      # that assign the same variable.

      # Write the variable, indenting by two spaces.
      s.write("  %s\n" % _pretty_variable(var).replace("\n", "\n  "))
    s.write("\n")

  return s.getvalue()
Ejemplo n.º 2
0
def program_to_text(program):
  """Generate a text (CFG nodes + assignments) version of a program.

  For debugging only.

  Args:
    program: An instance of cfg.Program

  Returns:
    A string representing all of the data for this program.
  """
  s = StringIO.StringIO()
  seen = set()
  for node in utils.order_nodes(program.cfg_nodes):
    seen.add(node)
    s.write("%s\n" % node.Label())
    s.write("  From: %s\n" % ", ".join(n.Label() for n in node.incoming))
    s.write("  To: %s\n" % ", ".join(n.Label() for n in node.outgoing))
    s.write("\n")
    variables = set(value.variable for value in node.bindings)
    for var in sorted(variables, key=lambda v: v.id):
      # If a variable is bound in more than one node then it will be listed
      # redundantly multiple times.  One alternative would be to only list the
      # values that occur in the given node, and then also list the other nodes
      # that assign the same variable.

      # Write the variable, indenting by two spaces.
      s.write("  %s\n" % _pretty_variable(var).replace("\n", "\n  "))
    s.write("\n")

  return s.getvalue()
Ejemplo n.º 3
0
 def testOrderNodes4(self):
     # n1 --> n3 --> n2
     # ^      |
     # +------+
     n1 = self.prog.NewCFGNode("n1")
     n3 = n1.ConnectNew("n3")
     n2 = n3.ConnectNew("n2")
     n3.ConnectTo(n1)
     order = utils.order_nodes([n1, n2, n3])
     self.assertItemsEqual([n1, n3, n2], order)
Ejemplo n.º 4
0
 def testOrderNodes4(self):
   # n1 --> n3 --> n2
   # ^      |
   # +------+
   n1 = self.prog.NewCFGNode("n1")
   n3 = n1.ConnectNew("n3")
   n2 = n3.ConnectNew("n2")
   n3.ConnectTo(n1)
   order = utils.order_nodes([n1, n2, n3])
   self.assertItemsEqual([n1, n3, n2], order)
Ejemplo n.º 5
0
 def testOrderNodes6(self):
     #  +-------------------+
     #  |                   v
     # n1 --> n2 --> n3 --> n5
     #        ^      |
     #        +------n4
     n1 = self.prog.NewCFGNode("n1")
     n2 = n1.ConnectNew("n2")
     n3 = n2.ConnectNew("n3")
     n4 = n3.ConnectNew("n4")
     n4.ConnectTo(n2)
     n5 = n3.ConnectNew("n5")
     n1.ConnectTo(n5)
     order = utils.order_nodes([n1, n5, n4, n3, n2])
     self.assertItemsEqual([n1, n2, n3, n4, n5], order)
Ejemplo n.º 6
0
 def testOrderNodes6(self):
   #  +-------------------+
   #  |                   v
   # n1 --> n2 --> n3 --> n5
   #        ^      |
   #        +------n4
   n1 = self.prog.NewCFGNode("n1")
   n2 = n1.ConnectNew("n2")
   n3 = n2.ConnectNew("n3")
   n4 = n3.ConnectNew("n4")
   n4.ConnectTo(n2)
   n5 = n3.ConnectNew("n5")
   n1.ConnectTo(n5)
   order = utils.order_nodes([n1, n5, n4, n3, n2])
   self.assertItemsEqual([n1, n2, n3, n4, n5], order)
Ejemplo n.º 7
0
def program_to_pseudocode(program):
  """Generate a pseudocode (CFG nodes + assignments) version of a program.

  For debugging only.

  Args:
    program: An instance of cfg.Program

  Returns:
    A string, the "pseudocode" of this program.
  """
  s = StringIO.StringIO()
  seen = set()
  for node in utils.order_nodes(program.cfg_nodes):
    seen.add(node)
    s.write("<%d>%s\n" % (node.id, node.name))
    for value in node.values:
      s.write("  %s\n" % pretty_assignment(value))
      overwritten = False
      for cfg_node, source_sets in value.origins:
        if node != cfg_node:
          overwritten = True
          continue
        if source_sets == [set()]:
          pass  # don't print trivially true source_sets
        else:
          src = utils.pretty_dnf([[pretty_assignment(v, short=True)
                                   for v in source_set]
                                  for source_set in source_sets])
          s.write("    from: %s\n" % src)
      if overwritten:
        s.write("    (also set to this value in other nodes)\n")
    for out in node.outgoing:
      s.write("  jump to <%d>%s\n" % (out.id, out.name))

  # "stray" nodes are nodes that are unreachable in the CFG.
  stray_nodes = set(program.cfg_nodes) - seen
  if stray_nodes:
    s.write("Stray nodes:\n")
    for node in stray_nodes:
      s.write("<%d>%s\n" % (node.id, node.name))

  return s.getvalue()
Ejemplo n.º 8
0
def program_to_pseudocode(program):
  """Generate a pseudocode (CFG nodes + assignments) version of a program.

  For debugging only.

  Args:
    program: An instance of cfg.Program

  Returns:
    A string, the "pseudocode" of this program.
  """
  s = StringIO.StringIO()
  seen = set()
  for node in utils.order_nodes(program.cfg_nodes):
    seen.add(node)
    s.write("<%d>%s\n" % (node.id, node.name))
    for value in node.values:
      s.write("  %s\n" % pretty_assignment(value))
      overwritten = False
      for cfg_node, source_sets in value.origins:
        if node != cfg_node:
          overwritten = True
          continue
        if source_sets == [set()]:
          pass  # don't print trivially true source_sets
        else:
          src = utils.pretty_dnf([[pretty_assignment(v, short=True)
                                   for v in source_set]
                                  for source_set in source_sets])
          s.write("    from: %s\n" % src)
      if overwritten:
        s.write("    (also set to this value in other nodes)\n")
    for out in node.outgoing:
      s.write("  jump to <%d>%s\n" % (out.id, out.name))

  # "stray" nodes are nodes that are unreachable in the CFG.
  stray_nodes = set(program.cfg_nodes) - seen
  if stray_nodes:
    s.write("Stray nodes:\n")
    for node in stray_nodes:
      s.write("<%d>%s\n" % (node.id, node.name))

  return s.getvalue()
Ejemplo n.º 9
0
 def testOrderNodes7(self):
     #  +---------------------------------+
     #  |                                 v
     # n1 --> n2 --> n3 --> n4 --> n5 --> n6
     #        ^      |      ^      |
     #        |      v      |      v
     #        +------n7     +------n8
     n1 = self.prog.NewCFGNode("n1")
     n2 = n1.ConnectNew("n2")
     n3 = n2.ConnectNew("n3")
     n4 = n3.ConnectNew("n4")
     n5 = n4.ConnectNew("n5")
     n6 = n5.ConnectNew("n6")
     n7 = n3.ConnectNew("n7")
     n7.ConnectTo(n2)
     n8 = n5.ConnectNew("n8")
     n8.ConnectTo(n4)
     n1.ConnectTo(n6)
     order = utils.order_nodes([n1, n2, n3, n4, n5, n6, n7, n8])
     self.assertItemsEqual([n1, n2, n3, n7, n4, n5, n8, n6], order)
Ejemplo n.º 10
0
 def testOrderNodes7(self):
   #  +---------------------------------+
   #  |                                 v
   # n1 --> n2 --> n3 --> n4 --> n5 --> n6
   #        ^      |      ^      |
   #        |      v      |      v
   #        +------n7     +------n8
   n1 = self.prog.NewCFGNode("n1")
   n2 = n1.ConnectNew("n2")
   n3 = n2.ConnectNew("n3")
   n4 = n3.ConnectNew("n4")
   n5 = n4.ConnectNew("n5")
   n6 = n5.ConnectNew("n6")
   n7 = n3.ConnectNew("n7")
   n7.ConnectTo(n2)
   n8 = n5.ConnectNew("n8")
   n8.ConnectTo(n4)
   n1.ConnectTo(n6)
   order = utils.order_nodes([n1, n2, n3, n4, n5, n6, n7, n8])
   self.assertItemsEqual([n1, n2, n3, n7, n4, n5, n8, n6], order)
Ejemplo n.º 11
0
def compute_order(bytecode):
    """Split bytecode into blocks and order the blocks.

  This builds an "ancestor first" ordering of the basic blocks of the bytecode.

  Args:
    bytecode: A list of instances of opcodes.Opcode. (E.g. returned from
      opcodes.dis())

  Returns:
    A list of Block instances.
  """
    blocks = _split_bytecode(bytecode)
    first_op_to_block = {block.code[0]: block for block in blocks}
    for i, block in enumerate(blocks):
        next_block = blocks[i + 1] if i < len(blocks) - 1 else None
        last_op = block.code[-1]
        if next_block and not last_op.no_next():
            block.connect_outgoing(next_block)
        if last_op.target:
            block.connect_outgoing(first_op_to_block[last_op.target])
        if last_op.block_target:
            block.connect_outgoing(first_op_to_block[last_op.block_target])
    return utils.order_nodes(blocks)
Ejemplo n.º 12
0
def compute_order(bytecode):
  """Split bytecode into blocks and order the blocks.

  This builds an "ancestor first" ordering of the basic blocks of the bytecode.

  Args:
    bytecode: A list of instances of opcodes.Opcode. (E.g. returned from
      opcodes.dis())

  Returns:
    A list of Block instances.
  """
  blocks = _split_bytecode(bytecode)
  first_op_to_block = {block.code[0]: block for block in blocks}
  for i, block in enumerate(blocks):
    next_block = blocks[i + 1] if i < len(blocks) - 1 else None
    last_op = block.code[-1]
    if next_block and not last_op.no_next():
      block.connect_outgoing(next_block)
    if last_op.target:
      block.connect_outgoing(first_op_to_block[last_op.target])
    if last_op.block_target:
      block.connect_outgoing(first_op_to_block[last_op.block_target])
  return utils.order_nodes(blocks)
Ejemplo n.º 13
0
 def testOrderNodes2(self):
     # n1   n2(dead)
     n1 = self.prog.NewCFGNode("n1")
     n2 = self.prog.NewCFGNode("n2")
     order = utils.order_nodes([n1, n2])
     self.assertItemsEqual([n1], order)
Ejemplo n.º 14
0
 def testOrderNodes1(self):
     # n1 --> n2
     n1 = self.prog.NewCFGNode("n1")
     n2 = n1.ConnectNew("n2")
     order = utils.order_nodes([n1, n2])
     self.assertItemsEqual([n1, n2], order)
Ejemplo n.º 15
0
 def testOrderNodes0(self):
     order = utils.order_nodes([])
     self.assertItemsEqual(order, [])
Ejemplo n.º 16
0
 def testOrderNodes0(self):
   order = utils.order_nodes([])
   self.assertItemsEqual(order, [])
Ejemplo n.º 17
0
 def testOrderNodes1(self):
   # n1 --> n2
   n1 = self.prog.NewCFGNode("n1")
   n2 = n1.ConnectNew("n2")
   order = utils.order_nodes([n1, n2])
   self.assertItemsEqual([n1, n2], order)
Ejemplo n.º 18
0
 def testOrderNodes2(self):
   # n1   n2(dead)
   n1 = self.prog.NewCFGNode("n1")
   n2 = self.prog.NewCFGNode("n2")
   order = utils.order_nodes([n1, n2])
   self.assertItemsEqual([n1], order)