{-# LANGUAGE GADTs               #-}
{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators       #-}
{-# OPTIONS_HADDOCK hide #-}
-- |
-- Module      : Data.Array.Accelerate.LLVM.CodeGen.Skeleton
-- Copyright   : [2015..2020] The Accelerate Team
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module Data.Array.Accelerate.LLVM.CodeGen.Skeleton (

  Skeleton(..),

) where

import Data.Array.Accelerate.AST
import Data.Array.Accelerate.Representation.Array
import Data.Array.Accelerate.Representation.Shape
import Data.Array.Accelerate.Representation.Stencil
import Data.Array.Accelerate.Representation.Type
import Data.Array.Accelerate.Type

import Data.Array.Accelerate.LLVM.CodeGen.Environment
import Data.Array.Accelerate.LLVM.CodeGen.Monad
import Data.Array.Accelerate.LLVM.CodeGen.Permute
import Data.Array.Accelerate.LLVM.CodeGen.Stencil
import Data.Array.Accelerate.LLVM.CodeGen.Sugar
import Data.Array.Accelerate.LLVM.Compile.Cache

import Prelude                                                  hiding ( id )


-- | A class covering code generation for all of the primitive array operations.
-- Client backends implement an instance of this class.
--
class Skeleton arch where
  {-# MINIMAL generate, transform
            , fold , foldSeg
            , scan, scan'
            , permute
            , stencil1, stencil2 #-}

  generate      :: UID
                -> Gamma        aenv
                -> ArrayR            (Array sh e)
                -> IRFun1  arch aenv (sh -> e)
                -> CodeGen arch      (IROpenAcc arch aenv (Array sh e))

  transform     :: UID
                -> Gamma        aenv
                -> ArrayR            (Array sh  a)
                -> ArrayR            (Array sh' b)
                -> IRFun1  arch aenv (sh' -> sh)
                -> IRFun1  arch aenv (a -> b)
                -> CodeGen arch      (IROpenAcc arch aenv (Array sh' b))

  map           :: UID
                -> Gamma        aenv
                -> ArrayR            (Array sh a)
                -> TypeR             b
                -> IRFun1  arch aenv (a -> b)
                -> CodeGen arch      (IROpenAcc arch aenv (Array sh b))

  fold          :: UID
                -> Gamma           aenv
                -> ArrayR               (Array sh e)
                -> IRFun2     arch aenv (e -> e -> e)
                -> Maybe (IRExp arch aenv e)
                -> MIRDelayed arch aenv (Array (sh, Int) e)
                -> CodeGen    arch      (IROpenAcc arch aenv (Array sh e))

  foldSeg       :: UID
                -> Gamma           aenv
                -> ArrayR               (Array (sh, Int) e)
                -> IntegralType i
                -> IRFun2     arch aenv (e -> e -> e)
                -> Maybe (IRExp arch aenv e)
                -> MIRDelayed arch aenv (Array (sh, Int) e)
                -> MIRDelayed arch aenv (Segments i)
                -> CodeGen    arch      (IROpenAcc arch aenv (Array (sh, Int) e))

  scan          :: UID
                -> Gamma           aenv
                -> ArrayR               (Array (sh, Int) e)
                -> Direction
                -> IRFun2     arch aenv (e -> e -> e)
                -> Maybe (IRExp arch aenv e)
                -> MIRDelayed arch aenv (Array (sh, Int) e)
                -> CodeGen    arch      (IROpenAcc arch aenv (Array (sh, Int) e))

  scan'         :: UID
                -> Gamma           aenv
                -> ArrayR               (Array (sh, Int) e)
                -> Direction
                -> IRFun2     arch aenv (e -> e -> e)
                -> IRExp      arch aenv e
                -> MIRDelayed arch aenv (Array (sh, Int) e)
                -> CodeGen    arch      (IROpenAcc arch aenv (Array (sh, Int) e, Array sh e))

  permute       :: UID
                -> Gamma             aenv
                -> ArrayR                 (Array sh e)
                -> ShapeR                 sh'
                -> IRPermuteFun arch aenv (e -> e -> e)
                -> IRFun1       arch aenv (sh -> PrimMaybe sh')
                -> MIRDelayed   arch aenv (Array sh e)
                -> CodeGen      arch      (IROpenAcc arch aenv (Array sh' e))

  backpermute   :: UID
                -> Gamma          aenv
                -> ArrayR              (Array sh e)
                -> ShapeR              sh'
                -> IRFun1    arch aenv (sh' -> sh)
                -> CodeGen   arch      (IROpenAcc arch aenv (Array sh' e))

  stencil1      :: UID
                -> Gamma aenv
                -> StencilR sh a stencil
                -> TypeR b
                -> IRFun1     arch aenv (stencil -> b)
                -> IRBoundary arch aenv (Array sh a)
                -> MIRDelayed arch aenv (Array sh a)
                -> CodeGen    arch      (IROpenAcc arch aenv (Array sh b))

  stencil2      :: UID
                -> Gamma aenv
                -> StencilR sh a stencil1
                -> StencilR sh b stencil2
                -> TypeR c
                -> IRFun2 arch aenv (stencil1 -> stencil2 -> c)
                -> IRBoundary arch aenv (Array sh a)
                -> MIRDelayed arch aenv (Array sh a)
                -> IRBoundary arch aenv (Array sh b)
                -> MIRDelayed arch aenv (Array sh b)
                -> CodeGen    arch      (IROpenAcc arch aenv (Array sh c))

  -- Default instances
  -- -----------------
  map           = UID
-> Gamma aenv
-> ArrayR (Array sh a)
-> TypeR b
-> IRFun1 arch aenv (a -> b)
-> CodeGen arch (IROpenAcc arch aenv (Array sh b))
forall arch aenv sh a b.
Skeleton arch =>
UID
-> Gamma aenv
-> ArrayR (Array sh a)
-> TypeR b
-> IRFun1 arch aenv (a -> b)
-> CodeGen arch (IROpenAcc arch aenv (Array sh b))
defaultMap
  backpermute   = UID
-> Gamma aenv
-> ArrayR (Array sh e)
-> ShapeR sh'
-> IRFun1 arch aenv (sh' -> sh)
-> CodeGen arch (IROpenAcc arch aenv (Array sh' e))
forall arch aenv sh e sh'.
Skeleton arch =>
UID
-> Gamma aenv
-> ArrayR (Array sh e)
-> ShapeR sh'
-> IRFun1 arch aenv (sh' -> sh)
-> CodeGen arch (IROpenAcc arch aenv (Array sh' e))
defaultBackpermute


{-# INLINE id #-}
id :: forall arch aenv a. IRFun1 arch aenv (a -> a)
id :: IRFun1 arch aenv (a -> a)
id = (Operands a -> IROpenExp arch ((), a) aenv a)
-> IRFun1 arch aenv (a -> a)
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 Operands a -> IROpenExp arch ((), a) aenv a
forall (m :: * -> *) a. Monad m => a -> m a
return

{-# INLINEABLE defaultMap #-}
defaultMap
    :: Skeleton arch
    => UID
    -> Gamma        aenv
    -> ArrayR (Array sh a)
    -> TypeR b
    -> IRFun1  arch aenv (a -> b)
    -> CodeGen arch      (IROpenAcc arch aenv (Array sh b))
defaultMap :: UID
-> Gamma aenv
-> ArrayR (Array sh a)
-> TypeR b
-> IRFun1 arch aenv (a -> b)
-> CodeGen arch (IROpenAcc arch aenv (Array sh b))
defaultMap UID
uid Gamma aenv
aenv repr :: ArrayR (Array sh a)
repr@(ArrayR ShapeR sh
shr TypeR e
_) TypeR b
tp IRFun1 arch aenv (a -> b)
f
  = UID
-> Gamma aenv
-> ArrayR (Array sh a)
-> ArrayR (Array sh b)
-> IRFun1 arch aenv (sh -> sh)
-> IRFun1 arch aenv (a -> b)
-> CodeGen arch (IROpenAcc arch aenv (Array sh b))
forall arch aenv sh a sh' b.
Skeleton arch =>
UID
-> Gamma aenv
-> ArrayR (Array sh a)
-> ArrayR (Array sh' b)
-> IRFun1 arch aenv (sh' -> sh)
-> IRFun1 arch aenv (a -> b)
-> CodeGen arch (IROpenAcc arch aenv (Array sh' b))
transform UID
uid Gamma aenv
aenv ArrayR (Array sh a)
repr (ShapeR sh -> TypeR b -> ArrayR (Array sh b)
forall sh e. ShapeR sh -> TypeR e -> ArrayR (Array sh e)
ArrayR ShapeR sh
shr TypeR b
tp) IRFun1 arch aenv (sh -> sh)
forall arch aenv a. IRFun1 arch aenv (a -> a)
id IRFun1 arch aenv (a -> b)
f

{-# INLINEABLE defaultBackpermute #-}
defaultBackpermute
    :: Skeleton arch
    => UID
    -> Gamma          aenv
    -> ArrayR (Array sh e)
    -> ShapeR sh'
    -> IRFun1    arch aenv (sh' -> sh)
    -> CodeGen   arch      (IROpenAcc arch aenv (Array sh' e))
defaultBackpermute :: UID
-> Gamma aenv
-> ArrayR (Array sh e)
-> ShapeR sh'
-> IRFun1 arch aenv (sh' -> sh)
-> CodeGen arch (IROpenAcc arch aenv (Array sh' e))
defaultBackpermute UID
uid Gamma aenv
aenv repr :: ArrayR (Array sh e)
repr@(ArrayR ShapeR sh
_ TypeR e
tp) ShapeR sh'
shr IRFun1 arch aenv (sh' -> sh)
p
  = UID
-> Gamma aenv
-> ArrayR (Array sh e)
-> ArrayR (Array sh' e)
-> IRFun1 arch aenv (sh' -> sh)
-> IRFun1 arch aenv (e -> e)
-> CodeGen arch (IROpenAcc arch aenv (Array sh' e))
forall arch aenv sh a sh' b.
Skeleton arch =>
UID
-> Gamma aenv
-> ArrayR (Array sh a)
-> ArrayR (Array sh' b)
-> IRFun1 arch aenv (sh' -> sh)
-> IRFun1 arch aenv (a -> b)
-> CodeGen arch (IROpenAcc arch aenv (Array sh' b))
transform UID
uid Gamma aenv
aenv ArrayR (Array sh e)
repr (ShapeR sh' -> TypeR e -> ArrayR (Array sh' e)
forall sh e. ShapeR sh -> TypeR e -> ArrayR (Array sh e)
ArrayR ShapeR sh'
shr TypeR e
tp) IRFun1 arch aenv (sh' -> sh)
p IRFun1 arch aenv (e -> e)
forall arch aenv a. IRFun1 arch aenv (a -> a)
id