Ejemplo n.º 1
0
  def MaybeAddDataFlowElements(
    self, g: nx.MultiDiGraph, tag_hook: typing.Optional[llvm_util.TagHook]
  ) -> None:
    if self.dataflow == "none":
      return

    prefix = lambda s: f"{g.name}_{s}"
    unprefix = lambda s: s[len(f"{g.name}_") :]

    # Collect the edges to add so that we don't modify the graph while
    # iterating.
    edges_to_add: typing.List[typing.Tuple[str, str, str, int]] = []

    for statement, data in nx_utils.StatementNodeIterator(g):
      # TODO(github.com/ChrisCummins/ProGraML/issues/9): Separate !IDENTIFIER
      # and !IMMEDIATE uses.
      def_, uses = GetLlvmStatementDefAndUses(
        data["text"], store_destination_is_def=self.store_destination_is_def
      )
      if def_:  # Data flow out edge.
        def_name = f"{prefix(def_)}_operand"
        edges_to_add.append(
          (statement, def_name, def_name, 0, def_, data, "def")
        )
      for position, identifier in enumerate(uses):  # Data flow in edge.
        identifier_name = f"{prefix(identifier)}_operand"
        edges_to_add.append(
          (
            identifier_name,
            statement,
            identifier_name,
            position,
            identifier,
            data,
            "use",
          )
        )

    for (
      src,
      dst,
      identifier,
      position,
      name,
      original_node,
      dtype,
    ) in edges_to_add:
      g.add_edge(src, dst, flow="data", position=position)
      node = g.nodes[identifier]
      # TODO(github.com/ChrisCummins/ProGraML/issues/9): Separate !IDENTIFIER
      # and !IMMEDIATE nodes.
      node["type"] = "identifier"
      node["name"] = name
      node["text"] = name
      node["x"] = self.dictionary["!IDENTIFIER"]

      if tag_hook is not None:
        other_attrs = tag_hook.OnIdentifier(original_node, node, dtype) or {}
        for attrname, attrval in other_attrs.items():
          node[attrname] = attrval
Ejemplo n.º 2
0
def ToControlFlowGraph(g: nx.MultiDiGraph):
    """Create a new graph with only the statements and control flow edges."""
    # CFGs cannot have parallel edges, so we use only a DiGraph rather than
    # MultiDiGraph.
    cfg = nx.DiGraph()

    for node, data in nx_utils.StatementNodeIterator(g):
        cfg.add_node(node, **data)

    for src, dst, data in nx_utils.ControlFlowEdgeIterator(g):
        cfg.add_edge(src, dst, **data)
Ejemplo n.º 3
0
def FindCallSites(graph, source_function, destination_function):
    """Find the statements in function that call another function."""
    call_sites = []
    for node, data in nx_utils.StatementNodeIterator(graph):
        if data["function"] != source_function:
            continue
        called_function = GetCalledFunctionName(data["text"])
        if not called_function:
            continue
        if called_function == destination_function:
            call_sites.append(node)
    return call_sites
Ejemplo n.º 4
0
def test_every_statement_has_a_predecessor(simple_bytecode: str):
  """Test that every statement (except entry blocks) have control preds."""
  builder = graph_builder.ProGraMLGraphBuilder()
  graph = builder.Build(simple_bytecode)
  entry_blocks = set([node for node, _ in nx_utils.EntryBlockIterator(graph)])
  for node, _ in nx_utils.StatementNodeIterator(graph):
    if not node or node in entry_blocks:
      continue
    for edge in graph.in_edges(node):
      if graph.edges[edge[0], edge[1], 0]["flow"] == programl_pb2.Edge.CONTROL:
        break
    else:
      assert False, f"{node} has no control flow predecessor."
Ejemplo n.º 5
0
def test_StatementNodeIterator(graph):
    assert len(list(nx_utils.StatementNodeIterator(graph))) == 5