def extract_io_from_exir_program(
    exported_program,  # torch.export.ExportedProgram
) -> Tuple[
    List[TensorType],
    List[str],
    Dict[str, torch.Tensor],
    Dict[str, torch.Tensor],
    Dict[str, str],
    Dict[str, str],
]:
    """
    Extract "input"s and "output"s from torch.export.ExportedProgram

    For easy delegation to different backends,
    EXIR lifts constants and buffer references also as inputs, buffer mutations also as outputs,
    so we will extract all user inputs / outputs, constants, buffers and their mutations

    Given:
        exported_program: torch.export.ExportedProgram
    Return:
        user_inputs: List[ct.TensorType]
            list of coremltools input tensor specifications
        user_outputs: List[str]
            list of output names
        constants: Dict[str, torch.Tensor]
            dictionary mapping variable names to torch constant tensors
        buffers: Dict[str, torch.Tensor]
            dictionary mapping torch mutable buffer names to tensors
        input_name_to_source_buffer_name: Dict[str, str]
            dictionary mapping input variable names to underlying mutable buffer names,
            i.e. these input variables are "read" from mutable buffer
        output_name_to_target_buffer_name: Dict[str, str]
            dictionary mapping output variable names to underlying mutable buffer names,
            i.e. these output variables are "written" to mutable buffer
    """
    (
        user_inputs,
        constants,
        buffers,
        input_name_to_source_buffer_name,
    ) = _extract_inputs_from_exir_program(exported_program)
    user_outputs, output_name_to_target_buffer_name = _extract_outputs_from_exir_program(
        exported_program
    )
    return (
        user_inputs,
        user_outputs,
        constants,
        buffers,
        input_name_to_source_buffer_name,
        output_name_to_target_buffer_name,
    )

    Extract "input"s and "output"s from torch.export.ExportedProgram

    For easy delegation to different backends,
    EXIR lifts constants and buffer references also as inputs, buffer mutations also as outputs,
    so we will extract all user inputs / outputs, constants, buffers and their mutations

    Given:
        exported_program: torch.export.ExportedProgram
    Return:
        user_inputs: List[ct.TensorType]
            list of coremltools input tensor specifications
        user_outputs: List[str]
            list of output names
        constants: Dict[str, torch.Tensor]
            dictionary mapping variable names to torch constant tensors
        buffers: Dict[str, torch.Tensor]
            dictionary mapping torch mutable buffer names to tensors
        input_name_to_source_buffer_name: Dict[str, str]
            dictionary mapping input variable names to underlying mutable buffer names,
            i.e. these input variables are "read" from mutable buffer
        output_name_to_target_buffer_name: Dict[str, str]
            dictionary mapping output variable names to underlying mutable buffer names,
            i.e. these output variables are "written" to mutable buffer
    
coremltools/converters/mil/frontend/torch/exir_utils.py