{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE TypeApplications #-}
module GHC.Types.ForeignStubs
( ForeignStubs (..)
, CHeader(..)
, CStub(..)
, initializerCStub
, finalizerCStub
, appendStubC
)
where
import {-# SOURCE #-} GHC.Cmm.CLabel
import GHC.Platform
import GHC.Utils.Outputable
import Data.List ((++))
import Data.Monoid
import Data.Semigroup
import Data.Coerce
data CStub = CStub { CStub -> SDoc
getCStub :: SDoc
, CStub -> [CLabel]
getInitializers :: [CLabel]
, CStub -> [CLabel]
getFinalizers :: [CLabel]
}
emptyCStub :: CStub
emptyCStub :: CStub
emptyCStub = SDoc -> [CLabel] -> [CLabel] -> CStub
CStub SDoc
forall doc. IsOutput doc => doc
empty [] []
instance Monoid CStub where
mempty :: CStub
mempty = CStub
emptyCStub
instance Semigroup CStub where
CStub SDoc
a0 [CLabel]
b0 [CLabel]
c0 <> :: CStub -> CStub -> CStub
<> CStub SDoc
a1 [CLabel]
b1 [CLabel]
c1 =
SDoc -> [CLabel] -> [CLabel] -> CStub
CStub (SDoc
a0 SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ SDoc
a1) ([CLabel]
b0 [CLabel] -> [CLabel] -> [CLabel]
forall a. [a] -> [a] -> [a]
++ [CLabel]
b1) ([CLabel]
c0 [CLabel] -> [CLabel] -> [CLabel]
forall a. [a] -> [a] -> [a]
++ [CLabel]
c1)
functionCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
functionCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
functionCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body =
SDoc -> [CLabel] -> [CLabel] -> CStub
CStub SDoc
body' [] []
where
body' :: SDoc
body' = [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat
[ SDoc
declarations
, [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hsep [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"void", Platform -> CLabel -> SDoc
forall doc. IsLine doc => Platform -> CLabel -> doc
pprCLabel Platform
platform CLabel
clbl, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"(void)"]
, SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
braces SDoc
body
]
initializerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
initializerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
initializerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body =
Platform -> CLabel -> SDoc -> SDoc -> CStub
functionCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
CStub -> CStub -> CStub
forall a. Monoid a => a -> a -> a
`mappend` SDoc -> [CLabel] -> [CLabel] -> CStub
CStub SDoc
forall doc. IsOutput doc => doc
empty [CLabel
clbl] []
finalizerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
finalizerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
finalizerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
| Arch
ArchWasm32 <- Platform -> Arch
platformArch Platform
platform
=
Platform -> CLabel -> SDoc -> SDoc -> CStub
cxaAtexitFinalizerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
finalizerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
| OS
OSDarwin <- Platform -> OS
platformOS Platform
platform
=
Platform -> CLabel -> SDoc -> SDoc -> CStub
cxaAtexitFinalizerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
finalizerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
= Platform -> CLabel -> SDoc -> SDoc -> CStub
functionCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body
CStub -> CStub -> CStub
forall a. Monoid a => a -> a -> a
`mappend` SDoc -> [CLabel] -> [CLabel] -> CStub
CStub SDoc
forall doc. IsOutput doc => doc
empty [] [CLabel
clbl]
cxaAtexitFinalizerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
cxaAtexitFinalizerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
cxaAtexitFinalizerCStub Platform
platform CLabel
clbl SDoc
declarations SDoc
body =
let clbl_pretty :: SDoc
clbl_pretty = Platform -> CLabel -> SDoc
forall doc. IsLine doc => Platform -> CLabel -> doc
pprCLabel Platform
platform CLabel
clbl
fini_name :: SDoc
fini_name = [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [SDoc
clbl_pretty, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"$fini"]
wrapper_name :: SDoc
wrapper_name = [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [SDoc
clbl_pretty, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"$fini_atexit"]
c_code :: SDoc
c_code = [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat
[ SDoc
declarations
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"int __cxa_atexit(void (*)(void *), void *, void *);"
, [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"static void ", SDoc
fini_name, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"(void)"]
, SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
braces SDoc
body
, [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"static void ", SDoc
wrapper_name, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"(void *arg __attribute__((unused)))"]
, SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
braces ([SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [SDoc
fini_name, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"();"])
, [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hsep [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"void", SDoc
clbl_pretty, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"(void)"]
, SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
braces ([SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"__cxa_atexit(", SDoc
wrapper_name, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
", 0, 0);"])
]
in SDoc -> [CLabel] -> [CLabel] -> CStub
CStub SDoc
c_code [CLabel
clbl] []
newtype = { :: SDoc }
instance Monoid CHeader where
mempty :: CHeader
mempty = SDoc -> CHeader
CHeader SDoc
forall doc. IsOutput doc => doc
empty
mconcat :: [CHeader] -> CHeader
mconcat = ([SDoc] -> SDoc) -> [CHeader] -> CHeader
forall a b. Coercible a b => a -> b
coerce (forall doc. IsDoc doc => [doc] -> doc
vcat @SDoc)
instance Semigroup CHeader where
<> :: CHeader -> CHeader -> CHeader
(<>) = (SDoc -> SDoc -> SDoc) -> CHeader -> CHeader -> CHeader
forall a b. Coercible a b => a -> b
coerce (forall doc. IsDoc doc => doc -> doc -> doc
($$) @SDoc)
data ForeignStubs
= NoStubs
| ForeignStubs CHeader CStub
appendStubC :: ForeignStubs -> CStub -> ForeignStubs
appendStubC :: ForeignStubs -> CStub -> ForeignStubs
appendStubC ForeignStubs
NoStubs CStub
c_code = CHeader -> CStub -> ForeignStubs
ForeignStubs CHeader
forall a. Monoid a => a
mempty CStub
c_code
appendStubC (ForeignStubs CHeader
h CStub
c) CStub
c_code = CHeader -> CStub -> ForeignStubs
ForeignStubs CHeader
h (CStub
c CStub -> CStub -> CStub
forall a. Monoid a => a -> a -> a
`mappend` CStub
c_code)