File: ForeignStubs.hs

package info (click to toggle)
haskell-ghc-lib-parser 9.6.6.20240701-1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,280 kB
  • sloc: haskell: 109,582; yacc: 3,744; ansic: 2,480; makefile: 12
file content (92 lines) | stat: -rw-r--r-- 2,865 bytes parent folder | download | duplicates (2)
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
-- | Foreign export stubs
{-# 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 { getCStub :: SDoc
                   , getInitializers :: [CLabel]
                     -- ^ Initializers to be run at startup
                     -- See Note [Initializers and finalizers in Cmm] in
                     -- "GHC.Cmm.InitFini".
                   , getFinalizers :: [CLabel]
                     -- ^ Finalizers to be run at shutdown
                   }

emptyCStub :: CStub
emptyCStub = CStub empty [] []

instance Monoid CStub where
  mempty = emptyCStub

instance Semigroup CStub where
  CStub a0 b0 c0 <> CStub a1 b1 c1 =
      CStub (a0 $$ a1) (b0 ++ b1) (c0 ++ c1)

functionCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
functionCStub platform clbl declarations body =
    CStub body' [] []
  where
    body' = vcat
        [ declarations
        , hsep [text "void", pprCLabel platform clbl, text "(void)"]
        , braces body
        ]

-- | @initializerCStub fn_nm decls body@ is a 'CStub' containing C initializer
-- function (e.g. an entry of the @.init_array@ section) named
-- @fn_nm@ with the given body and the given set of declarations.
initializerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
initializerCStub platform clbl declarations body =
    functionCStub platform clbl declarations body
    `mappend` CStub empty [clbl] []

-- | @finalizerCStub fn_nm decls body@ is a 'CStub' containing C finalizer
-- function (e.g. an entry of the @.fini_array@ section) named
-- @fn_nm@ with the given body and the given set of declarations.
finalizerCStub :: Platform -> CLabel -> SDoc -> SDoc -> CStub
finalizerCStub platform clbl declarations body =
    functionCStub platform clbl declarations body
    `mappend` CStub empty [] [clbl]

newtype CHeader = CHeader { getCHeader :: SDoc }

instance Monoid CHeader where
  mempty = CHeader empty
  mconcat = coerce (vcat @SDoc)

instance Semigroup CHeader where
    (<>) = coerce (($$) @SDoc)

-- | Foreign export stubs
data ForeignStubs
  = NoStubs
      -- ^ We don't have any stubs
  | ForeignStubs CHeader CStub
      -- ^ There are some stubs. Parameters:
      --
      --  1) Header file prototypes for
      --     "foreign exported" functions
      --
      --  2) C stubs to use when calling
      --     "foreign exported" functions

appendStubC :: ForeignStubs -> CStub -> ForeignStubs
appendStubC NoStubs         c_code = ForeignStubs mempty c_code
appendStubC (ForeignStubs h c) c_code = ForeignStubs h (c `mappend` c_code)