{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
module DsForeign ( dsForeigns ) where
#include "HsVersions.h"
import GhcPrelude
import TcRnMonad
import CoreSyn
import DsCCall
import DsMonad
import HsSyn
import DataCon
import CoreUnfold
import Id
import Literal
import Module
import Name
import Type
import RepType
import TyCon
import Coercion
import TcEnv
import TcType
import CmmExpr
import CmmUtils
import HscTypes
import ForeignCall
import TysWiredIn
import TysPrim
import PrelNames
import BasicTypes
import SrcLoc
import Outputable
import FastString
import DynFlags
import Platform
import Config
import OrdList
import Pair
import Util
import Hooks
import Encoding
import Data.Maybe
import Data.List
type Binding = (Id, CoreExpr)
dsForeigns :: [LForeignDecl GhcTc]
-> DsM (ForeignStubs, OrdList Binding)
dsForeigns :: [LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding)
dsForeigns fos :: [LForeignDecl GhcTc]
fos = (Hooks
-> Maybe
([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding)))
-> ([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding))
-> IOEnv
(Env DsGblEnv DsLclEnv)
([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding))
forall (f :: * -> *) a.
(Functor f, HasDynFlags f) =>
(Hooks -> Maybe a) -> a -> f a
getHooked Hooks
-> Maybe
([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding))
dsForeignsHook [LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding)
dsForeigns' IOEnv
(Env DsGblEnv DsLclEnv)
([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding))
-> (([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding))
-> DsM (ForeignStubs, OrdList Binding))
-> DsM (ForeignStubs, OrdList Binding)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (([LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding))
-> [LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding)
forall a b. (a -> b) -> a -> b
$ [LForeignDecl GhcTc]
fos)
dsForeigns' :: [LForeignDecl GhcTc]
-> DsM (ForeignStubs, OrdList Binding)
dsForeigns' :: [LForeignDecl GhcTc] -> DsM (ForeignStubs, OrdList Binding)
dsForeigns' []
= (ForeignStubs, OrdList Binding)
-> DsM (ForeignStubs, OrdList Binding)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignStubs
NoStubs, OrdList Binding
forall a. OrdList a
nilOL)
dsForeigns' fos :: [LForeignDecl GhcTc]
fos = do
[(SDoc, SDoc, [Var], [Binding])]
fives <- (LForeignDecl GhcTc
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding]))
-> [LForeignDecl GhcTc]
-> IOEnv (Env DsGblEnv DsLclEnv) [(SDoc, SDoc, [Var], [Binding])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM LForeignDecl GhcTc
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
forall a pass.
(HasSrcSpan a, Outputable (IdP pass),
XForeignImport pass ~ Coercion, XForeignExport pass ~ Coercion,
IdP pass ~ Var, SrcSpanLess a ~ ForeignDecl pass) =>
a -> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
do_ldecl [LForeignDecl GhcTc]
fos
let
(hs :: [SDoc]
hs, cs :: [SDoc]
cs, idss :: [[Var]]
idss, bindss :: [[Binding]]
bindss) = [(SDoc, SDoc, [Var], [Binding])]
-> ([SDoc], [SDoc], [[Var]], [[Binding]])
forall a b c d. [(a, b, c, d)] -> ([a], [b], [c], [d])
unzip4 [(SDoc, SDoc, [Var], [Binding])]
fives
fe_ids :: [Var]
fe_ids = [[Var]] -> [Var]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Var]]
idss
fe_init_code :: [SDoc]
fe_init_code = (Var -> SDoc) -> [Var] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map Var -> SDoc
foreignExportInitialiser [Var]
fe_ids
(ForeignStubs, OrdList Binding)
-> DsM (ForeignStubs, OrdList Binding)
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> SDoc -> ForeignStubs
ForeignStubs
([SDoc] -> SDoc
vcat [SDoc]
hs)
([SDoc] -> SDoc
vcat [SDoc]
cs SDoc -> SDoc -> SDoc
$$ [SDoc] -> SDoc
vcat [SDoc]
fe_init_code),
([Binding] -> OrdList Binding -> OrdList Binding)
-> OrdList Binding -> [[Binding]] -> OrdList Binding
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (OrdList Binding -> OrdList Binding -> OrdList Binding
forall a. OrdList a -> OrdList a -> OrdList a
appOL (OrdList Binding -> OrdList Binding -> OrdList Binding)
-> ([Binding] -> OrdList Binding)
-> [Binding]
-> OrdList Binding
-> OrdList Binding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Binding] -> OrdList Binding
forall a. [a] -> OrdList a
toOL) OrdList Binding
forall a. OrdList a
nilOL [[Binding]]
bindss)
where
do_ldecl :: a -> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
do_ldecl (a -> Located (SrcSpanLess a)
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L loc :: SrcSpan
loc decl :: SrcSpanLess a
decl) = SrcSpan
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
forall a. SrcSpan -> DsM a -> DsM a
putSrcSpanDs SrcSpan
loc (ForeignDecl pass
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
forall pass.
(Outputable (IdP pass), XForeignExport pass ~ Coercion,
IdP pass ~ Var, XForeignImport pass ~ Coercion) =>
ForeignDecl pass
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
do_decl SrcSpanLess a
ForeignDecl pass
decl)
do_decl :: ForeignDecl pass
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
do_decl (ForeignImport { fd_name :: forall pass. ForeignDecl pass -> Located (IdP pass)
fd_name = Located (IdP pass)
id, fd_i_ext :: forall pass. ForeignDecl pass -> XForeignImport pass
fd_i_ext = XForeignImport pass
co, fd_fi :: forall pass. ForeignDecl pass -> ForeignImport
fd_fi = ForeignImport
spec }) = do
SDoc -> TcRnIf DsGblEnv DsLclEnv ()
forall m n. SDoc -> TcRnIf m n ()
traceIf (String -> SDoc
text "fi start" SDoc -> SDoc -> SDoc
<+> Located (IdP pass) -> SDoc
forall a. Outputable a => a -> SDoc
ppr Located (IdP pass)
id)
let id' :: SrcSpanLess (Located (IdP pass))
id' = Located (IdP pass) -> SrcSpanLess (Located (IdP pass))
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located (IdP pass)
id
(bs :: [Binding]
bs, h :: SDoc
h, c :: SDoc
c) <- Var -> Coercion -> ForeignImport -> DsM ([Binding], SDoc, SDoc)
dsFImport SrcSpanLess (Located (IdP pass))
Var
id' Coercion
XForeignImport pass
co ForeignImport
spec
SDoc -> TcRnIf DsGblEnv DsLclEnv ()
forall m n. SDoc -> TcRnIf m n ()
traceIf (String -> SDoc
text "fi end" SDoc -> SDoc -> SDoc
<+> Located (IdP pass) -> SDoc
forall a. Outputable a => a -> SDoc
ppr Located (IdP pass)
id)
(SDoc, SDoc, [Var], [Binding])
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc
h, SDoc
c, [], [Binding]
bs)
do_decl (ForeignExport { fd_name :: forall pass. ForeignDecl pass -> Located (IdP pass)
fd_name = (Located (IdP pass) -> Located (SrcSpanLess (Located (IdP pass)))
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L _ id :: SrcSpanLess (Located (IdP pass))
id)
, fd_e_ext :: forall pass. ForeignDecl pass -> XForeignExport pass
fd_e_ext = XForeignExport pass
co
, fd_fe :: forall pass. ForeignDecl pass -> ForeignExport
fd_fe = CExport
(Located CExportSpec -> Located (SrcSpanLess (Located CExportSpec))
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L _ (CExportStatic _ ext_nm cconv)) _ }) = do
(h :: SDoc
h, c :: SDoc
c, _, _) <- Var
-> Coercion
-> CLabelString
-> CCallConv
-> Bool
-> DsM (SDoc, SDoc, String, Int)
dsFExport SrcSpanLess (Located (IdP pass))
Var
id Coercion
XForeignExport pass
co CLabelString
ext_nm CCallConv
cconv Bool
False
(SDoc, SDoc, [Var], [Binding])
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc
h, SDoc
c, [SrcSpanLess (Located (IdP pass))
Var
id], [])
do_decl (XForeignDecl _) = String
-> IOEnv (Env DsGblEnv DsLclEnv) (SDoc, SDoc, [Var], [Binding])
forall a. String -> a
panic "dsForeigns'"
dsFImport :: Id
-> Coercion
-> ForeignImport
-> DsM ([Binding], SDoc, SDoc)
dsFImport :: Var -> Coercion -> ForeignImport -> DsM ([Binding], SDoc, SDoc)
dsFImport id :: Var
id co :: Coercion
co (CImport cconv :: Located CCallConv
cconv safety :: Located Safety
safety mHeader :: Maybe Header
mHeader spec :: CImportSpec
spec _) =
Var
-> Coercion
-> CImportSpec
-> CCallConv
-> Safety
-> Maybe Header
-> DsM ([Binding], SDoc, SDoc)
dsCImport Var
id Coercion
co CImportSpec
spec (Located CCallConv -> SrcSpanLess (Located CCallConv)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located CCallConv
cconv) (Located Safety -> SrcSpanLess (Located Safety)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located Safety
safety) Maybe Header
mHeader
dsCImport :: Id
-> Coercion
-> CImportSpec
-> CCallConv
-> Safety
-> Maybe Header
-> DsM ([Binding], SDoc, SDoc)
dsCImport :: Var
-> Coercion
-> CImportSpec
-> CCallConv
-> Safety
-> Maybe Header
-> DsM ([Binding], SDoc, SDoc)
dsCImport id :: Var
id co :: Coercion
co (CLabel cid :: CLabelString
cid) cconv :: CCallConv
cconv _ _ = do
DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let ty :: Type
ty = Pair Type -> Type
forall a. Pair a -> a
pFst (Pair Type -> Type) -> Pair Type -> Type
forall a b. (a -> b) -> a -> b
$ Coercion -> Pair Type
coercionKind Coercion
co
fod :: FunctionOrData
fod = case Type -> Maybe TyCon
tyConAppTyCon_maybe (Type -> Type
dropForAlls Type
ty) of
Just tycon :: TyCon
tycon
| TyCon -> Unique
tyConUnique TyCon
tycon Unique -> Unique -> Bool
forall a. Eq a => a -> a -> Bool
== Unique
funPtrTyConKey ->
FunctionOrData
IsFunction
_ -> FunctionOrData
IsData
(resTy :: Maybe Type
resTy, foRhs :: CoreExpr -> CoreExpr
foRhs) <- Type -> DsM (Maybe Type, CoreExpr -> CoreExpr)
resultWrapper Type
ty
ASSERT(fromJust resTy `eqType` addrPrimTy)
let
rhs :: CoreExpr
rhs = CoreExpr -> CoreExpr
foRhs (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (CLabelString -> Maybe Int -> FunctionOrData -> Literal
LitLabel CLabelString
cid Maybe Int
stdcall_info FunctionOrData
fod))
rhs' :: CoreExpr
rhs' = CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
rhs Coercion
co
stdcall_info :: Maybe Int
stdcall_info = DynFlags -> CCallConv -> Type -> Maybe Int
fun_type_arg_stdcall_info DynFlags
dflags CCallConv
cconv Type
ty
in
([Binding], SDoc, SDoc) -> DsM ([Binding], SDoc, SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Var
id, CoreExpr
rhs')], SDoc
empty, SDoc
empty)
dsCImport id :: Var
id co :: Coercion
co (CFunction target :: CCallTarget
target) cconv :: CCallConv
cconv@CCallConv
PrimCallConv safety :: Safety
safety _
= Var -> Coercion -> ForeignCall -> DsM ([Binding], SDoc, SDoc)
dsPrimCall Var
id Coercion
co (CCallSpec -> ForeignCall
CCall (CCallTarget -> CCallConv -> Safety -> CCallSpec
CCallSpec CCallTarget
target CCallConv
cconv Safety
safety))
dsCImport id :: Var
id co :: Coercion
co (CFunction target :: CCallTarget
target) cconv :: CCallConv
cconv safety :: Safety
safety mHeader :: Maybe Header
mHeader
= Var
-> Coercion
-> ForeignCall
-> Maybe Header
-> DsM ([Binding], SDoc, SDoc)
dsFCall Var
id Coercion
co (CCallSpec -> ForeignCall
CCall (CCallTarget -> CCallConv -> Safety -> CCallSpec
CCallSpec CCallTarget
target CCallConv
cconv Safety
safety)) Maybe Header
mHeader
dsCImport id :: Var
id co :: Coercion
co CWrapper cconv :: CCallConv
cconv _ _
= Var -> Coercion -> CCallConv -> DsM ([Binding], SDoc, SDoc)
dsFExportDynamic Var
id Coercion
co CCallConv
cconv
fun_type_arg_stdcall_info :: DynFlags -> CCallConv -> Type -> Maybe Int
fun_type_arg_stdcall_info :: DynFlags -> CCallConv -> Type -> Maybe Int
fun_type_arg_stdcall_info dflags :: DynFlags
dflags StdCallConv ty :: Type
ty
| Just (tc :: TyCon
tc,[arg_ty :: Type
arg_ty]) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
ty,
TyCon -> Unique
tyConUnique TyCon
tc Unique -> Unique -> Bool
forall a. Eq a => a -> a -> Bool
== Unique
funPtrTyConKey
= let
(bndrs :: [TyBinder]
bndrs, _) = Type -> ([TyBinder], Type)
tcSplitPiTys Type
arg_ty
fe_arg_tys :: [Type]
fe_arg_tys = (TyBinder -> Maybe Type) -> [TyBinder] -> [Type]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe TyBinder -> Maybe Type
binderRelevantType_maybe [TyBinder]
bndrs
in Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Type -> Int) -> [Type] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Width -> Int
widthInBytes (Width -> Int) -> (Type -> Width) -> Type -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CmmType -> Width
typeWidth (CmmType -> Width) -> (Type -> CmmType) -> Type -> Width
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynFlags -> Type -> CmmType
typeCmmType DynFlags
dflags (Type -> CmmType) -> (Type -> Type) -> Type -> CmmType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> Type
getPrimTyOf) [Type]
fe_arg_tys)
fun_type_arg_stdcall_info _ _other_conv :: CCallConv
_other_conv _
= Maybe Int
forall a. Maybe a
Nothing
dsFCall :: Id -> Coercion -> ForeignCall -> Maybe Header
-> DsM ([(Id, Expr TyVar)], SDoc, SDoc)
dsFCall :: Var
-> Coercion
-> ForeignCall
-> Maybe Header
-> DsM ([Binding], SDoc, SDoc)
dsFCall fn_id :: Var
fn_id co :: Coercion
co fcall :: ForeignCall
fcall mDeclHeader :: Maybe Header
mDeclHeader = do
let
ty :: Type
ty = Pair Type -> Type
forall a. Pair a -> a
pFst (Pair Type -> Type) -> Pair Type -> Type
forall a b. (a -> b) -> a -> b
$ Coercion -> Pair Type
coercionKind Coercion
co
(tv_bndrs :: [TyVarBinder]
tv_bndrs, rho :: Type
rho) = Type -> ([TyVarBinder], Type)
tcSplitForAllVarBndrs Type
ty
(arg_tys :: [Type]
arg_tys, io_res_ty :: Type
io_res_ty) = Type -> ([Type], Type)
tcSplitFunTys Type
rho
[Var]
args <- [Type] -> DsM [Var]
newSysLocalsDs [Type]
arg_tys
(val_args :: [CoreExpr]
val_args, arg_wrappers :: [CoreExpr -> CoreExpr]
arg_wrappers) <- (CoreExpr
-> IOEnv (Env DsGblEnv DsLclEnv) (CoreExpr, CoreExpr -> CoreExpr))
-> [CoreExpr]
-> IOEnv
(Env DsGblEnv DsLclEnv) ([CoreExpr], [CoreExpr -> CoreExpr])
forall (m :: * -> *) a b c.
Applicative m =>
(a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM CoreExpr
-> IOEnv (Env DsGblEnv DsLclEnv) (CoreExpr, CoreExpr -> CoreExpr)
unboxArg ((Var -> CoreExpr) -> [Var] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map Var -> CoreExpr
forall b. Var -> Expr b
Var [Var]
args)
let
work_arg_ids :: [Var]
work_arg_ids = [Var
v | Var v :: Var
v <- [CoreExpr]
val_args]
(ccall_result_ty :: Type
ccall_result_ty, res_wrapper :: CoreExpr -> CoreExpr
res_wrapper) <- Type -> DsM (Type, CoreExpr -> CoreExpr)
boxResult Type
io_res_ty
Unique
ccall_uniq <- TcRnIf DsGblEnv DsLclEnv Unique
forall gbl lcl. TcRnIf gbl lcl Unique
newUnique
Unique
work_uniq <- TcRnIf DsGblEnv DsLclEnv Unique
forall gbl lcl. TcRnIf gbl lcl Unique
newUnique
DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(fcall' :: ForeignCall
fcall', cDoc :: SDoc
cDoc) <-
case ForeignCall
fcall of
CCall (CCallSpec (StaticTarget _ cName :: CLabelString
cName mUnitId :: Maybe UnitId
mUnitId isFun :: Bool
isFun)
CApiConv safety :: Safety
safety) ->
do CLabelString
wrapperName <- String -> String -> IOEnv (Env DsGblEnv DsLclEnv) CLabelString
forall (m :: * -> *).
(MonadIO m, HasDynFlags m, HasModule m) =>
String -> String -> m CLabelString
mkWrapperName "ghc_wrapper" (CLabelString -> String
unpackFS CLabelString
cName)
let fcall' :: ForeignCall
fcall' = CCallSpec -> ForeignCall
CCall (CCallTarget -> CCallConv -> Safety -> CCallSpec
CCallSpec
(SourceText -> CLabelString -> Maybe UnitId -> Bool -> CCallTarget
StaticTarget SourceText
NoSourceText
CLabelString
wrapperName Maybe UnitId
mUnitId
Bool
True)
CCallConv
CApiConv Safety
safety)
c :: SDoc
c = SDoc
includes
SDoc -> SDoc -> SDoc
$$ SDoc
fun_proto SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
braces (SDoc
cRet SDoc -> SDoc -> SDoc
<> SDoc
semi)
includes :: SDoc
includes = [SDoc] -> SDoc
vcat [ String -> SDoc
text "#include \"" SDoc -> SDoc -> SDoc
<> CLabelString -> SDoc
ftext CLabelString
h
SDoc -> SDoc -> SDoc
<> String -> SDoc
text "\""
| Header _ h :: CLabelString
h <- [Header] -> [Header]
forall a. Eq a => [a] -> [a]
nub [Header]
headers ]
fun_proto :: SDoc
fun_proto = SDoc
cResType SDoc -> SDoc -> SDoc
<+> SDoc
pprCconv SDoc -> SDoc -> SDoc
<+> CLabelString -> SDoc
forall a. Outputable a => a -> SDoc
ppr CLabelString
wrapperName SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens SDoc
argTypes
cRet :: SDoc
cRet
| Bool
isVoidRes = SDoc
cCall
| Bool
otherwise = String -> SDoc
text "return" SDoc -> SDoc -> SDoc
<+> SDoc
cCall
cCall :: SDoc
cCall = if Bool
isFun
then CLabelString -> SDoc
forall a. Outputable a => a -> SDoc
ppr CLabelString
cName SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens SDoc
argVals
else if [Type] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
arg_tys
then CLabelString -> SDoc
forall a. Outputable a => a -> SDoc
ppr CLabelString
cName
else String -> SDoc
forall a. String -> a
panic "dsFCall: Unexpected arguments to FFI value import"
raw_res_ty :: Type
raw_res_ty = case Type -> Maybe (TyCon, Type)
tcSplitIOType_maybe Type
io_res_ty of
Just (_ioTyCon :: TyCon
_ioTyCon, res_ty :: Type
res_ty) -> Type
res_ty
Nothing -> Type
io_res_ty
isVoidRes :: Bool
isVoidRes = Type
raw_res_ty Type -> Type -> Bool
`eqType` Type
unitTy
(mHeader :: Maybe Header
mHeader, cResType :: SDoc
cResType)
| Bool
isVoidRes = (Maybe Header
forall a. Maybe a
Nothing, String -> SDoc
text "void")
| Bool
otherwise = Type -> (Maybe Header, SDoc)
toCType Type
raw_res_ty
pprCconv :: SDoc
pprCconv = CCallConv -> SDoc
ccallConvAttribute CCallConv
CApiConv
mHeadersArgTypeList :: [(Maybe Header, SDoc)]
mHeadersArgTypeList
= [ (Maybe Header
header, SDoc
cType SDoc -> SDoc -> SDoc
<+> Char -> SDoc
char 'a' SDoc -> SDoc -> SDoc
<> Int -> SDoc
int Int
n)
| (t :: Type
t, n :: Int
n) <- [Type] -> [Int] -> [(Type, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Type]
arg_tys [1..]
, let (header :: Maybe Header
header, cType :: SDoc
cType) = Type -> (Maybe Header, SDoc)
toCType Type
t ]
(mHeaders :: [Maybe Header]
mHeaders, argTypeList :: [SDoc]
argTypeList) = [(Maybe Header, SDoc)] -> ([Maybe Header], [SDoc])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Maybe Header, SDoc)]
mHeadersArgTypeList
argTypes :: SDoc
argTypes = if [SDoc] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SDoc]
argTypeList
then String -> SDoc
text "void"
else [SDoc] -> SDoc
hsep ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> [SDoc] -> [SDoc]
punctuate SDoc
comma [SDoc]
argTypeList
mHeaders' :: [Maybe Header]
mHeaders' = Maybe Header
mDeclHeader Maybe Header -> [Maybe Header] -> [Maybe Header]
forall a. a -> [a] -> [a]
: Maybe Header
mHeader Maybe Header -> [Maybe Header] -> [Maybe Header]
forall a. a -> [a] -> [a]
: [Maybe Header]
mHeaders
headers :: [Header]
headers = [Maybe Header] -> [Header]
forall a. [Maybe a] -> [a]
catMaybes [Maybe Header]
mHeaders'
argVals :: SDoc
argVals = [SDoc] -> SDoc
hsep ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> [SDoc] -> [SDoc]
punctuate SDoc
comma
[ Char -> SDoc
char 'a' SDoc -> SDoc -> SDoc
<> Int -> SDoc
int Int
n
| (_, n :: Int
n) <- [Type] -> [Int] -> [(Type, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Type]
arg_tys [1..] ]
(ForeignCall, SDoc)
-> IOEnv (Env DsGblEnv DsLclEnv) (ForeignCall, SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignCall
fcall', SDoc
c)
_ ->
(ForeignCall, SDoc)
-> IOEnv (Env DsGblEnv DsLclEnv) (ForeignCall, SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignCall
fcall, SDoc
empty)
let
worker_ty :: Type
worker_ty = [TyVarBinder] -> Type -> Type
mkForAllTys [TyVarBinder]
tv_bndrs ([Type] -> Type -> Type
mkFunTys ((Var -> Type) -> [Var] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Var -> Type
idType [Var]
work_arg_ids) Type
ccall_result_ty)
tvs :: [Var]
tvs = (TyVarBinder -> Var) -> [TyVarBinder] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map TyVarBinder -> Var
forall tv argf. VarBndr tv argf -> tv
binderVar [TyVarBinder]
tv_bndrs
the_ccall_app :: CoreExpr
the_ccall_app = DynFlags -> Unique -> ForeignCall -> [CoreExpr] -> Type -> CoreExpr
mkFCall DynFlags
dflags Unique
ccall_uniq ForeignCall
fcall' [CoreExpr]
val_args Type
ccall_result_ty
work_rhs :: CoreExpr
work_rhs = [Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
tvs ([Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
work_arg_ids CoreExpr
the_ccall_app)
work_id :: Var
work_id = CLabelString -> Unique -> Type -> Var
mkSysLocal (String -> CLabelString
fsLit "$wccall") Unique
work_uniq Type
worker_ty
work_app :: CoreExpr
work_app = CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (CoreExpr -> [Var] -> CoreExpr
forall b. Expr b -> [Var] -> Expr b
mkVarApps (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
work_id) [Var]
tvs) [CoreExpr]
val_args
wrapper_body :: CoreExpr
wrapper_body = ((CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr)
-> CoreExpr -> [CoreExpr -> CoreExpr] -> CoreExpr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
($) (CoreExpr -> CoreExpr
res_wrapper CoreExpr
work_app) [CoreExpr -> CoreExpr]
arg_wrappers
wrap_rhs :: CoreExpr
wrap_rhs = [Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams ([Var]
tvs [Var] -> [Var] -> [Var]
forall a. [a] -> [a] -> [a]
++ [Var]
args) CoreExpr
wrapper_body
wrap_rhs' :: CoreExpr
wrap_rhs' = CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
wrap_rhs Coercion
co
fn_id_w_inl :: Var
fn_id_w_inl = Var
fn_id Var -> Unfolding -> Var
`setIdUnfolding` Int -> CoreExpr -> Unfolding
mkInlineUnfoldingWithArity
([Var] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Var]
args) CoreExpr
wrap_rhs'
([Binding], SDoc, SDoc) -> DsM ([Binding], SDoc, SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Var
work_id, CoreExpr
work_rhs), (Var
fn_id_w_inl, CoreExpr
wrap_rhs')], SDoc
empty, SDoc
cDoc)
dsPrimCall :: Id -> Coercion -> ForeignCall
-> DsM ([(Id, Expr TyVar)], SDoc, SDoc)
dsPrimCall :: Var -> Coercion -> ForeignCall -> DsM ([Binding], SDoc, SDoc)
dsPrimCall fn_id :: Var
fn_id co :: Coercion
co fcall :: ForeignCall
fcall = do
let
ty :: Type
ty = Pair Type -> Type
forall a. Pair a -> a
pFst (Pair Type -> Type) -> Pair Type -> Type
forall a b. (a -> b) -> a -> b
$ Coercion -> Pair Type
coercionKind Coercion
co
(tvs :: [Var]
tvs, fun_ty :: Type
fun_ty) = Type -> ([Var], Type)
tcSplitForAllTys Type
ty
(arg_tys :: [Type]
arg_tys, io_res_ty :: Type
io_res_ty) = Type -> ([Type], Type)
tcSplitFunTys Type
fun_ty
[Var]
args <- [Type] -> DsM [Var]
newSysLocalsDs [Type]
arg_tys
Unique
ccall_uniq <- TcRnIf DsGblEnv DsLclEnv Unique
forall gbl lcl. TcRnIf gbl lcl Unique
newUnique
DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let
call_app :: CoreExpr
call_app = DynFlags -> Unique -> ForeignCall -> [CoreExpr] -> Type -> CoreExpr
mkFCall DynFlags
dflags Unique
ccall_uniq ForeignCall
fcall ((Var -> CoreExpr) -> [Var] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map Var -> CoreExpr
forall b. Var -> Expr b
Var [Var]
args) Type
io_res_ty
rhs :: CoreExpr
rhs = [Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
tvs ([Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
args CoreExpr
call_app)
rhs' :: CoreExpr
rhs' = CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
rhs Coercion
co
([Binding], SDoc, SDoc) -> DsM ([Binding], SDoc, SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Var
fn_id, CoreExpr
rhs')], SDoc
empty, SDoc
empty)
dsFExport :: Id
-> Coercion
-> CLabelString
-> CCallConv
-> Bool
-> DsM ( SDoc
, SDoc
, String
, Int
)
dsFExport :: Var
-> Coercion
-> CLabelString
-> CCallConv
-> Bool
-> DsM (SDoc, SDoc, String, Int)
dsFExport fn_id :: Var
fn_id co :: Coercion
co ext_name :: CLabelString
ext_name cconv :: CCallConv
cconv isDyn :: Bool
isDyn = do
let
ty :: Type
ty = Pair Type -> Type
forall a. Pair a -> a
pSnd (Pair Type -> Type) -> Pair Type -> Type
forall a b. (a -> b) -> a -> b
$ Coercion -> Pair Type
coercionKind Coercion
co
(bndrs :: [TyBinder]
bndrs, orig_res_ty :: Type
orig_res_ty) = Type -> ([TyBinder], Type)
tcSplitPiTys Type
ty
fe_arg_tys' :: [Type]
fe_arg_tys' = (TyBinder -> Maybe Type) -> [TyBinder] -> [Type]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe TyBinder -> Maybe Type
binderRelevantType_maybe [TyBinder]
bndrs
fe_arg_tys :: [Type]
fe_arg_tys | Bool
isDyn = [Type] -> [Type]
forall a. [a] -> [a]
tail [Type]
fe_arg_tys'
| Bool
otherwise = [Type]
fe_arg_tys'
(res_ty :: Type
res_ty, is_IO_res_ty :: Bool
is_IO_res_ty) = case Type -> Maybe (TyCon, Type)
tcSplitIOType_maybe Type
orig_res_ty of
Just (_ioTyCon :: TyCon
_ioTyCon, res_ty :: Type
res_ty) -> (Type
res_ty, Bool
True)
Nothing -> (Type
orig_res_ty, Bool
False)
DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(SDoc, SDoc, String, Int) -> DsM (SDoc, SDoc, String, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return ((SDoc, SDoc, String, Int) -> DsM (SDoc, SDoc, String, Int))
-> (SDoc, SDoc, String, Int) -> DsM (SDoc, SDoc, String, Int)
forall a b. (a -> b) -> a -> b
$
DynFlags
-> CLabelString
-> Maybe Var
-> [Type]
-> Type
-> Bool
-> CCallConv
-> (SDoc, SDoc, String, Int)
mkFExportCBits DynFlags
dflags CLabelString
ext_name
(if Bool
isDyn then Maybe Var
forall a. Maybe a
Nothing else Var -> Maybe Var
forall a. a -> Maybe a
Just Var
fn_id)
[Type]
fe_arg_tys Type
res_ty Bool
is_IO_res_ty CCallConv
cconv
dsFExportDynamic :: Id
-> Coercion
-> CCallConv
-> DsM ([Binding], SDoc, SDoc)
dsFExportDynamic :: Var -> Coercion -> CCallConv -> DsM ([Binding], SDoc, SDoc)
dsFExportDynamic id :: Var
id co0 :: Coercion
co0 cconv :: CCallConv
cconv = do
Module
mod <- IOEnv (Env DsGblEnv DsLclEnv) Module
forall (m :: * -> *). HasModule m => m Module
getModule
DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let fe_nm :: CLabelString
fe_nm = String -> CLabelString
mkFastString (String -> CLabelString) -> String -> CLabelString
forall a b. (a -> b) -> a -> b
$ String -> String
zEncodeString
(Module -> String
moduleStableString Module
mod String -> String -> String
forall a. [a] -> [a] -> [a]
++ "$" String -> String -> String
forall a. [a] -> [a] -> [a]
++ DynFlags -> Var -> String
toCName DynFlags
dflags Var
id)
Var
cback <- Type -> DsM Var
newSysLocalDs Type
arg_ty
Var
newStablePtrId <- Name -> DsM Var
dsLookupGlobalId Name
newStablePtrName
TyCon
stable_ptr_tycon <- Name -> DsM TyCon
dsLookupTyCon Name
stablePtrTyConName
let
stable_ptr_ty :: Type
stable_ptr_ty = TyCon -> [Type] -> Type
mkTyConApp TyCon
stable_ptr_tycon [Type
arg_ty]
export_ty :: Type
export_ty = Type -> Type -> Type
mkFunTy Type
stable_ptr_ty Type
arg_ty
Var
bindIOId <- Name -> DsM Var
dsLookupGlobalId Name
bindIOName
Var
stbl_value <- Type -> DsM Var
newSysLocalDs Type
stable_ptr_ty
(h_code :: SDoc
h_code, c_code :: SDoc
c_code, typestring :: String
typestring, args_size :: Int
args_size) <- Var
-> Coercion
-> CLabelString
-> CCallConv
-> Bool
-> DsM (SDoc, SDoc, String, Int)
dsFExport Var
id (Type -> Coercion
mkRepReflCo Type
export_ty) CLabelString
fe_nm CCallConv
cconv Bool
True
let
adj_args :: [CoreExpr]
adj_args = [ DynFlags -> Int -> CoreExpr
forall b. DynFlags -> Int -> Expr b
mkIntLitInt DynFlags
dflags (CCallConv -> Int
ccallConvToInt CCallConv
cconv)
, Var -> CoreExpr
forall b. Var -> Expr b
Var Var
stbl_value
, Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (CLabelString -> Maybe Int -> FunctionOrData -> Literal
LitLabel CLabelString
fe_nm Maybe Int
mb_sz_args FunctionOrData
IsFunction)
, Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (String -> Literal
mkLitString String
typestring)
]
adjustor :: CLabelString
adjustor = String -> CLabelString
fsLit "createAdjustor"
mb_sz_args :: Maybe Int
mb_sz_args = case CCallConv
cconv of
StdCallConv -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
args_size
_ -> Maybe Int
forall a. Maybe a
Nothing
CoreExpr
ccall_adj <- CLabelString -> [CoreExpr] -> Safety -> Type -> DsM CoreExpr
dsCCall CLabelString
adjustor [CoreExpr]
adj_args Safety
PlayRisky (TyCon -> [Type] -> Type
mkTyConApp TyCon
io_tc [Type
res_ty])
let io_app :: CoreExpr
io_app = [Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
tvs (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$
Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
cback (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$
CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
bindIOId)
[ Type -> CoreExpr
forall b. Type -> Expr b
Type Type
stable_ptr_ty
, Type -> CoreExpr
forall b. Type -> Expr b
Type Type
res_ty
, CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
newStablePtrId) [ Type -> CoreExpr
forall b. Type -> Expr b
Type Type
arg_ty, Var -> CoreExpr
forall b. Var -> Expr b
Var Var
cback ]
, Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
stbl_value CoreExpr
ccall_adj
]
fed :: Binding
fed = (Var
id Var -> Activation -> Var
`setInlineActivation` Activation
NeverActive, CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
io_app Coercion
co0)
([Binding], SDoc, SDoc) -> DsM ([Binding], SDoc, SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Binding
fed], SDoc
h_code, SDoc
c_code)
where
ty :: Type
ty = Pair Type -> Type
forall a. Pair a -> a
pFst (Coercion -> Pair Type
coercionKind Coercion
co0)
(tvs :: [Var]
tvs,sans_foralls :: Type
sans_foralls) = Type -> ([Var], Type)
tcSplitForAllTys Type
ty
([arg_ty :: Type
arg_ty], fn_res_ty :: Type
fn_res_ty) = Type -> ([Type], Type)
tcSplitFunTys Type
sans_foralls
Just (io_tc :: TyCon
io_tc, res_ty :: Type
res_ty) = Type -> Maybe (TyCon, Type)
tcSplitIOType_maybe Type
fn_res_ty
toCName :: DynFlags -> Id -> String
toCName :: DynFlags -> Var -> String
toCName dflags :: DynFlags
dflags i :: Var
i = DynFlags -> SDoc -> String
showSDoc DynFlags
dflags (CodeStyle -> SDoc -> SDoc
pprCode CodeStyle
CStyle (Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> Name
idName Var
i)))
mkFExportCBits :: DynFlags
-> FastString
-> Maybe Id
-> [Type]
-> Type
-> Bool
-> CCallConv
-> (SDoc,
SDoc,
String,
Int
)
mkFExportCBits :: DynFlags
-> CLabelString
-> Maybe Var
-> [Type]
-> Type
-> Bool
-> CCallConv
-> (SDoc, SDoc, String, Int)
mkFExportCBits dflags :: DynFlags
dflags c_nm :: CLabelString
c_nm maybe_target :: Maybe Var
maybe_target arg_htys :: [Type]
arg_htys res_hty :: Type
res_hty is_IO_res_ty :: Bool
is_IO_res_ty cc :: CCallConv
cc
= (SDoc
header_bits, SDoc
c_bits, String
type_string,
[Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Width -> Int
widthInBytes (CmmType -> Width
typeWidth CmmType
rep) | (_,_,_,rep :: CmmType
rep) <- [(SDoc, SDoc, Type, CmmType)]
aug_arg_info]
)
where
arg_info :: [(SDoc,
SDoc,
Type,
CmmType)]
arg_info :: [(SDoc, SDoc, Type, CmmType)]
arg_info = [ let stg_type :: SDoc
stg_type = Type -> SDoc
showStgType Type
ty in
(Int -> SDoc -> SDoc
arg_cname Int
n SDoc
stg_type,
SDoc
stg_type,
Type
ty,
DynFlags -> Type -> CmmType
typeCmmType DynFlags
dflags (Type -> Type
getPrimTyOf Type
ty))
| (ty :: Type
ty,n :: Int
n) <- [Type] -> [Int] -> [(Type, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Type]
arg_htys [1::Int ..] ]
arg_cname :: Int -> SDoc -> SDoc
arg_cname n :: Int
n stg_ty :: SDoc
stg_ty
| Bool
libffi = Char -> SDoc
char '*' SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (SDoc
stg_ty SDoc -> SDoc -> SDoc
<> Char -> SDoc
char '*') SDoc -> SDoc -> SDoc
<>
String -> SDoc
text "args" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
brackets (Int -> SDoc
int (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-1))
| Bool
otherwise = String -> SDoc
text ('a'Char -> String -> String
forall a. a -> [a] -> [a]
:Int -> String
forall a. Show a => a -> String
show Int
n)
libffi :: Bool
libffi = Bool
cLibFFI Bool -> Bool -> Bool
&& Maybe Var -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Var
maybe_target
type_string :: String
type_string
| Bool
libffi = DynFlags -> Type -> Char
primTyDescChar DynFlags
dflags Type
res_hty Char -> String -> String
forall a. a -> [a] -> [a]
: String
arg_type_string
| Bool
otherwise = String
arg_type_string
arg_type_string :: String
arg_type_string = [DynFlags -> Type -> Char
primTyDescChar DynFlags
dflags Type
ty | (_,_,ty :: Type
ty,_) <- [(SDoc, SDoc, Type, CmmType)]
arg_info]
aug_arg_info :: [(SDoc, SDoc, Type, CmmType)]
aug_arg_info
| Maybe Var -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Var
maybe_target = (SDoc, SDoc, Type, CmmType)
stable_ptr_arg (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: DynFlags
-> CCallConv
-> [(SDoc, SDoc, Type, CmmType)]
-> [(SDoc, SDoc, Type, CmmType)]
insertRetAddr DynFlags
dflags CCallConv
cc [(SDoc, SDoc, Type, CmmType)]
arg_info
| Bool
otherwise = [(SDoc, SDoc, Type, CmmType)]
arg_info
stable_ptr_arg :: (SDoc, SDoc, Type, CmmType)
stable_ptr_arg =
(String -> SDoc
text "the_stableptr", String -> SDoc
text "StgStablePtr", Type
forall a. HasCallStack => a
undefined,
DynFlags -> Type -> CmmType
typeCmmType DynFlags
dflags (Type -> Type
mkStablePtrPrimTy Type
alphaTy))
res_hty_is_unit :: Bool
res_hty_is_unit = Type
res_hty Type -> Type -> Bool
`eqType` Type
unitTy
cResType :: SDoc
cResType | Bool
res_hty_is_unit = String -> SDoc
text "void"
| Bool
otherwise = Type -> SDoc
showStgType Type
res_hty
ffi_cResType :: SDoc
ffi_cResType
| Bool
is_ffi_arg_type = String -> SDoc
text "ffi_arg"
| Bool
otherwise = SDoc
cResType
where
res_ty_key :: Unique
res_ty_key = Name -> Unique
forall a. Uniquable a => a -> Unique
getUnique (TyCon -> Name
forall a. NamedThing a => a -> Name
getName (Type -> TyCon
typeTyCon Type
res_hty))
is_ffi_arg_type :: Bool
is_ffi_arg_type = Unique
res_ty_key Unique -> [Unique] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem`
[Unique
floatTyConKey, Unique
doubleTyConKey,
Unique
int64TyConKey, Unique
word64TyConKey]
pprCconv :: SDoc
pprCconv = CCallConv -> SDoc
ccallConvAttribute CCallConv
cc
header_bits :: SDoc
header_bits = String -> SDoc
text "extern" SDoc -> SDoc -> SDoc
<+> SDoc
fun_proto SDoc -> SDoc -> SDoc
<> SDoc
semi
fun_args :: SDoc
fun_args
| [(SDoc, SDoc, Type, CmmType)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(SDoc, SDoc, Type, CmmType)]
aug_arg_info = String -> SDoc
text "void"
| Bool
otherwise = [SDoc] -> SDoc
hsep ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> [SDoc] -> [SDoc]
punctuate SDoc
comma
([SDoc] -> [SDoc]) -> [SDoc] -> [SDoc]
forall a b. (a -> b) -> a -> b
$ ((SDoc, SDoc, Type, CmmType) -> SDoc)
-> [(SDoc, SDoc, Type, CmmType)] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (\(nm :: SDoc
nm,ty :: SDoc
ty,_,_) -> SDoc
ty SDoc -> SDoc -> SDoc
<+> SDoc
nm) [(SDoc, SDoc, Type, CmmType)]
aug_arg_info
fun_proto :: SDoc
fun_proto
| Bool
libffi
= String -> SDoc
text "void" SDoc -> SDoc -> SDoc
<+> CLabelString -> SDoc
ftext CLabelString
c_nm SDoc -> SDoc -> SDoc
<>
SDoc -> SDoc
parens (String -> SDoc
text "void *cif STG_UNUSED, void* resp, void** args, void* the_stableptr")
| Bool
otherwise
= SDoc
cResType SDoc -> SDoc -> SDoc
<+> SDoc
pprCconv SDoc -> SDoc -> SDoc
<+> CLabelString -> SDoc
ftext CLabelString
c_nm SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens SDoc
fun_args
the_cfun :: SDoc
the_cfun
= case Maybe Var
maybe_target of
Nothing -> String -> SDoc
text "(StgClosure*)deRefStablePtr(the_stableptr)"
Just hs_fn :: Var
hs_fn -> Char -> SDoc
char '&' SDoc -> SDoc -> SDoc
<> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
hs_fn SDoc -> SDoc -> SDoc
<> String -> SDoc
text "_closure"
cap :: SDoc
cap = String -> SDoc
text "cap" SDoc -> SDoc -> SDoc
<> SDoc
comma
expr_to_run :: SDoc
expr_to_run
= (SDoc -> (SDoc, SDoc, Type, CmmType) -> SDoc)
-> SDoc -> [(SDoc, SDoc, Type, CmmType)] -> SDoc
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' SDoc -> (SDoc, SDoc, Type, CmmType) -> SDoc
forall b d. SDoc -> (SDoc, b, Type, d) -> SDoc
appArg SDoc
the_cfun [(SDoc, SDoc, Type, CmmType)]
arg_info
where
appArg :: SDoc -> (SDoc, b, Type, d) -> SDoc
appArg acc :: SDoc
acc (arg_cname :: SDoc
arg_cname, _, arg_hty :: Type
arg_hty, _)
= String -> SDoc
text "rts_apply"
SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (SDoc
cap SDoc -> SDoc -> SDoc
<> SDoc
acc SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<> Type -> SDoc
mkHObj Type
arg_hty SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (SDoc
cap SDoc -> SDoc -> SDoc
<> SDoc
arg_cname))
declareResult :: SDoc
declareResult = String -> SDoc
text "HaskellObj ret;"
declareCResult :: SDoc
declareCResult | Bool
res_hty_is_unit = SDoc
empty
| Bool
otherwise = SDoc
cResType SDoc -> SDoc -> SDoc
<+> String -> SDoc
text "cret;"
assignCResult :: SDoc
assignCResult | Bool
res_hty_is_unit = SDoc
empty
| Bool
otherwise =
String -> SDoc
text "cret=" SDoc -> SDoc -> SDoc
<> Type -> SDoc
unpackHObj Type
res_hty SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (String -> SDoc
text "ret") SDoc -> SDoc -> SDoc
<> SDoc
semi
extern_decl :: SDoc
extern_decl
= case Maybe Var
maybe_target of
Nothing -> SDoc
empty
Just hs_fn :: Var
hs_fn -> String -> SDoc
text "extern StgClosure " SDoc -> SDoc -> SDoc
<> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
hs_fn SDoc -> SDoc -> SDoc
<> String -> SDoc
text "_closure" SDoc -> SDoc -> SDoc
<> SDoc
semi
c_bits :: SDoc
c_bits =
SDoc
space SDoc -> SDoc -> SDoc
$$
SDoc
extern_decl SDoc -> SDoc -> SDoc
$$
SDoc
fun_proto SDoc -> SDoc -> SDoc
$$
[SDoc] -> SDoc
vcat
[ SDoc
lbrace
, String -> SDoc
text "Capability *cap;"
, SDoc
declareResult
, SDoc
declareCResult
, String -> SDoc
text "cap = rts_lock();"
, String -> SDoc
text "rts_evalIO" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (
Char -> SDoc
char '&' SDoc -> SDoc -> SDoc
<> SDoc
cap SDoc -> SDoc -> SDoc
<>
String -> SDoc
text "rts_apply" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (
SDoc
cap SDoc -> SDoc -> SDoc
<>
String -> SDoc
text "(HaskellObj)"
SDoc -> SDoc -> SDoc
<> PtrString -> SDoc
ptext (if Bool
is_IO_res_ty
then (String -> PtrString
sLit "runIO_closure")
else (String -> PtrString
sLit "runNonIO_closure"))
SDoc -> SDoc -> SDoc
<> SDoc
comma
SDoc -> SDoc -> SDoc
<> SDoc
expr_to_run
) SDoc -> SDoc -> SDoc
<+> SDoc
comma
SDoc -> SDoc -> SDoc
<> String -> SDoc
text "&ret"
) SDoc -> SDoc -> SDoc
<> SDoc
semi
, String -> SDoc
text "rts_checkSchedStatus" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (SDoc -> SDoc
doubleQuotes (CLabelString -> SDoc
ftext CLabelString
c_nm)
SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<> String -> SDoc
text "cap") SDoc -> SDoc -> SDoc
<> SDoc
semi
, SDoc
assignCResult
, String -> SDoc
text "rts_unlock(cap);"
, Bool -> SDoc -> SDoc
ppUnless Bool
res_hty_is_unit (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$
if Bool
libffi
then Char -> SDoc
char '*' SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (SDoc
ffi_cResType SDoc -> SDoc -> SDoc
<> Char -> SDoc
char '*') SDoc -> SDoc -> SDoc
<>
String -> SDoc
text "resp = cret;"
else String -> SDoc
text "return cret;"
, SDoc
rbrace
]
foreignExportInitialiser :: Id -> SDoc
foreignExportInitialiser :: Var -> SDoc
foreignExportInitialiser hs_fn :: Var
hs_fn =
[SDoc] -> SDoc
vcat
[ String -> SDoc
text "static void stginit_export_" SDoc -> SDoc -> SDoc
<> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
hs_fn
SDoc -> SDoc -> SDoc
<> String -> SDoc
text "() __attribute__((constructor));"
, String -> SDoc
text "static void stginit_export_" SDoc -> SDoc -> SDoc
<> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
hs_fn SDoc -> SDoc -> SDoc
<> String -> SDoc
text "()"
, SDoc -> SDoc
braces (String -> SDoc
text "foreignExportStablePtr"
SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (String -> SDoc
text "(StgPtr) &" SDoc -> SDoc -> SDoc
<> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
hs_fn SDoc -> SDoc -> SDoc
<> String -> SDoc
text "_closure")
SDoc -> SDoc -> SDoc
<> SDoc
semi)
]
mkHObj :: Type -> SDoc
mkHObj :: Type -> SDoc
mkHObj t :: Type
t = String -> SDoc
text "rts_mk" SDoc -> SDoc -> SDoc
<> String -> SDoc
text (Type -> String
showFFIType Type
t)
unpackHObj :: Type -> SDoc
unpackHObj :: Type -> SDoc
unpackHObj t :: Type
t = String -> SDoc
text "rts_get" SDoc -> SDoc -> SDoc
<> String -> SDoc
text (Type -> String
showFFIType Type
t)
showStgType :: Type -> SDoc
showStgType :: Type -> SDoc
showStgType t :: Type
t = String -> SDoc
text "Hs" SDoc -> SDoc -> SDoc
<> String -> SDoc
text (Type -> String
showFFIType Type
t)
showFFIType :: Type -> String
showFFIType :: Type -> String
showFFIType t :: Type
t = Name -> String
forall a. NamedThing a => a -> String
getOccString (TyCon -> Name
forall a. NamedThing a => a -> Name
getName (Type -> TyCon
typeTyCon Type
t))
toCType :: Type -> (Maybe Header, SDoc)
toCType :: Type -> (Maybe Header, SDoc)
toCType = Bool -> Type -> (Maybe Header, SDoc)
f Bool
False
where f :: Bool -> Type -> (Maybe Header, SDoc)
f voidOK :: Bool
voidOK t :: Type
t
| Just (ptr :: TyCon
ptr, [t' :: Type
t']) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
t
, TyCon -> Name
tyConName TyCon
ptr Name -> [Name] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Name
ptrTyConName, Name
funPtrTyConName]
= case Bool -> Type -> (Maybe Header, SDoc)
f Bool
True Type
t' of
(mh :: Maybe Header
mh, cType' :: SDoc
cType') ->
(Maybe Header
mh, SDoc
cType' SDoc -> SDoc -> SDoc
<> Char -> SDoc
char '*')
| Just tycon :: TyCon
tycon <- Type -> Maybe TyCon
tyConAppTyConPicky_maybe Type
t
, Just (CType _ mHeader :: Maybe Header
mHeader (_,cType :: CLabelString
cType)) <- TyCon -> Maybe CType
tyConCType_maybe TyCon
tycon
= (Maybe Header
mHeader, CLabelString -> SDoc
ftext CLabelString
cType)
| Just t' :: Type
t' <- Type -> Maybe Type
coreView Type
t
= Bool -> Type -> (Maybe Header, SDoc)
f Bool
voidOK Type
t'
| TyCon -> Maybe TyCon
forall a. a -> Maybe a
Just TyCon
byteArrayPrimTyCon Maybe TyCon -> Maybe TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== Type -> Maybe TyCon
tyConAppTyConPicky_maybe Type
t
= (Maybe Header
forall a. Maybe a
Nothing, String -> SDoc
text "const void*")
| TyCon -> Maybe TyCon
forall a. a -> Maybe a
Just TyCon
mutableByteArrayPrimTyCon Maybe TyCon -> Maybe TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== Type -> Maybe TyCon
tyConAppTyConPicky_maybe Type
t
= (Maybe Header
forall a. Maybe a
Nothing, String -> SDoc
text "void*")
| Bool
voidOK = (Maybe Header
forall a. Maybe a
Nothing, String -> SDoc
text "void")
| Bool
otherwise
= String -> SDoc -> (Maybe Header, SDoc)
forall a. HasCallStack => String -> SDoc -> a
pprPanic "toCType" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
t)
typeTyCon :: Type -> TyCon
typeTyCon :: Type -> TyCon
typeTyCon ty :: Type
ty
| Just (tc :: TyCon
tc, _) <- HasCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe (Type -> Type
unwrapType Type
ty)
= TyCon
tc
| Bool
otherwise
= String -> SDoc -> TyCon
forall a. HasCallStack => String -> SDoc -> a
pprPanic "DsForeign.typeTyCon" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty)
insertRetAddr :: DynFlags -> CCallConv
-> [(SDoc, SDoc, Type, CmmType)]
-> [(SDoc, SDoc, Type, CmmType)]
insertRetAddr :: DynFlags
-> CCallConv
-> [(SDoc, SDoc, Type, CmmType)]
-> [(SDoc, SDoc, Type, CmmType)]
insertRetAddr dflags :: DynFlags
dflags CCallConv args :: [(SDoc, SDoc, Type, CmmType)]
args
= case Platform -> Arch
platformArch Platform
platform of
ArchX86_64
| Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32 ->
let go :: Int -> [(SDoc, SDoc, Type, CmmType)]
-> [(SDoc, SDoc, Type, CmmType)]
go :: Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go 4 args :: [(SDoc, SDoc, Type, CmmType)]
args = DynFlags -> (SDoc, SDoc, Type, CmmType)
ret_addr_arg DynFlags
dflags (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: [(SDoc, SDoc, Type, CmmType)]
args
go n :: Int
n (arg :: (SDoc, SDoc, Type, CmmType)
arg:args :: [(SDoc, SDoc, Type, CmmType)]
args) = (SDoc, SDoc, Type, CmmType)
arg (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) [(SDoc, SDoc, Type, CmmType)]
args
go _ [] = []
in Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go 0 [(SDoc, SDoc, Type, CmmType)]
args
| Bool
otherwise ->
let go :: Int -> [(SDoc, SDoc, Type, CmmType)]
-> [(SDoc, SDoc, Type, CmmType)]
go :: Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go 6 args :: [(SDoc, SDoc, Type, CmmType)]
args = DynFlags -> (SDoc, SDoc, Type, CmmType)
ret_addr_arg DynFlags
dflags (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: [(SDoc, SDoc, Type, CmmType)]
args
go n :: Int
n (arg :: (SDoc, SDoc, Type, CmmType)
arg@(_,_,_,rep :: CmmType
rep):args :: [(SDoc, SDoc, Type, CmmType)]
args)
| CmmType -> CmmType -> Bool
cmmEqType_ignoring_ptrhood CmmType
rep CmmType
b64 = (SDoc, SDoc, Type, CmmType)
arg (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) [(SDoc, SDoc, Type, CmmType)]
args
| Bool
otherwise = (SDoc, SDoc, Type, CmmType)
arg (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go Int
n [(SDoc, SDoc, Type, CmmType)]
args
go _ [] = []
in Int
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
go 0 [(SDoc, SDoc, Type, CmmType)]
args
_ ->
DynFlags -> (SDoc, SDoc, Type, CmmType)
ret_addr_arg DynFlags
dflags (SDoc, SDoc, Type, CmmType)
-> [(SDoc, SDoc, Type, CmmType)] -> [(SDoc, SDoc, Type, CmmType)]
forall a. a -> [a] -> [a]
: [(SDoc, SDoc, Type, CmmType)]
args
where platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
insertRetAddr _ _ args :: [(SDoc, SDoc, Type, CmmType)]
args = [(SDoc, SDoc, Type, CmmType)]
args
ret_addr_arg :: DynFlags -> (SDoc, SDoc, Type, CmmType)
ret_addr_arg :: DynFlags -> (SDoc, SDoc, Type, CmmType)
ret_addr_arg dflags :: DynFlags
dflags = (String -> SDoc
text "original_return_addr", String -> SDoc
text "void*", Type
forall a. HasCallStack => a
undefined,
DynFlags -> Type -> CmmType
typeCmmType DynFlags
dflags Type
addrPrimTy)
getPrimTyOf :: Type -> UnaryType
getPrimTyOf :: Type -> Type
getPrimTyOf ty :: Type
ty
| Type -> Bool
isBoolTy Type
rep_ty = Type
intPrimTy
| Bool
otherwise =
case Type -> Maybe (TyCon, [Type], DataCon, [Type])
splitDataProductType_maybe Type
rep_ty of
Just (_, _, data_con :: DataCon
data_con, [prim_ty :: Type
prim_ty]) ->
ASSERT(dataConSourceArity data_con == 1)
ASSERT2(isUnliftedType prim_ty, ppr prim_ty)
Type
prim_ty
_other :: Maybe (TyCon, [Type], DataCon, [Type])
_other -> String -> SDoc -> Type
forall a. HasCallStack => String -> SDoc -> a
pprPanic "DsForeign.getPrimTyOf" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty)
where
rep_ty :: Type
rep_ty = Type -> Type
unwrapType Type
ty
primTyDescChar :: DynFlags -> Type -> Char
primTyDescChar :: DynFlags -> Type -> Char
primTyDescChar dflags :: DynFlags
dflags ty :: Type
ty
| Type
ty Type -> Type -> Bool
`eqType` Type
unitTy = 'v'
| Bool
otherwise
= case HasDebugCallStack => Type -> PrimRep
Type -> PrimRep
typePrimRep1 (Type -> Type
getPrimTyOf Type
ty) of
IntRep -> Char
signed_word
WordRep -> Char
unsigned_word
Int64Rep -> 'L'
Word64Rep -> 'l'
AddrRep -> 'p'
FloatRep -> 'f'
DoubleRep -> 'd'
_ -> String -> SDoc -> Char
forall a. HasCallStack => String -> SDoc -> a
pprPanic "primTyDescChar" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty)
where
(signed_word :: Char
signed_word, unsigned_word :: Char
unsigned_word)
| DynFlags -> Int
wORD_SIZE DynFlags
dflags Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 4 = ('W','w')
| DynFlags -> Int
wORD_SIZE DynFlags
dflags Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 8 = ('L','l')
| Bool
otherwise = String -> (Char, Char)
forall a. String -> a
panic "primTyDescChar"