def gen_function(
    func_attrs,
    backend_spec,
    elems_per_thread=8,
    output_offset=0,
    update_output_shape=True,
    element_func=None,
    element_func_def=None,
    extra_header_template=None,
):
    """Generates function body.

    Parameters
    ----------
    func_attrs : Dict[str, Any]
        Stores the operation attributes.
    backend_spec: dataclass
        Backend specification.
    elems_per_thread: int
        Per thread elements.
    update_output_shape: bool
        Whether to update output shape, by default True.
    element_func: str
        Attributes for ease of tanh concatenate fusion, default is None.
    element_func_def: str
        Implmentation for fast_tanh, default is None.
    extra_header_template: str
        Header for fast_tanh, default is None.


    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")

    # TODO: consider to add profiling paths for tuning
    # elems_per_thread and threads_per_block
    exec_paths = EXEC_COND_TEMPLATE.render(
        indent="  ",
        num_inputs=len(inputs),
        rank=len(x_shape),
        elem_type=input_type,
        elems_per_thread=elems_per_thread,
        threads_per_block=128,
        output_offset=output_offset,
    )

    shape_func = SHAPE_UPDATE_FUNC.render(
        indent="  ",
        update_output_shape=update_output_shape,
        index_type=backend_spec.index_type,
    )
    extra_header = (
        extra_header_template.render(element_func_def=element_func_def)
        if extra_header_template is not None
        else ""
    )
    header_src = backend_spec.header_src_template.render(extra_header=extra_header)
    kernel_src = KERNEL_SRC_TEMPLATE.render(
        element_func=element_func,
        element_func_def=element_func_def,
        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"],
        shape_function=shape_func,
        exec_paths=exec_paths,
        index_type=backend_spec.index_type,
        prefix=backend_spec.prefix,
        header_src=header_src,
    )
Generates function body.

Parameters
----------
func_attrs : Dict[str, Any]
Stores the operation attributes.
backend_spec: dataclass
Backend specification.
elems_per_thread: int
Per thread elements.
update_output_shape: bool
Whether to update output shape, by default True.
element_func: str
Attributes for ease of tanh concatenate fusion, default is None.
element_func_def: str
Implmentation for fast_tanh, default is None.
extra_header_template: str
Header for fast_tanh, default is None.


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