[project @ 2002-09-13 15:02:25 by simonpj]
[ghc-hetmet.git] / ghc / compiler / deSugar / DsForeign.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1998
3 %
4 \section[DsCCall]{Desugaring \tr{foreign} declarations}
5
6 Expanding out @foreign import@ and @foreign export@ declarations.
7
8 \begin{code}
9 module DsForeign ( dsForeigns ) where
10
11 #include "HsVersions.h"
12
13 import CoreSyn
14
15 import DsCCall          ( dsCCall, mkFCall, boxResult, unboxArg, resultWrapper )
16 import DsMonad
17
18 import HsSyn            ( ForeignDecl(..), ForeignExport(..),
19                           ForeignImport(..), CImportSpec(..) )
20 import TcHsSyn          ( TypecheckedForeignDecl )
21 import CoreUtils        ( exprType, mkInlineMe )
22 import Id               ( Id, idType, idName, mkSysLocal, setInlinePragma )
23 import Literal          ( Literal(..) )
24 import Module           ( moduleString )
25 import Name             ( getOccString, NamedThing(..) )
26 import OccName          ( encodeFS )
27 import Type             ( repType, eqType )
28 import TcType           ( Type, mkFunTys, mkForAllTys, mkTyConApp,
29                           mkFunTy, tcSplitTyConApp_maybe, 
30                           tcSplitForAllTys, tcSplitFunTys, tcTyConAppArgs,
31                         )
32
33 import HscTypes         ( ForeignStubs(..) )
34 import ForeignCall      ( ForeignCall(..), CCallSpec(..), 
35                           Safety(..), playSafe,
36                           CExportSpec(..),
37                           CCallConv(..), ccallConvToInt,
38                           ccallConvAttribute
39                         )
40 import CStrings         ( CLabelString )
41 import TysWiredIn       ( unitTy, stablePtrTyCon )
42 import TysPrim          ( addrPrimTy )
43 import PrelNames        ( hasKey, ioTyConKey, newStablePtrName, bindIOName )
44 import BasicTypes       ( Activation( NeverActive ) )
45 import Outputable
46 import Maybe            ( fromJust )
47 import FastString
48 \end{code}
49
50 Desugaring of @foreign@ declarations is naturally split up into
51 parts, an @import@ and an @export@  part. A @foreign import@ 
52 declaration
53 \begin{verbatim}
54   foreign import cc nm f :: prim_args -> IO prim_res
55 \end{verbatim}
56 is the same as
57 \begin{verbatim}
58   f :: prim_args -> IO prim_res
59   f a1 ... an = _ccall_ nm cc a1 ... an
60 \end{verbatim}
61 so we reuse the desugaring code in @DsCCall@ to deal with these.
62
63 \begin{code}
64 type Binding = (Id, CoreExpr)   -- No rec/nonrec structure;
65                                 -- the occurrence analyser will sort it all out
66
67 dsForeigns :: [TypecheckedForeignDecl] 
68            -> DsM (ForeignStubs, [Binding])
69 dsForeigns fos
70   = foldlDs combine (ForeignStubs empty empty [] [], []) fos
71  where
72   combine (ForeignStubs acc_h acc_c acc_hdrs acc_feb, acc_f) 
73           (ForeignImport id _ spec depr loc)
74     = dsFImport id spec            `thenDs` \(bs, h, c, hd) -> 
75       warnDepr depr loc                            `thenDs` \_              ->
76       returnDs (ForeignStubs (h $$ acc_h) (c $$ acc_c) (hd ++ acc_hdrs) acc_feb, 
77                 bs ++ acc_f)
78
79   combine (ForeignStubs acc_h acc_c acc_hdrs acc_feb, acc_f) 
80           (ForeignExport id _ (CExport (CExportStatic ext_nm cconv)) depr loc)
81     = dsFExport id (idType id) 
82                 ext_nm cconv False                 `thenDs` \(h, c) ->
83       warnDepr depr loc                            `thenDs` \_              ->
84       returnDs (ForeignStubs (h $$ acc_h) (c $$ acc_c) acc_hdrs (id:acc_feb), 
85                 acc_f)
86
87   warnDepr False _   = returnDs ()
88   warnDepr True  loc = dsWarn (loc, msg)
89    where
90     msg = ptext SLIT("foreign declaration uses deprecated non-standard syntax")
91 \end{code}
92
93
94 %************************************************************************
95 %*                                                                      *
96 \subsection{Foreign import}
97 %*                                                                      *
98 %************************************************************************
99
100 Desugaring foreign imports is just the matter of creating a binding
101 that on its RHS unboxes its arguments, performs the external call
102 (using the @CCallOp@ primop), before boxing the result up and returning it.
103
104 However, we create a worker/wrapper pair, thus:
105
106         foreign import f :: Int -> IO Int
107 ==>
108         f x = IO ( \s -> case x of { I# x# ->
109                          case fw s x# of { (# s1, y# #) ->
110                          (# s1, I# y# #)}})
111
112         fw s x# = ccall f s x#
113
114 The strictness/CPR analyser won't do this automatically because it doesn't look
115 inside returned tuples; but inlining this wrapper is a Really Good Idea 
116 because it exposes the boxing to the call site.
117
118 \begin{code}
119 dsFImport :: Id
120           -> ForeignImport
121           -> DsM ([Binding], SDoc, SDoc, [FastString])
122 dsFImport id (CImport cconv safety header lib spec)
123   = dsCImport id spec cconv safety        `thenDs` \(ids, h, c) ->
124     returnDs (ids, h, c, if nullFastString header then [] else [header])
125   -- FIXME: the `lib' field is needed for .NET ILX generation when invoking
126   --        routines that are external to the .NET runtime, but GHC doesn't
127   --        support such calls yet; if `nullFastString lib', the value was not given
128 dsFImport id (DNImport spec)
129   = dsFCall id (DNCall spec)              `thenDs` \(ids, h, c) ->
130     returnDs (ids, h, c, [])
131
132 dsCImport :: Id
133           -> CImportSpec
134           -> CCallConv
135           -> Safety
136           -> DsM ([Binding], SDoc, SDoc)
137 dsCImport id (CLabel cid)       _     _
138  = ASSERT(fromJust resTy `eqType` addrPrimTy)    -- typechecker ensures this
139    returnDs ([(id, rhs)], empty, empty)
140  where
141    (resTy, foRhs) = resultWrapper (idType id)
142    rhs            = foRhs (mkLit (MachLabel cid))
143 dsCImport id (CFunction target) cconv safety
144   = dsFCall id (CCall (CCallSpec target cconv safety))
145 dsCImport id CWrapper           cconv _
146   = dsFExportDynamic id cconv
147 \end{code}
148
149
150 %************************************************************************
151 %*                                                                      *
152 \subsection{Foreign calls}
153 %*                                                                      *
154 %************************************************************************
155
156 \begin{code}
157 dsFCall fn_id fcall
158   = let
159         ty                   = idType fn_id
160         (tvs, fun_ty)        = tcSplitForAllTys ty
161         (arg_tys, io_res_ty) = tcSplitFunTys fun_ty
162                 -- Must use tcSplit* functions because we want to 
163                 -- see that (IO t) in the corner
164     in
165     newSysLocalsDs arg_tys                      `thenDs` \ args ->
166     mapAndUnzipDs unboxArg (map Var args)       `thenDs` \ (val_args, arg_wrappers) ->
167
168     let
169         work_arg_ids  = [v | Var v <- val_args] -- All guaranteed to be vars
170
171         -- These are the ids we pass to boxResult, which are used to decide
172         -- whether to touch# an argument after the call (used to keep
173         -- ForeignObj#s live across a 'safe' foreign import).
174         maybe_arg_ids | unsafe_call fcall = work_arg_ids
175                       | otherwise         = []
176     in
177     boxResult maybe_arg_ids io_res_ty           `thenDs` \ (ccall_result_ty, res_wrapper) ->
178
179     getUniqueDs                                 `thenDs` \ ccall_uniq ->
180     getUniqueDs                                 `thenDs` \ work_uniq ->
181     let
182         -- Build the worker
183         worker_ty     = mkForAllTys tvs (mkFunTys (map idType work_arg_ids) ccall_result_ty)
184         the_ccall_app = mkFCall ccall_uniq fcall val_args ccall_result_ty
185         work_rhs      = mkLams tvs (mkLams work_arg_ids the_ccall_app)
186         work_id       = mkSysLocal (encodeFS FSLIT("$wccall")) work_uniq worker_ty
187
188         -- Build the wrapper
189         work_app     = mkApps (mkVarApps (Var work_id) tvs) val_args
190         wrapper_body = foldr ($) (res_wrapper work_app) arg_wrappers
191         wrap_rhs     = mkInlineMe (mkLams (tvs ++ args) wrapper_body)
192     in
193     returnDs ([(work_id, work_rhs), (fn_id, wrap_rhs)], empty, empty)
194
195 unsafe_call (CCall (CCallSpec _ _ safety)) = playSafe safety
196 unsafe_call (DNCall _)                     = False
197 \end{code}
198
199
200 %************************************************************************
201 %*                                                                      *
202 \subsection{Foreign export}
203 %*                                                                      *
204 %************************************************************************
205
206 The function that does most of the work for `@foreign export@' declarations.
207 (see below for the boilerplate code a `@foreign export@' declaration expands
208  into.)
209
210 For each `@foreign export foo@' in a module M we generate:
211 \begin{itemize}
212 \item a C function `@foo@', which calls
213 \item a Haskell stub `@M.$ffoo@', which calls
214 \end{itemize}
215 the user-written Haskell function `@M.foo@'.
216
217 \begin{code}
218 dsFExport :: Id                 -- Either the exported Id, 
219                                 -- or the foreign-export-dynamic constructor
220           -> Type               -- The type of the thing callable from C
221           -> CLabelString       -- The name to export to C land
222           -> CCallConv
223           -> Bool               -- True => foreign export dynamic
224                                 --         so invoke IO action that's hanging off 
225                                 --         the first argument's stable pointer
226           -> DsM ( SDoc         -- contents of Module_stub.h
227                  , SDoc         -- contents of Module_stub.c
228                  )
229
230 dsFExport fn_id ty ext_name cconv isDyn
231    = 
232      let
233         (tvs,sans_foralls)              = tcSplitForAllTys ty
234         (fe_arg_tys', orig_res_ty)      = tcSplitFunTys sans_foralls
235         -- We must use tcSplits here, because we want to see 
236         -- the (IO t) in the corner of the type!
237         fe_arg_tys | isDyn     = tail fe_arg_tys'
238                    | otherwise = fe_arg_tys'
239      in
240         -- Look at the result type of the exported function, orig_res_ty
241         -- If it's IO t, return         (t, True)
242         -- If it's plain t, return      (t, False)
243      (case tcSplitTyConApp_maybe orig_res_ty of
244         -- We must use tcSplit here so that we see the (IO t) in
245         -- the type.  [IO t is transparent to plain splitTyConApp.]
246
247         Just (ioTyCon, [res_ty])
248               -> ASSERT( ioTyCon `hasKey` ioTyConKey )
249                  -- The function already returns IO t
250                  returnDs (res_ty, True)
251
252         other -> -- The function returns t
253                  returnDs (orig_res_ty, False)
254      )
255                                         `thenDs` \ (res_ty,             -- t
256                                                     is_IO_res_ty) ->    -- Bool
257      let
258         (h_stub, c_stub) 
259            = mkFExportCBits ext_name 
260                             (if isDyn then Nothing else Just fn_id)
261                             fe_arg_tys res_ty is_IO_res_ty cconv
262      in
263      returnDs (h_stub, c_stub)
264 \end{code}
265
266 @foreign export dynamic@ lets you dress up Haskell IO actions
267 of some fixed type behind an externally callable interface (i.e.,
268 as a C function pointer). Useful for callbacks and stuff.
269
270 \begin{verbatim}
271 foreign export dynamic f :: (Addr -> Int -> IO Int) -> IO Addr
272
273 -- Haskell-visible constructor, which is generated from the above:
274 -- SUP: No check for NULL from createAdjustor anymore???
275
276 f :: (Addr -> Int -> IO Int) -> IO Addr
277 f cback =
278    bindIO (newStablePtr cback)
279           (\StablePtr sp# -> IO (\s1# ->
280               case _ccall_ createAdjustor cconv sp# ``f_helper'' s1# of
281                  (# s2#, a# #) -> (# s2#, A# a# #)))
282
283 foreign export "f_helper" f_helper :: StablePtr (Addr -> Int -> IO Int) -> Addr -> Int -> IO Int
284 -- `special' foreign export that invokes the closure pointed to by the
285 -- first argument.
286 \end{verbatim}
287
288 \begin{code}
289 dsFExportDynamic :: Id
290                  -> CCallConv
291                  -> DsM ([Binding], SDoc, SDoc)
292 dsFExportDynamic id cconv
293   =  newSysLocalDs ty                            `thenDs` \ fe_id ->
294      getModuleDs                                `thenDs` \ mod_name -> 
295      let 
296         -- hack: need to get at the name of the C stub we're about to generate.
297        fe_nm       = mkFastString (moduleString mod_name ++ "_" ++ toCName fe_id)
298      in
299      dsFExport id export_ty fe_nm cconv True    `thenDs` \ (h_code, c_code) ->
300      newSysLocalDs arg_ty                       `thenDs` \ cback ->
301      dsLookupGlobalId newStablePtrName  `thenDs` \ newStablePtrId ->
302      let
303         mk_stbl_ptr_app    = mkApps (Var newStablePtrId) [ Type arg_ty, Var cback ]
304      in
305      dsLookupGlobalId bindIOName                        `thenDs` \ bindIOId ->
306      newSysLocalDs (mkTyConApp stablePtrTyCon [arg_ty]) `thenDs` \ stbl_value ->
307      let
308       stbl_app cont ret_ty 
309         = mkApps (Var bindIOId)
310                  [ Type (mkTyConApp stablePtrTyCon [arg_ty])
311                  , Type ret_ty
312                  , mk_stbl_ptr_app
313                  , cont
314                  ]
315
316        {-
317         The arguments to the external function which will
318         create a little bit of (template) code on the fly
319         for allowing the (stable pointed) Haskell closure
320         to be entered using an external calling convention
321         (stdcall, ccall).
322        -}
323       adj_args      = [ mkIntLitInt (ccallConvToInt cconv)
324                       , Var stbl_value
325                       , mkLit (MachLabel fe_nm)
326                       ]
327         -- name of external entry point providing these services.
328         -- (probably in the RTS.) 
329       adjustor      = FSLIT("createAdjustor")
330      in
331      dsCCall adjustor adj_args PlayRisky False io_res_ty        `thenDs` \ ccall_adj ->
332         -- PlayRisky: the adjustor doesn't allocate in the Haskell heap or do a callback
333      let ccall_adj_ty = exprType ccall_adj
334          ccall_io_adj = mkLams [stbl_value]                  $
335                         Note (Coerce io_res_ty ccall_adj_ty)
336                              ccall_adj
337          io_app = mkLams tvs     $
338                   mkLams [cback] $
339                   stbl_app ccall_io_adj res_ty
340          fed = (id `setInlinePragma` NeverActive, io_app)
341                 -- Never inline the f.e.d. function, because the litlit
342                 -- might not be in scope in other modules.
343      in
344      returnDs ([fed], h_code, c_code)
345
346  where
347   ty                    = idType id
348   (tvs,sans_foralls)    = tcSplitForAllTys ty
349   ([arg_ty], io_res_ty) = tcSplitFunTys sans_foralls
350   [res_ty]              = tcTyConAppArgs io_res_ty
351         -- Must use tcSplit* to see the (IO t), which is a newtype
352   export_ty             = mkFunTy (mkTyConApp stablePtrTyCon [arg_ty]) arg_ty
353
354 toCName :: Id -> String
355 toCName i = showSDoc (pprCode CStyle (ppr (idName i)))
356 \end{code}
357
358 %*
359 %
360 \subsection{Generating @foreign export@ stubs}
361 %
362 %*
363
364 For each @foreign export@ function, a C stub function is generated.
365 The C stub constructs the application of the exported Haskell function 
366 using the hugs/ghc rts invocation API.
367
368 \begin{code}
369 mkFExportCBits :: FastString
370                -> Maybe Id      -- Just==static, Nothing==dynamic
371                -> [Type] 
372                -> Type 
373                -> Bool          -- True <=> returns an IO type
374                -> CCallConv 
375                -> (SDoc, SDoc)
376 mkFExportCBits c_nm maybe_target arg_htys res_hty is_IO_res_ty cc 
377  = (header_bits, c_bits)
378  where
379   -- Create up types and names for the real args
380   arg_cnames, arg_ctys :: [SDoc]
381   arg_cnames = mkCArgNames 1 arg_htys
382   arg_ctys   = map showStgType arg_htys
383
384   -- and also for auxiliary ones; the stable ptr in the dynamic case, and
385   -- a slot for the dummy return address in the dynamic + ccall case
386   extra_cnames_and_ctys
387      = case maybe_target of
388           Nothing -> [(text "the_stableptr", text "StgStablePtr")]
389           other   -> []
390        ++
391        case (maybe_target, cc) of
392           (Nothing, CCallConv) -> [(text "original_return_addr", text "void*")]
393           other                -> []
394
395   all_cnames_and_ctys :: [(SDoc, SDoc)]
396   all_cnames_and_ctys 
397      = extra_cnames_and_ctys ++ zip arg_cnames arg_ctys
398
399   -- stuff to do with the return type of the C function
400   res_hty_is_unit = res_hty `eqType` unitTy     -- Look through any newtypes
401
402   cResType | res_hty_is_unit = text "void"
403            | otherwise       = showStgType res_hty
404
405   -- Now we can cook up the prototype for the exported function.
406   pprCconv = case cc of
407                 CCallConv   -> empty
408                 StdCallConv -> text (ccallConvAttribute cc)
409
410   header_bits = ptext SLIT("extern") <+> fun_proto <> semi
411
412   fun_proto = cResType <+> pprCconv <+> ftext c_nm <>
413               parens (hsep (punctuate comma (map (\(nm,ty) -> ty <+> nm) 
414                                                  all_cnames_and_ctys)))
415
416   -- the target which will form the root of what we ask rts_evalIO to run
417   the_cfun
418      = case maybe_target of
419           Nothing    -> text "(StgClosure*)deRefStablePtr(the_stableptr)"
420           Just hs_fn -> char '&' <> ppr hs_fn <> text "_closure"
421
422   -- the expression we give to rts_evalIO
423   expr_to_run
424      = foldl appArg the_cfun (zip arg_cnames arg_htys)
425        where
426           appArg acc (arg_cname, arg_hty) 
427              = text "rts_apply" 
428                <> parens (acc <> comma <> mkHObj arg_hty <> parens arg_cname)
429
430   -- various other bits for inside the fn
431   declareResult = text "HaskellObj ret;"
432
433   return_what | res_hty_is_unit = empty
434               | otherwise       = parens (unpackHObj res_hty <> parens (text "ret"))
435
436   -- an extern decl for the fn being called
437   extern_decl
438      = case maybe_target of
439           Nothing -> empty
440           Just hs_fn -> text "extern StgClosure " <> ppr hs_fn <> text "_closure" <> semi
441
442   -- finally, the whole darn thing
443   c_bits =
444     space $$
445     extern_decl $$
446     fun_proto  $$
447     vcat 
448      [ lbrace
449      ,   text "SchedulerStatus rc;"
450      ,   declareResult
451           -- create the application + perform it.
452      ,   text "rc=rts_evalIO" <> parens (
453                 text "rts_apply" <> parens (
454                     text "(HaskellObj)"
455                  <> text (if is_IO_res_ty 
456                                 then "runIO_closure" 
457                                 else "runNonIO_closure")
458                  <> comma
459                  <> expr_to_run
460                 ) <+> comma
461                <> text "&ret"
462              ) <> semi
463      ,   text "rts_checkSchedStatus" <> parens (doubleQuotes (ftext c_nm)
464                                                 <> comma <> text "rc") <> semi
465      ,   text "return" <> return_what <> semi
466      , rbrace
467      ]
468
469
470 mkCArgNames :: Int -> [a] -> [SDoc]
471 mkCArgNames n as = zipWith (\ _ n -> text ('a':show n)) as [n..] 
472
473 mkHObj :: Type -> SDoc
474 mkHObj t = text "rts_mk" <> text (showFFIType t)
475
476 unpackHObj :: Type -> SDoc
477 unpackHObj t = text "rts_get" <> text (showFFIType t)
478
479 showStgType :: Type -> SDoc
480 showStgType t = text "Hs" <> text (showFFIType t)
481
482 showFFIType :: Type -> String
483 showFFIType t = getOccString (getName tc)
484  where
485   tc = case tcSplitTyConApp_maybe (repType t) of
486             Just (tc,_) -> tc
487             Nothing     -> pprPanic "showFFIType" (ppr t)
488 \end{code}