summaryrefslogtreecommitdiff
path: root/Data/Array/Accelerate/C.hs
blob: 04e587a948b2c4f092c7e98a972b039651d9b084 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
{-|
Module      : Data.Array.Accelerate.C
Description : Sequential C backend for Accelerate
Copyright   : (c) Tom Smeding, 2021
License     : MIT
Maintainer  : x+accelerate@tomsmeding.com
Stability   : experimental
Portability : non-portable (GHC extensions)

This is a sequential C backend to Accelerate.

Arrays are flattened in the C code: a two-dimensional array with elements of
type @Float@ is encoded as a row-major single-dimensional array of type
@float*@ in C. The indexing is the same as for the @linearIndex@ function from
Accelerate.

Because of the choices made in representing arrays as arguments to the
generated C functions, using this backend may require a (basic) understanding
of how Accelerate internally represents arrays (i.e. the so-called
/representation types/). However, this only really becomes relevant if you use
self-defined data types or sum types like @Maybe@, since otherwise it should be
intuitive enough for casual use. These representation types show up in the
precise form of the argument and output variable descriptors ('CArrTupNames')
returned by 'translateAcc', and they influence the ordering of the arguments to the
C functions.
-}
module Data.Array.Accelerate.C (
    translateAcc,
    CArrTupNames(..), CShNames(..), CArrNames(..),
    C.Name(..), C.Type(..), C.Bits(..),
) where

import qualified Data.Array.Accelerate.Smart as Smart
import qualified Data.Array.Accelerate.Sugar.Array as A hiding ((!))
import qualified Data.Array.Accelerate.Trafo as A

import Data.Array.Accelerate.Trafo.UnDelayed
import qualified Language.C as C
import Language.C.Print (printProgram)
import SC.Afun
import SC.Prelude
import SC.Monad


-- | The function passed should have exactly one argument (that may consist of
-- multiple arrays in a tuple, of course). The string argument determines the
-- name of the top-level generated C function.
--
-- The result consists of:
--
-- 1. C source code (including required prelude) defining, ultimately, a C
--    function that implements the top-level Accelerate array function.
-- 2. The variable names corresponding to the components of the argument of the
--    top-level function.
-- 3. The variable names corresponding to the components of the result of the
--    top-level function. These are out-arguments (i.e. pointer arguments) to
--    that function.
--
-- For an example of how the produced function looks and how the variable name
-- containers describe its arguments, see the documentation of 'CArrTupNames'.
--
-- Note that the variable name descriptors refer to the /representation types/
-- of the input and output of the array function. This essentially means that
-- the type has been converted to a form using only pairs and arrays. (This is
-- the internal representation of data types in Accelerate.)
translateAcc :: (A.Arrays a, A.Arrays b)
             => String
             -> (Smart.Acc a -> Smart.Acc b)
             -> Either String (String, CArrTupNames (A.ArraysR a), CArrTupNames (A.ArraysR b))
translateAcc procname afun = do
    let ast = unDelayedAfun (A.convertAfun afun)
    (auxdefs, fundef, argnames, outnames) <- evalSC (compileAfun1 (C.Name procname) ast)
    let program = C.Program (auxdefs ++ [fundef])
    return (prelude ++ "\n" ++ printProgram program 0 ""
           ,argnames
           ,outnames)