def gen_function_call(func_attrs, indent="  ") -> str:
    """
    Generate function call.

    Returns
    -------
    str
        The function call string
    """
    backend_spec = CUDASpec()
    x, mask = func_attrs["inputs"]
    y = func_attrs["outputs"][0]

    dtype = backend_spec.dtype_to_backend_type(func_attrs["inputs"][0]._attrs["dtype"])

    input_ptr = backend_spec.cast_to_ptr_template.render(
        name=x._attrs["name"],
        dtype=dtype,
    )
    output_ptr = backend_spec.cast_to_ptr_template.render(
        name=y._attrs["name"],
        dtype=dtype,
    )
    mask_ptr = backend_spec.cast_to_ptr_template.render(
        name=mask._attrs["name"],
        dtype="bool",
    )
    max_shape = func_attrs["max_shape"]
    # Number of nonmasked elements, i.e. size of the output
    num_nonmasked_ptr = "&" + y._attrs["shape"][0]._attrs["name"]

    return FUNC_CALL_TEMPLATE.render(
        indent=indent,
        func_name=func_attrs["name"],
        input_name=x._attrs["name"],
        num_nonmasked=num_nonmasked_ptr,
        max_dims="{" + ",".join([dim._attrs["name"] for dim in max_shape]) + "}",
        max_rank=len(max_shape),
        need_broadcast=x._attrs["shape"] != mask._attrs["shape"],
        dynamic_dims_call=gen_dynamic_dim_str(
            index_type=backend_spec.index_type,
            dynamic_dims=get_dynamic_dims(x.shape(), mask.shape()),
            has_type=False,
        ),
        output_ptr=output_ptr,
        input_ptr=input_ptr,
        mask_ptr=mask_ptr,
        index_type=backend_spec.index_type,
    )

    Generate function call.

    Returns
    -------
    str
        The function call string
    
python/aitemplate/backend/cuda/tensor/masked_select.py