def gen_function(func_attrs, backend_spec):
    """Generates function body.

    Parameters
    ----------
    func_attrs : Dict[str, Any]
        Stores the operation attributes.

    Returns
    -------
    str
        Rendered function body.
    """
    inputs = func_attrs["inputs"]
    x = inputs[0]
    y = func_attrs["outputs"][0]
    x_shape = x._attrs["shape"]

    input_type = backend_spec.dtype_to_backend_type(x._attrs["dtype"])
    output_type = backend_spec.dtype_to_backend_type(y._attrs["dtype"])

    if input_type != output_type:
        raise NotImplementedError("input type must equal to output type")

    split_indices = [idx for idx, mask in enumerate(func_attrs["output_masks"]) if mask]

    # TODO: consider to add profiling paths for tuning
    # elems_per_thread and threads_per_block
    exec_paths = EXEC_COND_TEMPLATE.render(
        indent="  ",
        rank=len(x_shape),
        real_num_splits=len(func_attrs["outputs"]),
        split_indices=split_indices,
        elem_type=input_type,
        elems_per_thread=128,
        threads_per_block=128,
        index_type=backend_spec.index_type,
    )
    header_src = backend_spec.header_src_template.render()
    kernel_src = KERNEL_SRC_TEMPLATE.render(
        index_type=backend_spec.index_type,
        prefix=backend_spec.prefix,
        header_src=header_src,
    )
    return SRC_TEMPLATE.render(
        kernel_src=kernel_src,
        func_name=func_attrs["name"],
        exec_paths=exec_paths,
        index_type=backend_spec.index_type,
        prefix=backend_spec.prefix,
    )
Generates function body.

    Parameters
    ----------
    func_attrs : Dict[str, Any]
        Stores the operation attributes.

    Returns
    -------
    str
        Rendered function body.
    
python/aitemplate/backend/common/split_common.py