1{-
2(c) The University of Glasgow 2006
3(c) The AQUA Project, Glasgow University, 1994-1998
4
5
6Desugaring foreign calls
7-}
8
9{-# LANGUAGE CPP #-}
10module DsCCall
11        ( dsCCall
12        , mkFCall
13        , unboxArg
14        , boxResult
15        , resultWrapper
16        ) where
17
18#include "HsVersions.h"
19
20
21import GhcPrelude
22
23import CoreSyn
24
25import DsMonad
26import CoreUtils
27import MkCore
28import MkId
29import ForeignCall
30import DataCon
31import DsUtils
32
33import TcType
34import Type
35import Id   ( Id )
36import Coercion
37import PrimOp
38import TysPrim
39import TyCon
40import TysWiredIn
41import BasicTypes
42import Literal
43import PrelNames
44import DynFlags
45import Outputable
46import Util
47
48import Data.Maybe
49
50import RepType (mkCCallSpec)
51{-
52Desugaring of @ccall@s consists of adding some state manipulation,
53unboxing any boxed primitive arguments and boxing the result if
54desired.
55
56The state stuff just consists of adding in
57@PrimIO (\ s -> case s of { S# s# -> ... })@ in an appropriate place.
58
59The unboxing is straightforward, as all information needed to unbox is
60available from the type.  For each boxed-primitive argument, we
61transform:
62\begin{verbatim}
63   _ccall_ foo [ r, t1, ... tm ] e1 ... em
64   |
65   |
66   V
67   case e1 of { T1# x1# ->
68   ...
69   case em of { Tm# xm# -> xm#
70   ccall# foo [ r, t1#, ... tm# ] x1# ... xm#
71   } ... }
72\end{verbatim}
73
74The reboxing of a @_ccall_@ result is a bit tricker: the types don't
75contain information about the state-pairing functions so we have to
76keep a list of \tr{(type, s-p-function)} pairs.  We transform as
77follows:
78\begin{verbatim}
79   ccall# foo [ r, t1#, ... tm# ] e1# ... em#
80   |
81   |
82   V
83   \ s# -> case (ccall# foo [ r, t1#, ... tm# ] s# e1# ... em#) of
84          (StateAnd<r># result# state#) -> (R# result#, realWorld#)
85\end{verbatim}
86-}
87
88dsCCall :: CLabelString -- C routine to invoke
89        -> [CoreExpr]   -- Arguments (desugared)
90                        -- Precondition: none have levity-polymorphic types
91        -> Safety       -- Safety of the call
92        -> Type         -- Type of the result: IO t
93        -> DsM CoreExpr -- Result, of type ???
94
95dsCCall lbl args may_gc result_ty
96  = do (unboxed_args, arg_wrappers) <- mapAndUnzipM unboxArg args
97       (ccall_result_ty, res_wrapper) <- boxResult result_ty
98       uniq <- newUnique
99       dflags <- getDynFlags
100       let
101           arg_tys = map exprType args
102
103           raw_res_ty = case tcSplitIOType_maybe result_ty of
104             Just (_ioTyCon, res_ty) -> res_ty
105             Nothing                 -> result_ty
106
107           target = StaticTarget NoSourceText lbl Nothing True
108           the_fcall    = CCall (mkCCallSpec target CCallConv may_gc raw_res_ty arg_tys)
109           the_prim_app = mkFCall dflags uniq the_fcall unboxed_args ccall_result_ty
110       return (foldr ($) (res_wrapper the_prim_app) arg_wrappers)
111
112mkFCall :: DynFlags -> Unique -> ForeignCall
113        -> [CoreExpr]     -- Args
114        -> Type           -- Result type
115        -> CoreExpr
116-- Construct the ccall.  The only tricky bit is that the ccall Id should have
117-- no free vars, so if any of the arg tys do we must give it a polymorphic type.
118--      [I forget *why* it should have no free vars!]
119-- For example:
120--      mkCCall ... [s::StablePtr (a->b), x::Addr, c::Char]
121--
122-- Here we build a ccall thus
123--      (ccallid::(forall a b.  StablePtr (a -> b) -> Addr -> Char -> IO Addr))
124--                      a b s x c
125mkFCall dflags uniq the_fcall val_args res_ty
126  = ASSERT( all isTyVar tyvars )  -- this must be true because the type is top-level
127    mkApps (mkVarApps (Var the_fcall_id) tyvars) val_args
128  where
129    arg_tys = map exprType val_args
130    body_ty = (mkVisFunTys arg_tys res_ty)
131    tyvars  = tyCoVarsOfTypeWellScoped body_ty
132    ty      = mkInvForAllTys tyvars body_ty
133    the_fcall_id = mkFCallId dflags uniq the_fcall ty
134
135unboxArg :: CoreExpr                    -- The supplied argument, not levity-polymorphic
136         -> DsM (CoreExpr,              -- To pass as the actual argument
137                 CoreExpr -> CoreExpr   -- Wrapper to unbox the arg
138                )
139-- Example: if the arg is e::Int, unboxArg will return
140--      (x#::Int#, \W. case x of I# x# -> W)
141-- where W is a CoreExpr that probably mentions x#
142
143-- always returns a non-levity-polymorphic expression
144
145unboxArg arg
146  -- Primitive types: nothing to unbox
147  | isPrimitiveType arg_ty
148  = return (arg, \body -> body)
149
150  -- Recursive newtypes
151  | Just(co, _rep_ty) <- topNormaliseNewType_maybe arg_ty
152  = unboxArg (mkCastDs arg co)
153
154  -- Booleans
155  | Just tc <- tyConAppTyCon_maybe arg_ty,
156    tc `hasKey` boolTyConKey
157  = do dflags <- getDynFlags
158       prim_arg <- newSysLocalDs intPrimTy
159       return (Var prim_arg,
160              \ body -> Case (mkWildCase arg arg_ty intPrimTy
161                                       [(DataAlt falseDataCon,[],mkIntLit dflags 0),
162                                        (DataAlt trueDataCon, [],mkIntLit dflags 1)])
163                                        -- In increasing tag order!
164                             prim_arg
165                             (exprType body)
166                             [(DEFAULT,[],body)])
167
168  -- Data types with a single constructor, which has a single, primitive-typed arg
169  -- This deals with Int, Float etc; also Ptr, ForeignPtr
170  | is_product_type && data_con_arity == 1
171  = ASSERT2(isUnliftedType data_con_arg_ty1, pprType arg_ty)
172                        -- Typechecker ensures this
173    do case_bndr <- newSysLocalDs arg_ty
174       prim_arg <- newSysLocalDs data_con_arg_ty1
175       return (Var prim_arg,
176               \ body -> Case arg case_bndr (exprType body) [(DataAlt data_con,[prim_arg],body)]
177              )
178
179  -- Byte-arrays, both mutable and otherwise; hack warning
180  -- We're looking for values of type ByteArray, MutableByteArray
181  --    data ByteArray          ix = ByteArray        ix ix ByteArray#
182  --    data MutableByteArray s ix = MutableByteArray ix ix (MutableByteArray# s)
183  | is_product_type &&
184    data_con_arity == 3 &&
185    isJust maybe_arg3_tycon &&
186    (arg3_tycon ==  byteArrayPrimTyCon ||
187     arg3_tycon ==  mutableByteArrayPrimTyCon)
188  = do case_bndr <- newSysLocalDs arg_ty
189       vars@[_l_var, _r_var, arr_cts_var] <- newSysLocalsDs data_con_arg_tys
190       return (Var arr_cts_var,
191               \ body -> Case arg case_bndr (exprType body) [(DataAlt data_con,vars,body)]
192              )
193
194  | otherwise
195  = do l <- getSrcSpanDs
196       pprPanic "unboxArg: " (ppr l <+> ppr arg_ty)
197  where
198    arg_ty                                      = exprType arg
199    maybe_product_type                          = splitDataProductType_maybe arg_ty
200    is_product_type                             = isJust maybe_product_type
201    Just (_, _, data_con, data_con_arg_tys)     = maybe_product_type
202    data_con_arity                              = dataConSourceArity data_con
203    (data_con_arg_ty1 : _)                      = data_con_arg_tys
204
205    (_ : _ : data_con_arg_ty3 : _) = data_con_arg_tys
206    maybe_arg3_tycon               = tyConAppTyCon_maybe data_con_arg_ty3
207    Just arg3_tycon                = maybe_arg3_tycon
208
209boxResult :: Type
210          -> DsM (Type, CoreExpr -> CoreExpr)
211
212-- Takes the result of the user-level ccall:
213--      either (IO t),
214--      or maybe just t for a side-effect-free call
215-- Returns a wrapper for the primitive ccall itself, along with the
216-- type of the result of the primitive ccall.  This result type
217-- will be of the form
218--      State# RealWorld -> (# State# RealWorld, t' #)
219-- where t' is the unwrapped form of t.  If t is simply (), then
220-- the result type will be
221--      State# RealWorld -> (# State# RealWorld #)
222
223boxResult result_ty
224  | Just (io_tycon, io_res_ty) <- tcSplitIOType_maybe result_ty
225        -- isIOType_maybe handles the case where the type is a
226        -- simple wrapping of IO.  E.g.
227        --      newtype Wrap a = W (IO a)
228        -- No coercion necessary because its a non-recursive newtype
229        -- (If we wanted to handle a *recursive* newtype too, we'd need
230        -- another case, and a coercion.)
231        -- The result is IO t, so wrap the result in an IO constructor
232  = do  { res <- resultWrapper io_res_ty
233        ; let extra_result_tys
234                = case res of
235                     (Just ty,_)
236                       | isUnboxedTupleType ty
237                       -> let Just ls = tyConAppArgs_maybe ty in tail ls
238                     _ -> []
239
240              return_result state anss
241                = mkCoreUbxTup
242                    (realWorldStatePrimTy : io_res_ty : extra_result_tys)
243                    (state : anss)
244
245        ; (ccall_res_ty, the_alt) <- mk_alt return_result res
246
247        ; state_id <- newSysLocalDs realWorldStatePrimTy
248        ; let io_data_con = head (tyConDataCons io_tycon)
249              toIOCon     = dataConWrapId io_data_con
250
251              wrap the_call =
252                              mkApps (Var toIOCon)
253                                     [ Type io_res_ty,
254                                       Lam state_id $
255                                       mkWildCase (App the_call (Var state_id))
256                                             ccall_res_ty
257                                             (coreAltType the_alt)
258                                             [the_alt]
259                                     ]
260
261        ; return (realWorldStatePrimTy `mkVisFunTy` ccall_res_ty, wrap) }
262
263boxResult result_ty
264  = do -- It isn't IO, so do unsafePerformIO
265       -- It's not conveniently available, so we inline it
266       res <- resultWrapper result_ty
267       (ccall_res_ty, the_alt) <- mk_alt return_result res
268       let
269           wrap = \ the_call -> mkWildCase (App the_call (Var realWorldPrimId))
270                                           ccall_res_ty
271                                           (coreAltType the_alt)
272                                           [the_alt]
273       return (realWorldStatePrimTy `mkVisFunTy` ccall_res_ty, wrap)
274  where
275    return_result _ [ans] = ans
276    return_result _ _     = panic "return_result: expected single result"
277
278
279mk_alt :: (Expr Var -> [Expr Var] -> Expr Var)
280       -> (Maybe Type, Expr Var -> Expr Var)
281       -> DsM (Type, (AltCon, [Id], Expr Var))
282mk_alt return_result (Nothing, wrap_result)
283  = do -- The ccall returns ()
284       state_id <- newSysLocalDs realWorldStatePrimTy
285       let
286             the_rhs = return_result (Var state_id)
287                                     [wrap_result (panic "boxResult")]
288
289             ccall_res_ty = mkTupleTy Unboxed [realWorldStatePrimTy]
290             the_alt      = (DataAlt (tupleDataCon Unboxed 1), [state_id], the_rhs)
291
292       return (ccall_res_ty, the_alt)
293
294mk_alt return_result (Just prim_res_ty, wrap_result)
295  = -- The ccall returns a non-() value
296    ASSERT2( isPrimitiveType prim_res_ty, ppr prim_res_ty )
297             -- True because resultWrapper ensures it is so
298    do { result_id <- newSysLocalDs prim_res_ty
299       ; state_id <- newSysLocalDs realWorldStatePrimTy
300       ; let the_rhs = return_result (Var state_id)
301                                [wrap_result (Var result_id)]
302             ccall_res_ty = mkTupleTy Unboxed [realWorldStatePrimTy, prim_res_ty]
303             the_alt      = (DataAlt (tupleDataCon Unboxed 2), [state_id, result_id], the_rhs)
304       ; return (ccall_res_ty, the_alt) }
305
306
307resultWrapper :: Type
308              -> DsM (Maybe Type,               -- Type of the expected result, if any
309                      CoreExpr -> CoreExpr)     -- Wrapper for the result
310-- resultWrapper deals with the result *value*
311-- E.g. foreign import foo :: Int -> IO T
312-- Then resultWrapper deals with marshalling the 'T' part
313-- So if    resultWrapper ty = (Just ty_rep, marshal)
314--  then      marshal (e :: ty_rep) :: ty
315-- That is, 'marshal' wrape the result returned by the foreign call,
316-- of type ty_rep, into the value Haskell expected, of type 'ty'
317--
318-- Invariant: ty_rep is always a primitive type
319--            i.e. (isPrimitiveType ty_rep) is True
320
321resultWrapper result_ty
322  -- Base case 1: primitive types
323  | isPrimitiveType result_ty
324  = return (Just result_ty, \e -> e)
325
326  -- Base case 2: the unit type ()
327  | Just (tc,_) <- maybe_tc_app
328  , tc `hasKey` unitTyConKey
329  = return (Nothing, \_ -> Var unitDataConId)
330
331  -- Base case 3: the boolean type
332  | Just (tc,_) <- maybe_tc_app
333  , tc `hasKey` boolTyConKey
334  = do { dflags <- getDynFlags
335       ; let marshal_bool e
336               = mkWildCase e intPrimTy boolTy
337                   [ (DEFAULT                   ,[],Var trueDataConId )
338                   , (LitAlt (mkLitInt dflags 0),[],Var falseDataConId)]
339       ; return (Just intPrimTy, marshal_bool) }
340
341  -- Newtypes
342  | Just (co, rep_ty) <- topNormaliseNewType_maybe result_ty
343  = do { (maybe_ty, wrapper) <- resultWrapper rep_ty
344       ; return (maybe_ty, \e -> mkCastDs (wrapper e) (mkSymCo co)) }
345
346  -- The type might contain foralls (eg. for dummy type arguments,
347  -- referring to 'Ptr a' is legal).
348  | Just (tyvar, rest) <- splitForAllTy_maybe result_ty
349  = do { (maybe_ty, wrapper) <- resultWrapper rest
350       ; return (maybe_ty, \e -> Lam tyvar (wrapper e)) }
351
352  -- Data types with a single constructor, which has a single arg
353  -- This includes types like Ptr and ForeignPtr
354  | Just (tycon, tycon_arg_tys) <- maybe_tc_app
355  , Just data_con <- isDataProductTyCon_maybe tycon  -- One constructor, no existentials
356  , [unwrapped_res_ty] <- dataConInstOrigArgTys data_con tycon_arg_tys  -- One argument
357  = do { dflags <- getDynFlags
358       ; (maybe_ty, wrapper) <- resultWrapper unwrapped_res_ty
359       ; let narrow_wrapper = maybeNarrow dflags tycon
360             marshal_con e  = Var (dataConWrapId data_con)
361                              `mkTyApps` tycon_arg_tys
362                              `App` wrapper (narrow_wrapper e)
363       ; return (maybe_ty, marshal_con) }
364
365  | otherwise
366  = pprPanic "resultWrapper" (ppr result_ty)
367  where
368    maybe_tc_app = splitTyConApp_maybe result_ty
369
370-- When the result of a foreign call is smaller than the word size, we
371-- need to sign- or zero-extend the result up to the word size.  The C
372-- standard appears to say that this is the responsibility of the
373-- caller, not the callee.
374
375maybeNarrow :: DynFlags -> TyCon -> (CoreExpr -> CoreExpr)
376maybeNarrow dflags tycon
377  | tycon `hasKey` int8TyConKey   = \e -> App (Var (mkPrimOpId Narrow8IntOp)) e
378  | tycon `hasKey` int16TyConKey  = \e -> App (Var (mkPrimOpId Narrow16IntOp)) e
379  | tycon `hasKey` int32TyConKey
380         && wORD_SIZE dflags > 4         = \e -> App (Var (mkPrimOpId Narrow32IntOp)) e
381
382  | tycon `hasKey` word8TyConKey  = \e -> App (Var (mkPrimOpId Narrow8WordOp)) e
383  | tycon `hasKey` word16TyConKey = \e -> App (Var (mkPrimOpId Narrow16WordOp)) e
384  | tycon `hasKey` word32TyConKey
385         && wORD_SIZE dflags > 4         = \e -> App (Var (mkPrimOpId Narrow32WordOp)) e
386  | otherwise                     = id
387