nodes: 0, module; 1, function_definition; 2, function_name:find_merge_points; 3, parameters; 4, comment:# pylint:disable=unused-argument; 5, block; 6, identifier:function_addr; 7, identifier:function_endpoints; 8, identifier:graph; 9, expression_statement; 10, expression_statement; 11, for_statement; 12, expression_statement; 13, expression_statement; 14, return_statement; 15, comment:"""
          Given a local transition graph of a function, find all merge points inside, and then perform a
          quasi-topological sort of those merge points.
  
          A merge point might be one of the following cases:
          - two or more paths come together, and ends at the same address.
          - end of the current function
  
          :param int function_addr: Address of the function.
          :param list function_endpoints: Endpoints of the function. They typically come from Function.endpoints.
          :param networkx.DiGraph graph: A local transition graph of a function. Normally it comes from Function.graph.
          :return: A list of ordered addresses of merge points.
          :rtype: list
          """; 16, assignment; 17, identifier:node; 18, call; 19, block; 20, assignment; 21, assignment; 22, identifier:addrs; 23, identifier:merge_points; 24, call; 25, attribute; 26, argument_list; 27, if_statement; 28, identifier:ordered_merge_points; 29, call; 30, identifier:addrs; 31, list_comprehension; 32, identifier:set; 33, argument_list; 34, identifier:graph; 35, identifier:nodes; 36, comparison_operator:graph.in_degree(node) > 1; 37, block; 38, attribute; 39, argument_list; 40, attribute; 41, for_in_clause; 42, call; 43, integer:1; 44, expression_statement; 45, identifier:CFGUtils; 46, identifier:quasi_topological_sort_nodes; 47, identifier:graph; 48, identifier:merge_points; 49, identifier:n; 50, identifier:addr; 51, identifier:n; 52, identifier:ordered_merge_points; 53, attribute; 54, argument_list; 55, call; 56, identifier:graph; 57, identifier:in_degree; 58, identifier:node; 59, attribute; 60, argument_list; 61, identifier:merge_points; 62, identifier:add; 63, identifier:node
code: def find_merge_points(function_addr, function_endpoints, graph):  # pylint:disable=unused-argument
          """
          Given a local transition graph of a function, find all merge points inside, and then perform a
          quasi-topological sort of those merge points.
  
          A merge point might be one of the following cases:
          - two or more paths come together, and ends at the same address.
          - end of the current function
  
          :param int function_addr: Address of the function.
          :param list function_endpoints: Endpoints of the function. They typically come from Function.endpoints.
          :param networkx.DiGraph graph: A local transition graph of a function. Normally it comes from Function.graph.
          :return: A list of ordered addresses of merge points.
          :rtype: list
          """
  
          merge_points = set()
  
          for node in graph.nodes():
              if graph.in_degree(node) > 1:
                  merge_points.add(node)
  
          ordered_merge_points = CFGUtils.quasi_topological_sort_nodes(graph, merge_points)
  
          addrs = [n.addr for n in ordered_merge_points]
          return addrs