{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module Data.Array.Accelerate.LLVM.PTX.Compile.Libdevice (
withLibdeviceNVVM,
withLibdeviceNVPTX,
) where
import LLVM.Context
import qualified LLVM.Module as LLVM
import LLVM.AST as AST
import LLVM.AST.Global as G
import LLVM.AST.Linkage
import Data.Array.Accelerate.LLVM.PTX.Compile.Libdevice.Load
import qualified Data.Array.Accelerate.LLVM.PTX.Debug as Debug
import Foreign.CUDA.Analysis
import Control.Monad
import Data.ByteString ( ByteString )
import Data.ByteString.Short.Char8 ( ShortByteString )
import Data.HashSet ( HashSet )
import Data.List
import Data.Maybe
import Text.Printf
import qualified Data.ByteString.Short.Char8 as S8
import qualified Data.ByteString.Short.Extra as BS
import qualified Data.HashSet as Set
withLibdeviceNVPTX
:: DeviceProperties
-> Context
-> Module
-> (LLVM.Module -> IO a)
-> IO a
withLibdeviceNVPTX :: DeviceProperties -> Context -> Module -> (Module -> IO a) -> IO a
withLibdeviceNVPTX DeviceProperties
dev Context
ctx Module
ast Module -> IO a
next =
case HashSet ShortByteString -> Bool
forall a. HashSet a -> Bool
Set.null HashSet ShortByteString
externs of
Bool
True -> Context -> Module -> (Module -> IO a) -> IO a
forall a. Context -> Module -> (Module -> IO a) -> IO a
LLVM.withModuleFromAST Context
ctx Module
ast Module -> IO a
next
Bool
False ->
Context -> Module -> (Module -> IO a) -> IO a
forall a. Context -> Module -> (Module -> IO a) -> IO a
LLVM.withModuleFromAST Context
ctx Module
ast ((Module -> IO a) -> IO a) -> (Module -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Module
mdl ->
Context -> Module -> (Module -> IO a) -> IO a
forall a. Context -> Module -> (Module -> IO a) -> IO a
LLVM.withModuleFromAST Context
ctx Module
forall a. NVVMReflect a => a
nvvmReflect ((Module -> IO a) -> IO a) -> (Module -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Module
refl ->
Context -> Module -> (Module -> IO a) -> IO a
forall a. Context -> Module -> (Module -> IO a) -> IO a
LLVM.withModuleFromAST Context
ctx (HashSet ShortByteString -> Module -> Module
internalise HashSet ShortByteString
externs Module
libdev) ((Module -> IO a) -> IO a) -> (Module -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Module
libd -> do
Module -> Module -> IO ()
LLVM.linkModules Module
mdl Module
refl
Module -> Module -> IO ()
LLVM.linkModules Module
mdl Module
libd
Flag -> String -> IO ()
Debug.traceIO Flag
Debug.dump_cc String
msg
Module -> IO a
next Module
mdl
where
libdev :: Module
libdev = (Compute -> Module
forall a. Libdevice a => Compute -> a
libdevice Compute
arch) { moduleTargetTriple :: Maybe ShortByteString
moduleTargetTriple = Module -> Maybe ShortByteString
moduleTargetTriple Module
ast
, moduleDataLayout :: Maybe DataLayout
moduleDataLayout = Module -> Maybe DataLayout
moduleDataLayout Module
ast
}
externs :: HashSet ShortByteString
externs = Module -> HashSet ShortByteString
analyse Module
ast
arch :: Compute
arch = DeviceProperties -> Compute
computeCapability DeviceProperties
dev
msg :: String
msg = String -> String -> String
forall r. PrintfType r => String -> r
printf String
"cc: linking with libdevice: %s"
(String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", "
([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (ShortByteString -> String) -> [ShortByteString] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ShortByteString -> String
S8.unpack
([ShortByteString] -> [String]) -> [ShortByteString] -> [String]
forall a b. (a -> b) -> a -> b
$ HashSet ShortByteString -> [ShortByteString]
forall a. HashSet a -> [a]
Set.toList HashSet ShortByteString
externs
withLibdeviceNVVM
:: DeviceProperties
-> Context
-> Module
-> ([(ShortByteString, ByteString)] -> LLVM.Module -> IO a)
-> IO a
withLibdeviceNVVM :: DeviceProperties
-> Context
-> Module
-> ([(ShortByteString, ByteString)] -> Module -> IO a)
-> IO a
withLibdeviceNVVM DeviceProperties
dev Context
ctx Module
ast [(ShortByteString, ByteString)] -> Module -> IO a
next =
Context -> Module -> (Module -> IO a) -> IO a
forall a. Context -> Module -> (Module -> IO a) -> IO a
LLVM.withModuleFromAST Context
ctx Module
ast ((Module -> IO a) -> IO a) -> (Module -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Module
mdl -> do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
withlib (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Flag -> String -> IO ()
Debug.traceIO Flag
Debug.dump_cc String
msg
[(ShortByteString, ByteString)] -> Module -> IO a
next [(ShortByteString, ByteString)]
lib Module
mdl
where
externs :: HashSet ShortByteString
externs = Module -> HashSet ShortByteString
analyse Module
ast
withlib :: Bool
withlib = Bool -> Bool
not (HashSet ShortByteString -> Bool
forall a. HashSet a -> Bool
Set.null HashSet ShortByteString
externs)
lib :: [(ShortByteString, ByteString)]
lib | Bool
withlib = [ (ShortByteString, ByteString)
forall a. NVVMReflect a => a
nvvmReflect, Compute -> (ShortByteString, ByteString)
forall a. Libdevice a => Compute -> a
libdevice Compute
arch ]
| Bool
otherwise = []
arch :: Compute
arch = DeviceProperties -> Compute
computeCapability DeviceProperties
dev
msg :: String
msg = String -> String -> String
forall r. PrintfType r => String -> r
printf String
"cc: linking with libdevice: %s"
(String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", "
([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (ShortByteString -> String) -> [ShortByteString] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ShortByteString -> String
S8.unpack
([ShortByteString] -> [String]) -> [ShortByteString] -> [String]
forall a b. (a -> b) -> a -> b
$ HashSet ShortByteString -> [ShortByteString]
forall a. HashSet a -> [a]
Set.toList HashSet ShortByteString
externs
analyse :: Module -> HashSet ShortByteString
analyse :: Module -> HashSet ShortByteString
analyse Module{[Definition]
Maybe ShortByteString
Maybe DataLayout
ShortByteString
moduleName :: Module -> ShortByteString
moduleSourceFileName :: Module -> ShortByteString
moduleDefinitions :: Module -> [Definition]
moduleDefinitions :: [Definition]
moduleTargetTriple :: Maybe ShortByteString
moduleDataLayout :: Maybe DataLayout
moduleSourceFileName :: ShortByteString
moduleName :: ShortByteString
moduleDataLayout :: Module -> Maybe DataLayout
moduleTargetTriple :: Module -> Maybe ShortByteString
..} =
let intrinsic :: Definition -> Maybe ShortByteString
intrinsic (GlobalDefinition Function{[Either GroupID FunctionAttribute]
[(ShortByteString, MDRef MDNode)]
[BasicBlock]
[ParameterAttribute]
Maybe ShortByteString
Maybe Constant
Maybe StorageClass
Word32
([Parameter], Bool)
Type
CallingConvention
Linkage
Name
Visibility
name :: Global -> Name
linkage :: Global -> Linkage
visibility :: Global -> Visibility
dllStorageClass :: Global -> Maybe StorageClass
section :: Global -> Maybe ShortByteString
comdat :: Global -> Maybe ShortByteString
alignment :: Global -> Word32
metadata :: Global -> [(ShortByteString, MDRef MDNode)]
callingConvention :: Global -> CallingConvention
returnAttributes :: Global -> [ParameterAttribute]
returnType :: Global -> Type
parameters :: Global -> ([Parameter], Bool)
functionAttributes :: Global -> [Either GroupID FunctionAttribute]
garbageCollectorName :: Global -> Maybe ShortByteString
prefix :: Global -> Maybe Constant
basicBlocks :: Global -> [BasicBlock]
personalityFunction :: Global -> Maybe Constant
metadata :: [(ShortByteString, MDRef MDNode)]
personalityFunction :: Maybe Constant
basicBlocks :: [BasicBlock]
prefix :: Maybe Constant
garbageCollectorName :: Maybe ShortByteString
alignment :: Word32
comdat :: Maybe ShortByteString
section :: Maybe ShortByteString
functionAttributes :: [Either GroupID FunctionAttribute]
parameters :: ([Parameter], Bool)
name :: Name
returnType :: Type
returnAttributes :: [ParameterAttribute]
callingConvention :: CallingConvention
dllStorageClass :: Maybe StorageClass
visibility :: Visibility
linkage :: Linkage
..})
| [BasicBlock] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [BasicBlock]
basicBlocks
, Name ShortByteString
n <- Name
name
, ShortByteString
"__nv_" <- Int -> ShortByteString -> ShortByteString
BS.take Int
5 ShortByteString
n
= ShortByteString -> Maybe ShortByteString
forall a. a -> Maybe a
Just ShortByteString
n
intrinsic Definition
_
= Maybe ShortByteString
forall a. Maybe a
Nothing
in
[ShortByteString] -> HashSet ShortByteString
forall a. (Eq a, Hashable a) => [a] -> HashSet a
Set.fromList ((Definition -> Maybe ShortByteString)
-> [Definition] -> [ShortByteString]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Definition -> Maybe ShortByteString
intrinsic [Definition]
moduleDefinitions)
internalise :: HashSet ShortByteString -> Module -> Module
internalise :: HashSet ShortByteString -> Module -> Module
internalise HashSet ShortByteString
externals Module{[Definition]
Maybe ShortByteString
Maybe DataLayout
ShortByteString
moduleDefinitions :: [Definition]
moduleTargetTriple :: Maybe ShortByteString
moduleDataLayout :: Maybe DataLayout
moduleSourceFileName :: ShortByteString
moduleName :: ShortByteString
moduleName :: Module -> ShortByteString
moduleSourceFileName :: Module -> ShortByteString
moduleDefinitions :: Module -> [Definition]
moduleDataLayout :: Module -> Maybe DataLayout
moduleTargetTriple :: Module -> Maybe ShortByteString
..} =
let internal :: Definition -> Definition
internal (GlobalDefinition Function{[Either GroupID FunctionAttribute]
[(ShortByteString, MDRef MDNode)]
[BasicBlock]
[ParameterAttribute]
Maybe ShortByteString
Maybe Constant
Maybe StorageClass
Word32
([Parameter], Bool)
Type
CallingConvention
Linkage
Name
Visibility
metadata :: [(ShortByteString, MDRef MDNode)]
personalityFunction :: Maybe Constant
basicBlocks :: [BasicBlock]
prefix :: Maybe Constant
garbageCollectorName :: Maybe ShortByteString
alignment :: Word32
comdat :: Maybe ShortByteString
section :: Maybe ShortByteString
functionAttributes :: [Either GroupID FunctionAttribute]
parameters :: ([Parameter], Bool)
name :: Name
returnType :: Type
returnAttributes :: [ParameterAttribute]
callingConvention :: CallingConvention
dllStorageClass :: Maybe StorageClass
visibility :: Visibility
linkage :: Linkage
name :: Global -> Name
linkage :: Global -> Linkage
visibility :: Global -> Visibility
dllStorageClass :: Global -> Maybe StorageClass
section :: Global -> Maybe ShortByteString
comdat :: Global -> Maybe ShortByteString
alignment :: Global -> Word32
metadata :: Global -> [(ShortByteString, MDRef MDNode)]
callingConvention :: Global -> CallingConvention
returnAttributes :: Global -> [ParameterAttribute]
returnType :: Global -> Type
parameters :: Global -> ([Parameter], Bool)
functionAttributes :: Global -> [Either GroupID FunctionAttribute]
garbageCollectorName :: Global -> Maybe ShortByteString
prefix :: Global -> Maybe Constant
basicBlocks :: Global -> [BasicBlock]
personalityFunction :: Global -> Maybe Constant
..})
| Name ShortByteString
n <- Name
name
, Bool -> Bool
not (ShortByteString -> HashSet ShortByteString -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
Set.member ShortByteString
n HashSet ShortByteString
externals)
, Bool -> Bool
not ([BasicBlock] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [BasicBlock]
basicBlocks)
= Global -> Definition
GlobalDefinition Function :: Linkage
-> Visibility
-> Maybe StorageClass
-> CallingConvention
-> [ParameterAttribute]
-> Type
-> Name
-> ([Parameter], Bool)
-> [Either GroupID FunctionAttribute]
-> Maybe ShortByteString
-> Maybe ShortByteString
-> Word32
-> Maybe ShortByteString
-> Maybe Constant
-> [BasicBlock]
-> Maybe Constant
-> [(ShortByteString, MDRef MDNode)]
-> Global
Function { linkage :: Linkage
linkage=Linkage
Internal, [Either GroupID FunctionAttribute]
[(ShortByteString, MDRef MDNode)]
[BasicBlock]
[ParameterAttribute]
Maybe ShortByteString
Maybe Constant
Maybe StorageClass
Word32
([Parameter], Bool)
Type
CallingConvention
Name
Visibility
metadata :: [(ShortByteString, MDRef MDNode)]
personalityFunction :: Maybe Constant
basicBlocks :: [BasicBlock]
prefix :: Maybe Constant
garbageCollectorName :: Maybe ShortByteString
alignment :: Word32
comdat :: Maybe ShortByteString
section :: Maybe ShortByteString
functionAttributes :: [Either GroupID FunctionAttribute]
parameters :: ([Parameter], Bool)
name :: Name
returnType :: Type
returnAttributes :: [ParameterAttribute]
callingConvention :: CallingConvention
dllStorageClass :: Maybe StorageClass
visibility :: Visibility
name :: Name
visibility :: Visibility
dllStorageClass :: Maybe StorageClass
section :: Maybe ShortByteString
comdat :: Maybe ShortByteString
alignment :: Word32
metadata :: [(ShortByteString, MDRef MDNode)]
callingConvention :: CallingConvention
returnAttributes :: [ParameterAttribute]
returnType :: Type
parameters :: ([Parameter], Bool)
functionAttributes :: [Either GroupID FunctionAttribute]
garbageCollectorName :: Maybe ShortByteString
prefix :: Maybe Constant
basicBlocks :: [BasicBlock]
personalityFunction :: Maybe Constant
.. }
internal Definition
x
= Definition
x
in
Module :: ShortByteString
-> ShortByteString
-> Maybe DataLayout
-> Maybe ShortByteString
-> [Definition]
-> Module
Module { moduleDefinitions :: [Definition]
moduleDefinitions = (Definition -> Definition) -> [Definition] -> [Definition]
forall a b. (a -> b) -> [a] -> [b]
map Definition -> Definition
internal [Definition]
moduleDefinitions, Maybe ShortByteString
Maybe DataLayout
ShortByteString
moduleTargetTriple :: Maybe ShortByteString
moduleDataLayout :: Maybe DataLayout
moduleSourceFileName :: ShortByteString
moduleName :: ShortByteString
moduleName :: ShortByteString
moduleSourceFileName :: ShortByteString
moduleDataLayout :: Maybe DataLayout
moduleTargetTriple :: Maybe ShortByteString
.. }