def _dict_from_graph_def(graph, fn_name="main", sg_input_shapes=None):
        """
        Loads a tf.Graph and transform it into dictionary of ParsedTFNodes.
        Potentially contains multiple functions, in such case, recursively
        resolve functions (sub-graphs).

        Parameters
        ----------
        graph: tf.Graph
            TensorFlow graph.
        fn_name: str, optional, defaults to 'main'
            Function name of the graph.
        sg_input_shapes: dict(str: list)
            Dictionary of name and input shapes for functions / sub-graphs.

        Returns
        -------
        dict(str: dict(str: ParsedTFNode))
            Dictionary of function name and dictionary of node name and
            ParsedTFNode object.
        """
        graph_dict = {fn_name: {}}
        graph_inputs = {fn_name: []}
        graph_outputs = {fn_name: []}
        graph_ret = {fn_name: {}}

        for op in graph.get_operations():
            graph_dict[fn_name].update({op.name: ParsedTFNode(op.node_def)})

        for name, sg in graph._functions.items():
            sg_def = context.get_function_def(name)
            if name in sg_input_shapes:
                input_shapes = sg_input_shapes[name]
                input_shapes = input_shapes[-len(sg_def.signature.input_arg):]
                fn_graph = _function_def_to_graph(sg_def, input_shapes=input_shapes)

                graph_dict.update(
                    TF2Loader._dict_from_graph_def(fn_graph, name, sg_input_shapes)[0]
                )
                graph_inputs.update({name: [t.name.split(":")[0] for t in fn_graph.inputs]})
                graph_outputs.update(
                    {name: [t.name.split(":")[0] for t in fn_graph.outputs]}
                )

                # ret is a mapping from the output arg names from `signature` to the
                # outputs from `node_def` that should be returned by the function.
                graph_ret.update({name: sg_def.ret})

        return graph_dict, graph_inputs, graph_outputs, graph_ret

        Loads a tf.Graph and transform it into dictionary of ParsedTFNodes.
        Potentially contains multiple functions, in such case, recursively
        resolve functions (sub-graphs).

        Parameters
        ----------
        graph: tf.Graph
            TensorFlow graph.
        fn_name: str, optional, defaults to 'main'
            Function name of the graph.
        sg_input_shapes: dict(str: list)
            Dictionary of name and input shapes for functions / sub-graphs.

        Returns
        -------
        dict(str: dict(str: ParsedTFNode))
            Dictionary of function name and dictionary of node name and
            ParsedTFNode object.
        
coremltools/converters/mil/frontend/tensorflow2/load.py