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