2 % (c) The AQUA Project, Glasgow University, 1998
4 \section[DsCCall]{Desugaring \tr{foreign} declarations}
6 Expanding out @foreign import@ and @foreign export@ declarations.
9 module DsForeign ( dsForeigns ) where
12 #include "HsVersions.h"
16 import DsCCall ( getIoOkDataCon, boxResult, unboxArg,
22 import HsSyn ( ExtName(..), ForeignDecl(..), isDynamic )
24 import TcHsSyn ( maybeBoxedPrimType, TypecheckedForeignDecl )
25 import CoreUtils ( coreExprType )
26 import Id ( Id, dataConArgTys, idType, idName,
27 mkVanillaId, dataConRawArgTys,
28 dataConTyCon, mkIdVisible
30 import IdInfo ( noIdInfo )
31 import Literal ( Literal(..), mkMachInt )
32 import Maybes ( maybeToBool )
33 import Name ( nameString, occNameString, nameOccName, nameUnique )
34 import PrelVals ( packStringForCId, eRROR_ID )
35 import PrimOp ( PrimOp(..) )
36 import Type ( isUnpointedType, splitAlgTyConApp_maybe,
37 splitTyConApp_maybe, splitFunTys, splitForAllTys,
38 Type, mkFunTys, applyTy, mkForAllTys, mkTyConApp,
39 typePrimRep, mkTyVarTy, mkFunTy, splitAppTy
41 import PrimRep ( showPrimRepToUser, PrimRep(..) )
42 import TyVar ( TyVar )
43 import TyCon ( tyConDataCons )
44 import TysPrim ( byteArrayPrimTy, realWorldStatePrimTy,
45 byteArrayPrimTyCon, mutableByteArrayPrimTyCon,
46 realWorldTy, addrPrimTy, mkStablePtrPrimTy,
49 import TysWiredIn ( getStatePairingConInfo,
50 unitDataCon, stringTy,
51 realWorldStateTy, stateDataCon,
52 isFFIArgumentTy, unitTy,
53 addrTy, stablePtrTyCon,
54 stateAndPtrPrimDataCon
59 Desugaring of @foreign@ declarations is naturally split up into
60 parts, an @import@ and an @export@ part. A @foreign import@
63 foreign import cc nm f :: prim_args -> IO prim_res
67 f :: prim_args -> IO prim_res
68 f a1 ... an = _ccall_ nm cc a1 ... an
70 so we reuse the desugaring code in @DsCCall@ to deal with these.
73 dsForeigns :: [TypecheckedForeignDecl]
74 -> DsM ( [CoreBinding] -- desugared foreign imports
75 , [CoreBinding] -- helper functions for foreign exports
76 , SDoc -- auxilliary code to emit into .hc file
77 , SDoc -- Header file prototypes for "foreign exported" functions.
78 , SDoc -- C stubs to use when calling "foreign exported" funs.
80 dsForeigns fos = foldlDs combine ([],[],empty,empty,empty) fos
82 combine (acc_fi, acc_fe, acc_hc, acc_h, acc_c) fo@(ForeignDecl i imp_exp _ ext_nm cconv _)
84 dsFImport i (idType i) uns ext_nm cconv `thenDs` \ b ->
85 returnDs (b:acc_fi, acc_fe, acc_hc, acc_h, acc_c)
87 dsFExportDynamic i (idType i) ext_nm cconv `thenDs` \ (fi,fe,hc,h,c) ->
88 returnDs (fi:acc_fi, fe:acc_fe, hc $$ acc_hc, h $$ acc_h, c $$ acc_c)
90 dsFExport i (idType i) ext_nm cconv False `thenDs` \ (fe,hc,h,c) ->
91 returnDs (acc_fi, fe:acc_fe, hc $$ acc_hc, h $$ acc_h, c $$ acc_c)
94 isForeignImport = maybeToBool imp_exp
99 Desugaring foreign imports is just the matter of creating a binding
100 that on its RHS unboxes its arguments, performs the external call
101 (using the CCallOp primop), before boxing the result up and returning it.
105 -> Type -- Type of foreign import.
106 -> Bool -- True <=> might cause Haskell GC
110 dsFImport nm ty may_not_gc ext_name cconv =
111 newSysLocalDs realWorldStatePrimTy `thenDs` \ old_s ->
112 mkArgs ty `thenDs` \ (tvs, args, io_res_ty) ->
113 mapAndUnzipDs unboxArg args `thenDs` \ (unboxed_args, arg_wrappers) ->
115 final_args = Var old_s : unboxed_args
116 (ioOkDataCon, ioDataCon, result_ty) = getIoOkDataCon io_res_ty
118 boxResult ioOkDataCon result_ty `thenDs` \ (final_result_ty, res_wrapper) ->
123 ExtName fs _ -> Just fs
125 the_ccall_op = CCallOp label False (not may_not_gc) cconv
126 (map coreExprType final_args)
129 mkPrimDs the_ccall_op (map VarArg final_args) `thenDs` \ the_prim_app ->
131 the_body = mkValLam [old_s]
132 (foldr ($) (res_wrapper the_prim_app) arg_wrappers)
134 newSysLocalDs (coreExprType the_body) `thenDs` \ ds ->
136 io_app = mkValApp (mkTyApp (Var ioDataCon) [result_ty]) [VarArg ds]
137 fo_rhs = mkTyLam tvs $
138 mkValLam (map (\ (Var x) -> x) args)
139 (mkCoLetAny (NonRec ds the_body) io_app)
141 returnDs (NonRec nm fo_rhs)
143 mkArgs :: Type -> DsM ([TyVar], [CoreExpr], Type)
145 case splitFunTys sans_foralls of
147 newSysLocalsDs arg_tys `thenDs` \ ds_args ->
148 returnDs (tvs, map Var ds_args, res_ty)
150 (tvs, sans_foralls) = splitForAllTys ty
156 -> Type -- Type of foreign export.
159 -> Bool -- True => invoke IO action that's hanging off
160 -- the first argument's stable pointer
161 -> DsM (CoreBinding, SDoc, SDoc, SDoc)
162 dsFExport i ty ext_name cconv isDyn =
163 newSysLocalDs realWorldStatePrimTy `thenDs` \ s1 ->
164 newSysLocalDs realWorldStatePrimTy `thenDs` \ s3 ->
165 newSysLocalDs helper_ty `thenDs` \ f_helper ->
166 newSysLocalsDs helper_arg_tys `thenDs` \ helper_args ->
167 newSysLocalDs res_ty `thenDs` \ v1 ->
168 unboxResult the_prim_result_ty res_ty s3 v1 `thenDs` \ (state_and_prim_ty, unpack_result) ->
169 zipWithDs boxArg fe_arg_tys helper_args `thenDs` \ stuff ->
171 newSysLocalDs realWorldStatePrimTy `thenDs` \ s11 ->
172 newSysLocalDs stbl_ptr_ty `thenDs` \ stbl_ptr ->
173 newSysLocalDs stbl_ptr_to_ty `thenDs` \ f ->
174 mkPrimDs DeRefStablePtrOp
175 [TyArg stbl_ptr_to_ty,
176 VarArg (Var stbl_ptr),
177 VarArg (Var s1)] `thenDs` \ the_deref_app ->
181 (AlgAlts [(stateAndPtrPrimDataCon, [s11, f], cont)]
184 returnDs (f, stbl_app, s11, stbl_ptr)
189 panic "stbl_ptr" -- should never be touched.
190 )) `thenDs` \ (i, getFun_wrapper, s2, stbl_ptr) ->
192 (boxed_args, arg_wrappers) = unzip stuff
195 | isDyn = stbl_ptr:helper_args
196 | otherwise = helper_args
199 | isDyn = stbl_ptr_ty:helper_arg_tys
200 | otherwise = helper_arg_tys
202 fe_app = mkGenApp (Var i) (map (TyArg . mkTyVarTy) tvs ++ map VarArg boxed_args)
205 mkValApp (Note (Coerce io_result_ty io_res) fe_app)
208 newFailLocalDs (coreExprType the_app) `thenDs` \ wild ->
209 getModuleAndGroupDs `thenDs` \ (mod,_) ->
210 getUniqueDs `thenDs` \ uniq ->
215 mkValLam wrapper_args $
217 foldr ($) (perform_and_unpack) arg_wrappers
220 Case the_app (AlgAlts [(ioOkDataCon, [s3, v1], unpack_result)]
221 (BindDefault wild err))
227 full_msg = "Exception caught: " ++ _UNPK_ (nameString (idName i))
228 msg = NoRepStr (_PK_ full_msg)
229 err = mkApp (Var eRROR_ID) [state_and_prim_ty] [LitArg msg]
231 f_helper_glob = (mkIdVisible mod uniq f_helper)
232 (hc_stub, h_stub, c_stub) = fexportEntry c_nm f_helper_glob wrapper_arg_tys the_prim_result_ty cconv
234 returnDs (NonRec f_helper_glob the_body, hc_stub, h_stub, c_stub)
236 (tvs,sans_foralls) = splitForAllTys ty
237 (fe_arg_tys', io_res) = splitFunTys sans_foralls
238 (ioOkDataCon, ioDataCon, res_ty) = getIoOkDataCon io_res
240 maybe_data_type = splitAlgTyConApp_maybe res_ty
241 Just (tycon, tycon_arg_tys, data_cons) = maybe_data_type
242 (the_data_con : other_data_cons) = data_cons
244 data_con_arg_tys = dataConArgTys the_data_con tycon_arg_tys
245 (prim_result_ty : other_args_tys) = data_con_arg_tys
247 ioDataConTy = idType ioDataCon
248 (io_tvs, ioDataConTy') = splitForAllTys ioDataConTy
249 ([arg_ty], _) = splitFunTys ioDataConTy'
250 io_result_ty = applyTy (mkForAllTys io_tvs arg_ty) res_ty
252 (_, stbl_ptr_ty') = splitForAllTys stbl_ptr_ty
253 (_, stbl_ptr_to_ty) = splitAppTy stbl_ptr_ty'
256 | isDyn = tail fe_arg_tys'
257 | otherwise = fe_arg_tys'
259 (stbl_ptr_ty, helper_arg_tys) =
260 case (map unboxTy fe_arg_tys') of
261 (x:xs) | isDyn -> (x,xs)
262 ls -> (error "stbl_ptr_ty", ls)
266 mkFunTys (arg_tys ++ [realWorldStatePrimTy])
270 | isDyn = stbl_ptr_ty : helper_arg_tys
271 | otherwise = helper_arg_tys
274 | null data_con_arg_tys = Nothing
275 | otherwise = Just prim_result_ty
278 | (null other_data_cons) &&
279 (null data_con_arg_tys) = realWorldStateTy
280 | otherwise = snd (getStatePairingConInfo (unboxTy res_ty))
283 "foreign export dynamic" lets you dress up Haskell IO actions
284 of some fixed type behind an externally callable interface (i.e.,
285 as a C function pointer). Useful for callbacks and stuff.
288 foreign export stdcall f :: (Addr -> Int -> IO Int) -> IO Addr
290 -- Haskell-visible constructor, which is generated from the
293 f :: (Addr -> Int -> IO Int) -> IO Addr
294 f cback = IO ( \ s1# ->
295 case makeStablePtr# cback s1# of { StateAndStablePtr# s2# sp# ->
296 case _ccall_ "mkAdjustor" sp# ``f_helper'' s2# of
297 StateAndAddr# s3# a# ->
307 foreign export "f_helper" f_helper :: StablePtr (Addr -> Int -> IO Int) -> Addr -> Int -> IO Int
308 -- `special' foreign export that invokes the closure pointed to by the
313 dsFExportDynamic :: Id
314 -> Type -- Type of foreign export.
317 -> DsM (CoreBinding, CoreBinding, SDoc, SDoc, SDoc)
318 dsFExportDynamic i ty ext_name cconv =
319 newSysLocalDs ty `thenDs` \ fe_id ->
321 -- hack: need to get at the name of the C stub we're about to generate.
322 fe_nm = toCName fe_id
323 fe_ext_name = ExtName (_PK_ fe_nm) Nothing
325 dsFExport i export_ty fe_ext_name cconv True `thenDs` \ (fe@(NonRec fe_helper fe_expr), hc_code, h_code, c_code) ->
326 newSysLocalDs realWorldStatePrimTy `thenDs` \ s1 ->
327 newSysLocalDs realWorldStatePrimTy `thenDs` \ s2 ->
328 newSysLocalDs realWorldStatePrimTy `thenDs` \ s3 ->
329 newSysLocalDs arg_ty `thenDs` \ cback_arg ->
330 newSysLocalDs arg_ty `thenDs` \ cback ->
331 newSysLocalDs (mkStablePtrPrimTy arg_ty) `thenDs` \ stbl ->
332 newSysLocalDs addrPrimTy `thenDs` \ addrPrim ->
333 newSysLocalDs addrTy `thenDs` \ addr ->
334 mkPrimDs MakeStablePtrOp [TyArg arg_ty,
336 VarArg (Var s1)] `thenDs` \ mkStablePtr_app ->
337 mkPrimDs Addr2IntOp [VarArg (Var addrPrim)] `thenDs` \ the_addr2Int_app ->
338 boxArg addrTy addrPrim `thenDs` \ (addr_result, addrPrim_wrapper) ->
340 (stateAndStablePtrPrimDataCon, _) = getStatePairingConInfo (mkStablePtrPrimTy arg_ty)
341 (stateAndAddrPrimDataCon, stateAndAddrPrimTy) = getStatePairingConInfo addrPrimTy
344 | cconv == stdCallConv = 1
347 ccall_args = [Var s2, Lit (mkMachInt cc),
349 Lit (MachLitLit (_PK_ fe_nm) AddrRep)]
351 label = Just SLIT("createAdjustor")
352 the_ccall_op = CCallOp label False False{-won't GC-} cCallConv
353 (map coreExprType ccall_args)
356 mkPrimDs the_ccall_op (map VarArg ccall_args) `thenDs` \ the_ccall_app ->
358 [TyArg res_ty, VarArg (Var s3), VarArg (Var addr_result)]
359 `thenDs` \ ioOkApp ->
360 newSysLocalDs intPrimTy `thenDs` \ default_val ->
362 the_mkStablePtr = \ cont ->
364 (AlgAlts [(stateAndStablePtrPrimDataCon, [s2, stbl], cont)]
367 the_ccall = \ cont ->
369 (AlgAlts [(stateAndAddrPrimDataCon, [s3, addrPrim], cont)]
371 the_addr2Int = \ cont ->
372 Case the_addr2Int_app
373 (PrimAlts [(mkMachInt 0, io_fail)]
374 (BindDefault default_val cont))
376 io_fail = mkApp (Var eRROR_ID) [coreExprType wrap_res] [LitArg msg]
377 full_msg = "Exception caught: " ++ _UNPK_ (nameString (idName i))
378 msg = NoRepStr (_PK_ full_msg)
380 wrap_res = addrPrim_wrapper ioOkApp
383 mkValLam [cback,s1] $
386 the_addr2Int wrap_res
389 newSysLocalDs (coreExprType the_body) `thenDs` \ ds ->
390 newSysLocalDs (mkFunTy realWorldStatePrimTy
391 (coreExprType ioOkApp)) `thenDs` \ ap ->
393 io_app = mkValApp (mkTyApp (Var ioDataCon) [res_ty]) [VarArg ap]
396 mkValLam [cback_arg] $
397 mkCoLetAny (NonRec ds the_body) $
398 mkCoLetAny (NonRec ap (mkValApp (mkTyApp (Var ds) (map mkTyVarTy tvs)) [VarArg cback_arg])) $
401 returnDs (NonRec i io_action, fe, hc_code, h_code, c_code)
403 (tvs,sans_foralls) = splitForAllTys ty
404 ([arg_ty], io_res) = splitFunTys sans_foralls
405 (ioOkDataCon, ioDataCon, res_ty) = getIoOkDataCon io_res
407 ioDataConTy = idType ioDataCon
408 (io_tvs, ioDataConTy') = splitForAllTys ioDataConTy
409 -- ([arg_ty], _) = splitFunTys ioDataConTy'
410 io_result_ty = applyTy (mkForAllTys io_tvs arg_ty) res_ty
412 export_ty = mkFunTy (mkTyConApp stablePtrTyCon [arg_ty]) arg_ty
414 toCName :: Id -> String
415 toCName i = showSDoc (pprCode CStyle (ppr (idName i)))
421 \subsection{Helper functions}
425 @boxArg@ boxes up an argument in preparation for calling
426 a function that maybe expects a boxed version of it, i.e.,
429 boxArg Addr a# ==> let ds_foo :: Addr ; ds_foo = A# a# in f ...ds_foo..
433 boxArg :: Type -- Expected type after possible boxing of arg.
434 -> Id -- The (unboxed) argument
435 -> DsM (Id, -- To pass as the actual, boxed argument
436 CoreExpr -> CoreExpr -- Wrapper to box the arg
438 boxArg box_ty prim_arg
439 | isUnpointedType box_ty = returnDs (prim_arg, \body -> body)
440 -- Data types with a single constructor,
441 -- which has a single, primitive-typed arg
443 = newSysLocalDs box_ty `thenDs` \ box_arg ->
445 , Let (NonRec box_arg (mkCon box_data_con tys_applied [VarArg prim_arg]))
448 maybe_boxed_prim_arg_ty = maybeBoxedPrimType box_ty
449 (Just (_,tys_applied,_)) = splitAlgTyConApp_maybe box_ty
450 (Just (box_data_con, _)) = maybe_boxed_prim_arg_ty
453 @foreign export@ed functions may return a value back to the outside world.
454 @unboxResult@ takes care of converting from the (boxed) value that the
455 exported action returns to the (unboxed) value that is returned across
459 unboxResult :: Maybe Type -- the (unboxed) type we want to return (along with the state token)
460 -- Nothing => no result, just the state token.
461 -> Type -- the (boxed) type we have in our hand.
462 -> Id -- the state token
464 -> DsM (Type, -- type of returned expression.
465 CoreExpr) -- expr that unboxes result and returns state+unboxed result.
467 unboxResult mb_res_uboxed_ty res_ty new_s v_boxed
468 | not (maybeToBool mb_res_uboxed_ty)
469 = -- no result, just return state token
470 mkConDs stateDataCon [ TyArg realWorldTy
471 , VarArg (Var new_s)] `thenDs` \ the_st ->
472 returnDs (realWorldStateTy, the_st)
475 -- oops! can't see the data constructors
476 = can'tSeeDataConsPanic "result" res_ty
478 | (maybeToBool maybe_data_type) && -- Data type
479 (null other_data_cons) && -- - with one constructor,
480 isUnpointedType res_uboxed_ty -- - and of primitive type.
481 -- (Glasgow extension)
483 newSysLocalDs res_uboxed_ty `thenDs` \ v_unboxed ->
484 mkConDs state_and_prim_datacon
485 ((TyArg realWorldTy):map (TyArg ) tycon_arg_tys ++
487 , VarArg (Var v_unboxed)]) `thenDs` \ the_result ->
489 the_alt = (the_data_con, [v_unboxed], the_result)
491 returnDs (state_and_prim_ty,
492 Case (Var v_boxed) (AlgAlts [the_alt] NoDefault))
495 = pprPanic "unboxResult: " (ppr res_ty)
497 (Just res_uboxed_ty) = mb_res_uboxed_ty
499 maybe_data_type = splitAlgTyConApp_maybe res_ty
500 Just (tycon, tycon_arg_tys, data_cons) = maybe_data_type
501 (the_data_con : other_data_cons) = data_cons
503 (state_and_prim_datacon, state_and_prim_ty) = getStatePairingConInfo res_uboxed_ty
507 Returned the unboxed type of a (primitive) type:
510 unboxTy :: Type -> Type
512 | isUnpointedType ty || (ty == unitTy) = ty
514 ASSERT( isFFIArgumentTy ty ) -- legal arg types subsume result types.
515 case splitTyConApp_maybe ty of
517 case (tyConDataCons tyc) of
518 [dc] -> case (dataConArgTys dc ts) of
520 -- HACK: for the array types, the prim type is
521 -- the second tycon arg.
523 _ -> pprPanic "unboxTy: " (ppr ty)
524 _ -> pprPanic "unboxTy: " (ppr ty)
525 _ -> pprPanic "unboxTy: " (ppr ty)
531 \subsection{Generating @foreign export@ stubs}
535 [Severe hack to get @foreign export@ off the ground:]
537 For each @foreign export@ function, a C stub together with a @.hc@ stub
538 is generated. The C stub enters the .hc stub, setting up the passing of
539 parameters from C land to STG land through the use of global variables
540 (don't worry, this just a temporary solution!). Ditto for the result.
543 The generation of .hc code will go once the transition is
544 made over to the new rts. Hence the hack, instead of extending
545 AbsCSyn to cope with the .hc code generated.
549 fexportEntry :: FAST_STRING -> Id -> [Type] -> Maybe Type -> CallConv -> (SDoc, SDoc, SDoc)
550 fexportEntry c_nm helper args res cc =
551 ( paramArea $$ stopTemplate $$ startTemplate $$ vtblTemplate, h_code, c_code )
553 (h_code, c_code) = mkCStub c_nm h_stub_nm args res cc
556 vcat (zipWith declVar ( res_ty : param_tys ) ( res_name : param_names ) )
558 -- name of the (Haskell) helper function generated by the desugarer.
560 h_stub_nm = text foreign_export_prefix <> h_nm
561 closure = h_nm <> text "_closure"
563 param_names = zipWith (\ i _ -> h_stub_nm <> text ('_':show i)) [1..] args
564 param_tys = map (ppr.typePrimRep) args
568 Nothing -> (empty, empty)
569 Just t -> (h_stub_nm <> text "_res", ppr (typePrimRep t))
573 [ text "extern realWorldZh_closure;"
574 , ptext SLIT("STGFUN") <> parens (h_stub_nm)
576 , ptext SLIT("FUNBEGIN;")
577 , text "RestoreAllStgRegs();"
578 , stackCheck param_names
582 , vcat (map pushArg (reverse param_names))
583 , text "Node=" <> closure <> semi
584 , text "ENT_VIA_NODE();" -- ticky count
585 , text "InfoPtr=(D_)(INFO_PTR(Node));"
586 , text "JMP_(ENTRY_CODE(InfoPtr));"
593 [ ptext SLIT("STGFUN") <> parens (text "stop" <> h_stub_nm <> text "DirectReturn")
595 , ptext SLIT("FUNBEGIN;")
598 , text "#if defined(__STG_GCC_REGS__)"
599 , text "SaveAllStgRegs();"
601 , text "SAVE_Hp = Hp;"
602 , text "SAVE_HpLim = HpLim;"
604 , text "JMP_(miniInterpretEnd);"
611 [ text "const W_ vtbl_" <> h_stub_nm <> text "[] = {"
612 , vcat (punctuate comma (replicate 8 dir_ret))
616 dir_ret = text "(W_)stop" <> h_stub_nm <> text "DirectReturn"
621 Just _ -> res_name <> equals <> text "R3.i;" -- wrong
624 text "SpB -= BREL(1);" $$
625 text "*SpB = (W_)RetReg;"
628 text "RetReg=(StgRetAddr)*SpB;" $$
629 text "SpB += BREL(1);"
632 text "RetReg=(StgRetAddr)UNVEC(stop" <> h_stub_nm <>
633 text "DirectReturn,vtbl_" <> h_stub_nm <> text ");"
636 text "SpB -= BREL(1);" $$
637 text "*SpB = (W_)realWorldZh_closure;"
641 text "SpB -= BREL(1);" $$
642 text "*SpB = (W_)" <> nm <> semi
645 text "STK_CHK(LivenessReg,0," <> sz <> text ",0,0,0,0);"
648 hsep $ punctuate (text " + ") (text "1":(map sizer args))
650 sizer x = text "BYTES_TO_STGWORDS" <> parens (text "sizeof" <> parens x)
652 foreign_export_prefix :: String
653 foreign_export_prefix = "__fexp_"
655 mkCStub :: FAST_STRING -> SDoc -> [Type] -> Maybe Type -> CallConv -> (SDoc, SDoc)
656 mkCStub c_nm h_stub_nm args res cc =
657 ( hsep [ ptext SLIT("extern")
661 , parens (hsep (punctuate comma (zipWith (<+>) stubParamTypes stubArgs)))
668 , ptext c_nm <> parens (hsep (punctuate comma stubArgs))
669 , vcat (zipWith declVar stubParamTypes stubArgs)
671 , vcat (zipWith assignArgs param_names c_args)
672 , text "miniInterpret" <> parens (parens (text "StgFunPtr") <> h_stub_nm) <> semi
678 -- tedious hack to let us deal with caller-cleans-up-stack
679 -- discipline that the C calling convention uses.
681 | cc == cCallConv = ptext SLIT("void*") : cParamTypes
682 | otherwise = cParamTypes
684 | cc == cCallConv = ptext SLIT("_a0") : c_args
687 param_names = zipWith (\ i _ -> h_stub_nm <> text ('_':show i)) [1..] args
688 cParamTypes = map (text.showPrimRepToUser.typePrimRep) args
689 (cResType, cResDecl) =
691 Nothing -> (text "void", empty)
692 Just t -> (text (showPrimRepToUser (typePrimRep t)),
693 text "extern" <+> cResType <+> res_name <> semi)
696 | cc == cCallConv = empty
697 | otherwise = pprCallConv cc
700 vcat (zipWith mkExtern cParamTypes param_names) $$
702 text "extern void" <+> h_stub_nm <> text "();"
704 mkExtern ty nm = text "extern" <+> ty <+> nm <> semi
706 c_args = zipWith (\ _ n -> text ('a':show n)) args [0..]
708 assignArgs p_nm c_arg = p_nm <+> equals <+> c_arg <> semi
713 Just _ -> text "return" <+> res_name <> semi
717 Nothing -> (empty, empty)
718 Just t -> (h_stub_nm <> text "_res", ppr (typePrimRep t))
720 declVar :: SDoc -> SDoc -> SDoc
721 declVar ty var = ty <+> var <> semi
727 f :: Int -> Int -> Int -> IO Int
729 we'll emit the following stuff into the .hc file
741 STK_CHK(LivenessReg,0/*A*/,(SIZE_IN_WORDS(StgInt) +
742 SIZE_IN_WORDS(StgInt) +
743 SIZE_IN_WORDS(StgInt) + 1)/*B*/, 0, 0, 0/*prim*/, 0/*re-enter*/);
744 RetReg = (StgRetAddr) UNVEC(stopds_fDirectReturn,vtbl_stopds_f);
746 *SpB = (W_)__f_param_3;
748 *SpB = (W_)__f_param_2;
750 *SpB = (W_)__f_param_1;
753 *SpB = (W_) realWorldZh_closure;
755 Node = ds_f_helper_closure;
757 InfoPtr=(D_)(INFO_PTR(Node));
758 JMP_(ENTRY_CODE(InfoPtr));
762 STGFUN(stop_ds_fDirectReturn)
767 RESUME(miniInterpretEnd);
771 const W_ vtbl_stopds_f[] = {
772 (W_) stopds_fDirectReturn,
773 (W_) stopds_fDirectReturn,
774 (W_) stopds_fDirectReturn,
775 (W_) stopds_fDirectReturn,
776 (W_) stopds_fDirectReturn,
777 (W_) stopds_fDirectReturn,
778 (W_) stopds_fDirectReturn,
779 (W_) stopds_fDirectReturn
787 extern StgInt __f_param_1;
788 extern StgInt __f_param_2;
789 extern StgInt __f_param_3;
790 extern StgInt __f_res;
793 extern void miniInterpret(StgAddr);
804 miniInterpret((StgAddr)ds_f);