# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
"""Wrapping existing transformations."""
# pylint: disable=invalid-name
from . import _ffi_api
from . import function_pass as _fpass


def Apply(ftransform):
    """Apply ftransform to each function in the Module.

    This function is a thin wrapper around tvm.tir.transform.prim_func_pass

    Parameters
    ----------
    ftransform: tvm.tir.PrimFunc -> tvm.tir.PrimFunc
       The transformation pass.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    # pylint: disable=unused-argument
    def _transform(func, mod, ctx):
        return ftransform(func)
    return _fpass.prim_func_pass(_transform, opt_level=0, name="Apply")


def Filter(fcond):
    """Filter functions by the calling convention attribute.

    Parameters
    ----------
    fcond : tvm.tir.PrimFunc -> bool
        The condition of the filtering.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    # pylint: disable=unused-argument
    def _transform(func, mod, ctx):
        return func if fcond(func) else None
    return _fpass.prim_func_pass(_transform, opt_level=0, name="Filter")


def LowerCustomDatatypes():
    """Lower custom datatypes.

    See tvm::datatypes::Registry for more information on adding custom datatypes.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.LowerCustomDatatypes()


def MakePackedAPI(num_unpacked_params=0):
    """Transform the PrimFuncs in the module to a packed func API.

    Parameters
    ----------
    num_unpacked_params : int
        Number of parameters that we hope to directly pass via normal arguments
        following the PackedFunc input signature.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.MakePackedAPI(num_unpacked_params)


def BindDeviceType():
    """Bind the device type of the function to be
       the device_type specified in the target attribute.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.BindDeviceType()


def SplitHostDevice():
    """Split the function into a host function and device functions.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.SplitHostDevice()


def SkipAssert():
    """Skip assert stmt.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.SkipAssert()


def ThreadSync(storage_scope):
    """ Insert sync between parallel read/write of shared buffers.

    Parameters
    ----------
    storage_scope: str
        The target storage scope.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.ThreadSync(storage_scope)


def LowerThreadAllreduce():
    """Lower cross thread alleduce.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.LowerThreadAllreduce()


def InferFragment():
    """ Infer the TensorCore fragment infomation using tensor intrinsics.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.InferFragment()


def LowerWarpMemory():
    """Lower warp memory access to low-level device related function calls.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.LowerWarpMemory()


def LowerTVMBuiltin():
    """Lower tvm builtin intrinsics.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.LowerTVMBuiltin()


def LowerIntrin():
    """Lower target specific intrinsic calls.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.LowerIntrin()


def LowerDeviceStorageAccessInfo():
    """Lower attached storage access information on device.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass

    Note
    ----
    Run this pass after all storage access analysis finish.
    """
    return _ffi_api.LowerDeviceStorageAccessInfo()


def CombineContextCall():
    """Combine context calls in the host function.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass
    """
    return _ffi_api.CombineContextCall()


def NarrowDataType(target_bits):
    """Narrow down PrimExpr datatype in stmt to target_bits.

    Parameters
    ----------
    target_bits : int
        The target bit configuration.

    Returns
    -------
    fpass : tvm.ir.transform.Pass
        The result pass

    Note
    ----
    Run this pass after StorageFlatten.
    """
    return _ffi_api.NarrowDataType(target_bits)
