Add a class HasDynFlags(getDynFlags)
[ghc.git] / compiler / ghci / LibFFI.hsc
1 -----------------------------------------------------------------------------
2 --
3 -- libffi bindings
4 --
5 -- (c) The University of Glasgow 2008
6 --
7 -----------------------------------------------------------------------------
8
9 #include <ffi.h>
10
11 {-# OPTIONS -fno-warn-tabs #-}
12 -- The above warning supression flag is a temporary kludge.
13 -- While working on this module you are encouraged to remove it and
14 -- detab the module (please do the detabbing in a separate patch). See
15 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSp
16 -- for details
17
18 module LibFFI (
19   ForeignCallToken,
20   prepForeignCall
21  ) where
22
23 import TyCon
24 import ForeignCall
25 import Panic
26 -- import Outputable
27 import Constants
28
29 import Foreign
30 import Foreign.C
31 import Text.Printf
32
33 ----------------------------------------------------------------------------
34
35 type ForeignCallToken = C_ffi_cif
36
37 prepForeignCall
38     :: CCallConv
39     -> [PrimRep]                        -- arg types
40     -> PrimRep                          -- result type
41     -> IO (Ptr ForeignCallToken)        -- token for making calls
42                                         -- (must be freed by caller)
43 prepForeignCall cconv arg_types result_type
44   = do
45     let n_args = length arg_types
46     arg_arr <- mallocArray n_args
47     let init_arg (ty,n) = pokeElemOff arg_arr n (primRepToFFIType ty)
48     mapM_ init_arg (zip arg_types [0..])
49     cif <- mallocBytes (#const sizeof(ffi_cif))
50     let abi = convToABI cconv
51     let res_ty = primRepToFFIType result_type
52     r <- ffi_prep_cif cif abi (fromIntegral n_args) res_ty arg_arr
53     if (r /= fFI_OK)
54        then ghcError (InstallationError 
55                         (printf "prepForeignCallFailed: %d" (show r)))
56        else return cif
57     
58 convToABI :: CCallConv -> C_ffi_abi
59 convToABI CCallConv   = fFI_DEFAULT_ABI
60 #ifdef mingw32_HOST_OS
61 convToABI StdCallConv = fFI_STDCALL
62 #endif
63 -- unknown conventions are mapped to the default, (#3336)
64 convToABI _           = fFI_DEFAULT_ABI
65
66 -- c.f. DsForeign.primTyDescChar
67 primRepToFFIType :: PrimRep -> Ptr C_ffi_type
68 primRepToFFIType r
69   = case r of
70      VoidRep     -> ffi_type_void
71      IntRep      -> signed_word
72      WordRep     -> unsigned_word
73      Int64Rep    -> ffi_type_sint64
74      Word64Rep   -> ffi_type_uint64
75      AddrRep     -> ffi_type_pointer
76      FloatRep    -> ffi_type_float
77      DoubleRep   -> ffi_type_double
78      _           -> panic "primRepToFFIType"
79   where
80     (signed_word, unsigned_word)
81        | wORD_SIZE == 4  = (ffi_type_sint32, ffi_type_uint32)
82        | wORD_SIZE == 8  = (ffi_type_sint64, ffi_type_uint64)
83        | otherwise       = panic "primTyDescChar"
84
85
86 data C_ffi_type
87 data C_ffi_cif
88
89 type C_ffi_status = (#type ffi_status)
90 type C_ffi_abi    = (#type ffi_abi)
91
92 foreign import ccall "&ffi_type_void"   ffi_type_void    :: Ptr C_ffi_type
93 --foreign import ccall "&ffi_type_uint8"  ffi_type_uint8   :: Ptr C_ffi_type
94 --foreign import ccall "&ffi_type_sint8"  ffi_type_sint8   :: Ptr C_ffi_type
95 --foreign import ccall "&ffi_type_uint16" ffi_type_uint16  :: Ptr C_ffi_type
96 --foreign import ccall "&ffi_type_sint16" ffi_type_sint16  :: Ptr C_ffi_type
97 foreign import ccall "&ffi_type_uint32" ffi_type_uint32  :: Ptr C_ffi_type
98 foreign import ccall "&ffi_type_sint32" ffi_type_sint32  :: Ptr C_ffi_type
99 foreign import ccall "&ffi_type_uint64" ffi_type_uint64  :: Ptr C_ffi_type
100 foreign import ccall "&ffi_type_sint64" ffi_type_sint64  :: Ptr C_ffi_type
101 foreign import ccall "&ffi_type_float"  ffi_type_float   :: Ptr C_ffi_type
102 foreign import ccall "&ffi_type_double" ffi_type_double  :: Ptr C_ffi_type
103 foreign import ccall "&ffi_type_pointer"ffi_type_pointer :: Ptr C_ffi_type
104
105 fFI_OK            :: C_ffi_status
106 fFI_OK            = (#const FFI_OK)
107 --fFI_BAD_ABI     :: C_ffi_status
108 --fFI_BAD_ABI     = (#const FFI_BAD_ABI)
109 --fFI_BAD_TYPEDEF :: C_ffi_status
110 --fFI_BAD_TYPEDEF = (#const FFI_BAD_TYPEDEF)
111
112 fFI_DEFAULT_ABI :: C_ffi_abi
113 fFI_DEFAULT_ABI = (#const FFI_DEFAULT_ABI)
114 #ifdef mingw32_HOST_OS
115 fFI_STDCALL     :: C_ffi_abi
116 fFI_STDCALL     = (#const FFI_STDCALL)
117 #endif
118
119 -- ffi_status ffi_prep_cif(ffi_cif *cif,
120 --                      ffi_abi abi,
121 --                      unsigned int nargs,
122 --                      ffi_type *rtype,
123 --                      ffi_type **atypes);
124
125 foreign import ccall "ffi_prep_cif"
126   ffi_prep_cif :: Ptr C_ffi_cif         -- cif
127                -> C_ffi_abi             -- abi
128                -> CUInt                 -- nargs
129                -> Ptr C_ffi_type        -- result type
130                -> Ptr (Ptr C_ffi_type)  -- arg types
131                -> IO C_ffi_status
132
133 -- Currently unused:
134
135 -- void ffi_call(ffi_cif *cif,
136 --            void (*fn)(),
137 --            void *rvalue,
138 --            void **avalue);
139
140 -- foreign import ccall "ffi_call"
141 --   ffi_call :: Ptr C_ffi_cif             -- cif
142 --            -> FunPtr (IO ())            -- function to call
143 --            -> Ptr ()                    -- put result here
144 --            -> Ptr (Ptr ())              -- arg values
145 --            -> IO ()