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) ->
120 Dynamic -> getUniqueDs `thenDs` \ u -> returnDs (Right u)
121 ExtName fs _ -> returnDs (Left fs)) `thenDs` \ label ->
123 the_ccall_op = CCallOp label False (not may_not_gc) cconv
124 (map coreExprType final_args)
127 mkPrimDs the_ccall_op (map VarArg final_args) `thenDs` \ the_prim_app ->
129 the_body = mkValLam [old_s]
130 (foldr ($) (res_wrapper the_prim_app) arg_wrappers)
132 newSysLocalDs (coreExprType the_body) `thenDs` \ ds ->
134 io_app = mkValApp (mkTyApp (Var ioDataCon) [result_ty]) [VarArg ds]
135 fo_rhs = mkTyLam tvs $
136 mkValLam (map (\ (Var x) -> x) args)
137 (mkCoLetAny (NonRec ds the_body) io_app)
139 returnDs (NonRec nm fo_rhs)
141 mkArgs :: Type -> DsM ([TyVar], [CoreExpr], Type)
143 case splitFunTys sans_foralls of
145 newSysLocalsDs arg_tys `thenDs` \ ds_args ->
146 returnDs (tvs, map Var ds_args, res_ty)
148 (tvs, sans_foralls) = splitForAllTys ty
154 -> Type -- Type of foreign export.
157 -> Bool -- True => invoke IO action that's hanging off
158 -- the first argument's stable pointer
159 -> DsM (CoreBinding, SDoc, SDoc, SDoc)
160 dsFExport i ty ext_name cconv isDyn =
161 newSysLocalDs realWorldStatePrimTy `thenDs` \ s1 ->
162 newSysLocalDs realWorldStatePrimTy `thenDs` \ s3 ->
163 newSysLocalDs helper_ty `thenDs` \ f_helper ->
164 newSysLocalsDs helper_arg_tys `thenDs` \ helper_args ->
165 newSysLocalDs res_ty `thenDs` \ v1 ->
166 unboxResult the_prim_result_ty res_ty s3 v1 `thenDs` \ (state_and_prim_ty, unpack_result) ->
167 zipWithDs boxArg fe_arg_tys helper_args `thenDs` \ stuff ->
169 newSysLocalDs realWorldStatePrimTy `thenDs` \ s11 ->
170 newSysLocalDs stbl_ptr_ty `thenDs` \ stbl_ptr ->
171 newSysLocalDs stbl_ptr_to_ty `thenDs` \ f ->
172 mkPrimDs DeRefStablePtrOp
173 [TyArg stbl_ptr_to_ty,
174 VarArg (Var stbl_ptr),
175 VarArg (Var s1)] `thenDs` \ the_deref_app ->
179 (AlgAlts [(stateAndPtrPrimDataCon, [s11, f], cont)]
182 returnDs (f, stbl_app, s11, stbl_ptr)
187 panic "stbl_ptr" -- should never be touched.
188 )) `thenDs` \ (i, getFun_wrapper, s2, stbl_ptr) ->
190 (boxed_args, arg_wrappers) = unzip stuff
193 | isDyn = stbl_ptr:helper_args
194 | otherwise = helper_args
197 | isDyn = stbl_ptr_ty:helper_arg_tys
198 | otherwise = helper_arg_tys
200 fe_app = mkGenApp (Var i) (map (TyArg . mkTyVarTy) tvs ++ map VarArg boxed_args)
203 mkValApp (Note (Coerce io_result_ty io_res) fe_app)
206 newFailLocalDs (coreExprType the_app) `thenDs` \ wild ->
207 getModuleAndGroupDs `thenDs` \ (mod,_) ->
208 getUniqueDs `thenDs` \ uniq ->
213 mkValLam wrapper_args $
215 foldr ($) (perform_and_unpack) arg_wrappers
218 Case the_app (AlgAlts [(ioOkDataCon, [s3, v1], unpack_result)]
219 (BindDefault wild err))
225 full_msg = "Exception caught: " ++ _UNPK_ (nameString (idName i))
226 msg = NoRepStr (_PK_ full_msg)
227 err = mkApp (Var eRROR_ID) [state_and_prim_ty] [LitArg msg]
229 f_helper_glob = (mkIdVisible mod uniq f_helper)
230 (hc_stub, h_stub, c_stub) = fexportEntry c_nm f_helper_glob wrapper_arg_tys the_prim_result_ty cconv
232 returnDs (NonRec f_helper_glob the_body, hc_stub, h_stub, c_stub)
234 (tvs,sans_foralls) = splitForAllTys ty
235 (fe_arg_tys', io_res) = splitFunTys sans_foralls
236 (ioOkDataCon, ioDataCon, res_ty) = getIoOkDataCon io_res
238 maybe_data_type = splitAlgTyConApp_maybe res_ty
239 Just (tycon, tycon_arg_tys, data_cons) = maybe_data_type
240 (the_data_con : other_data_cons) = data_cons
242 data_con_arg_tys = dataConArgTys the_data_con tycon_arg_tys
243 (prim_result_ty : other_args_tys) = data_con_arg_tys
245 ioDataConTy = idType ioDataCon
246 (io_tvs, ioDataConTy') = splitForAllTys ioDataConTy
247 ([arg_ty], _) = splitFunTys ioDataConTy'
248 io_result_ty = applyTy (mkForAllTys io_tvs arg_ty) res_ty
250 (_, stbl_ptr_ty') = splitForAllTys stbl_ptr_ty
251 (_, stbl_ptr_to_ty) = splitAppTy stbl_ptr_ty'
254 | isDyn = tail fe_arg_tys'
255 | otherwise = fe_arg_tys'
257 (stbl_ptr_ty, helper_arg_tys) =
258 case (map unboxTy fe_arg_tys') of
259 (x:xs) | isDyn -> (x,xs)
260 ls -> (error "stbl_ptr_ty", ls)
264 mkFunTys (arg_tys ++ [realWorldStatePrimTy])
268 | isDyn = stbl_ptr_ty : helper_arg_tys
269 | otherwise = helper_arg_tys
272 | null data_con_arg_tys = Nothing
273 | otherwise = Just prim_result_ty
276 | (null other_data_cons) &&
277 (null data_con_arg_tys) = realWorldStateTy
278 | otherwise = snd (getStatePairingConInfo (unboxTy res_ty))
281 "foreign export dynamic" lets you dress up Haskell IO actions
282 of some fixed type behind an externally callable interface (i.e.,
283 as a C function pointer). Useful for callbacks and stuff.
286 foreign export stdcall f :: (Addr -> Int -> IO Int) -> IO Addr
288 -- Haskell-visible constructor, which is generated from the
291 f :: (Addr -> Int -> IO Int) -> IO Addr
292 f cback = IO ( \ s1# ->
293 case makeStablePtr# cback s1# of { StateAndStablePtr# s2# sp# ->
294 case _ccall_ "mkAdjustor" sp# ``f_helper'' s2# of
295 StateAndAddr# s3# a# ->
305 foreign export "f_helper" f_helper :: StablePtr (Addr -> Int -> IO Int) -> Addr -> Int -> IO Int
306 -- `special' foreign export that invokes the closure pointed to by the
311 dsFExportDynamic :: Id
312 -> Type -- Type of foreign export.
315 -> DsM (CoreBinding, CoreBinding, SDoc, SDoc, SDoc)
316 dsFExportDynamic i ty ext_name cconv =
317 newSysLocalDs ty `thenDs` \ fe_id ->
319 -- hack: need to get at the name of the C stub we're about to generate.
320 fe_nm = toCName fe_id
321 fe_ext_name = ExtName (_PK_ fe_nm) Nothing
323 dsFExport i export_ty fe_ext_name cconv True `thenDs` \ (fe@(NonRec fe_helper fe_expr), hc_code, h_code, c_code) ->
324 newSysLocalDs realWorldStatePrimTy `thenDs` \ s1 ->
325 newSysLocalDs realWorldStatePrimTy `thenDs` \ s2 ->
326 newSysLocalDs realWorldStatePrimTy `thenDs` \ s3 ->
327 newSysLocalDs arg_ty `thenDs` \ cback_arg ->
328 newSysLocalDs arg_ty `thenDs` \ cback ->
329 newSysLocalDs (mkStablePtrPrimTy arg_ty) `thenDs` \ stbl ->
330 newSysLocalDs addrPrimTy `thenDs` \ addrPrim ->
331 newSysLocalDs addrTy `thenDs` \ addr ->
332 mkPrimDs MakeStablePtrOp [TyArg arg_ty,
334 VarArg (Var s1)] `thenDs` \ mkStablePtr_app ->
335 mkPrimDs Addr2IntOp [VarArg (Var addrPrim)] `thenDs` \ the_addr2Int_app ->
336 boxArg addrTy addrPrim `thenDs` \ (addr_result, addrPrim_wrapper) ->
338 (stateAndStablePtrPrimDataCon, _) = getStatePairingConInfo (mkStablePtrPrimTy arg_ty)
339 (stateAndAddrPrimDataCon, stateAndAddrPrimTy) = getStatePairingConInfo addrPrimTy
342 | cconv == stdCallConv = 1
345 ccall_args = [Var s2, Lit (mkMachInt cc),
347 Lit (MachLitLit (_PK_ fe_nm) AddrRep)]
349 label = Left SLIT("createAdjustor")
350 the_ccall_op = CCallOp label False False{-won't GC-} cCallConv
351 (map coreExprType ccall_args)
354 mkPrimDs the_ccall_op (map VarArg ccall_args) `thenDs` \ the_ccall_app ->
356 [TyArg res_ty, VarArg (Var s3), VarArg (Var addr_result)]
357 `thenDs` \ ioOkApp ->
358 newSysLocalDs intPrimTy `thenDs` \ default_val ->
360 the_mkStablePtr = \ cont ->
362 (AlgAlts [(stateAndStablePtrPrimDataCon, [s2, stbl], cont)]
365 the_ccall = \ cont ->
367 (AlgAlts [(stateAndAddrPrimDataCon, [s3, addrPrim], cont)]
369 the_addr2Int = \ cont ->
370 Case the_addr2Int_app
371 (PrimAlts [(mkMachInt 0, io_fail)]
372 (BindDefault default_val cont))
374 io_fail = mkApp (Var eRROR_ID) [coreExprType wrap_res] [LitArg msg]
375 full_msg = "Exception caught: " ++ _UNPK_ (nameString (idName i))
376 msg = NoRepStr (_PK_ full_msg)
378 wrap_res = addrPrim_wrapper ioOkApp
381 mkValLam [cback,s1] $
384 the_addr2Int wrap_res
387 newSysLocalDs (coreExprType the_body) `thenDs` \ ds ->
388 newSysLocalDs (mkFunTy realWorldStatePrimTy
389 (coreExprType ioOkApp)) `thenDs` \ ap ->
391 io_app = mkValApp (mkTyApp (Var ioDataCon) [res_ty]) [VarArg ap]
394 mkValLam [cback_arg] $
395 mkCoLetAny (NonRec ds the_body) $
396 mkCoLetAny (NonRec ap (mkValApp (mkTyApp (Var ds) (map mkTyVarTy tvs)) [VarArg cback_arg])) $
399 returnDs (NonRec i io_action, fe, hc_code, h_code, c_code)
401 (tvs,sans_foralls) = splitForAllTys ty
402 ([arg_ty], io_res) = splitFunTys sans_foralls
403 (ioOkDataCon, ioDataCon, res_ty) = getIoOkDataCon io_res
405 ioDataConTy = idType ioDataCon
406 (io_tvs, ioDataConTy') = splitForAllTys ioDataConTy
407 -- ([arg_ty], _) = splitFunTys ioDataConTy'
408 io_result_ty = applyTy (mkForAllTys io_tvs arg_ty) res_ty
410 export_ty = mkFunTy (mkTyConApp stablePtrTyCon [arg_ty]) arg_ty
412 toCName :: Id -> String
413 toCName i = showSDoc (pprCode CStyle (ppr (idName i)))
419 \subsection{Helper functions}
423 @boxArg@ boxes up an argument in preparation for calling
424 a function that maybe expects a boxed version of it, i.e.,
427 boxArg Addr a# ==> let ds_foo :: Addr ; ds_foo = A# a# in f ...ds_foo..
431 boxArg :: Type -- Expected type after possible boxing of arg.
432 -> Id -- The (unboxed) argument
433 -> DsM (Id, -- To pass as the actual, boxed argument
434 CoreExpr -> CoreExpr -- Wrapper to box the arg
436 boxArg box_ty prim_arg
437 | isUnpointedType box_ty = returnDs (prim_arg, \body -> body)
438 -- Data types with a single constructor,
439 -- which has a single, primitive-typed arg
441 = newSysLocalDs box_ty `thenDs` \ box_arg ->
443 , Let (NonRec box_arg (mkCon box_data_con tys_applied [VarArg prim_arg]))
446 maybe_boxed_prim_arg_ty = maybeBoxedPrimType box_ty
447 (Just (_,tys_applied,_)) = splitAlgTyConApp_maybe box_ty
448 (Just (box_data_con, _)) = maybe_boxed_prim_arg_ty
451 @foreign export@ed functions may return a value back to the outside world.
452 @unboxResult@ takes care of converting from the (boxed) value that the
453 exported action returns to the (unboxed) value that is returned across
457 unboxResult :: Maybe Type -- the (unboxed) type we want to return (along with the state token)
458 -- Nothing => no result, just the state token.
459 -> Type -- the (boxed) type we have in our hand.
460 -> Id -- the state token
462 -> DsM (Type, -- type of returned expression.
463 CoreExpr) -- expr that unboxes result and returns state+unboxed result.
465 unboxResult mb_res_uboxed_ty res_ty new_s v_boxed
466 | not (maybeToBool mb_res_uboxed_ty)
467 = -- no result, just return state token
468 mkConDs stateDataCon [ TyArg realWorldTy
469 , VarArg (Var new_s)] `thenDs` \ the_st ->
470 returnDs (realWorldStateTy, the_st)
473 -- oops! can't see the data constructors
474 = can'tSeeDataConsPanic "result" res_ty
476 | (maybeToBool maybe_data_type) && -- Data type
477 (null other_data_cons) && -- - with one constructor,
478 isUnpointedType res_uboxed_ty -- - and of primitive type.
479 -- (Glasgow extension)
481 newSysLocalDs res_uboxed_ty `thenDs` \ v_unboxed ->
482 mkConDs state_and_prim_datacon
483 ((TyArg realWorldTy):map (TyArg ) tycon_arg_tys ++
485 , VarArg (Var v_unboxed)]) `thenDs` \ the_result ->
487 the_alt = (the_data_con, [v_unboxed], the_result)
489 returnDs (state_and_prim_ty,
490 Case (Var v_boxed) (AlgAlts [the_alt] NoDefault))
493 = pprPanic "unboxResult: " (ppr res_ty)
495 (Just res_uboxed_ty) = mb_res_uboxed_ty
497 maybe_data_type = splitAlgTyConApp_maybe res_ty
498 Just (tycon, tycon_arg_tys, data_cons) = maybe_data_type
499 (the_data_con : other_data_cons) = data_cons
501 (state_and_prim_datacon, state_and_prim_ty) = getStatePairingConInfo res_uboxed_ty
505 Returned the unboxed type of a (primitive) type:
508 unboxTy :: Type -> Type
510 | isUnpointedType ty || (ty == unitTy) = ty
512 ASSERT( isFFIArgumentTy ty ) -- legal arg types subsume result types.
513 case splitTyConApp_maybe ty of
515 case (tyConDataCons tyc) of
516 [dc] -> case (dataConArgTys dc ts) of
518 -- HACK: for the array types, the prim type is
519 -- the second tycon arg.
521 _ -> pprPanic "unboxTy: " (ppr ty)
522 _ -> pprPanic "unboxTy: " (ppr ty)
523 _ -> pprPanic "unboxTy: " (ppr ty)
529 \subsection{Generating @foreign export@ stubs}
533 [Severe hack to get @foreign export@ off the ground:]
535 For each @foreign export@ function, a C stub together with a @.hc@ stub
536 is generated. The C stub enters the .hc stub, setting up the passing of
537 parameters from C land to STG land through the use of global variables
538 (don't worry, this just a temporary solution!). Ditto for the result.
541 The generation of .hc code will go once the transition is
542 made over to the new rts. Hence the hack, instead of extending
543 AbsCSyn to cope with the .hc code generated.
547 fexportEntry :: FAST_STRING -> Id -> [Type] -> Maybe Type -> CallConv -> (SDoc, SDoc, SDoc)
548 fexportEntry c_nm helper args res cc =
549 ( paramArea $$ stopTemplate $$ startTemplate $$ vtblTemplate, h_code, c_code )
551 (h_code, c_code) = mkCStub c_nm h_stub_nm args res cc
554 vcat (zipWith declVar ( res_ty : param_tys ) ( res_name : param_names ) )
556 -- name of the (Haskell) helper function generated by the desugarer.
558 h_stub_nm = text foreign_export_prefix <> h_nm
559 closure = h_nm <> text "_closure"
561 param_names = zipWith (\ i _ -> h_stub_nm <> text ('_':show i)) [1..] args
562 param_tys = map (ppr.typePrimRep) args
566 Nothing -> (empty, empty)
567 Just t -> (h_stub_nm <> text "_res", ppr (typePrimRep t))
571 [ text "extern realWorldZh_closure;"
572 , ptext SLIT("STGFUN") <> parens (h_stub_nm)
574 , ptext SLIT("FUNBEGIN;")
575 , text "RestoreAllStgRegs();"
576 , stackCheck param_names
580 , vcat (map pushArg (reverse param_names))
581 , text "Node=" <> closure <> semi
582 , text "ENT_VIA_NODE();" -- ticky count
583 , text "InfoPtr=(D_)(INFO_PTR(Node));"
584 , text "JMP_(ENTRY_CODE(InfoPtr));"
591 [ ptext SLIT("STGFUN") <> parens (text "stop" <> h_stub_nm <> text "DirectReturn")
593 , ptext SLIT("FUNBEGIN;")
596 , text "#if defined(__STG_GCC_REGS__)"
597 , text "SaveAllStgRegs();"
599 , text "SAVE_Hp = Hp;"
600 , text "SAVE_HpLim = HpLim;"
602 , text "JMP_(miniInterpretEnd);"
609 [ text "const W_ vtbl_" <> h_stub_nm <> text "[] = {"
610 , vcat (punctuate comma (replicate 8 dir_ret))
614 dir_ret = text "(W_)stop" <> h_stub_nm <> text "DirectReturn"
619 Just _ -> res_name <> equals <> text "R3.i;" -- wrong
622 text "SpB -= BREL(1);" $$
623 text "*SpB = (W_)RetReg;"
626 text "RetReg=(StgRetAddr)*SpB;" $$
627 text "SpB += BREL(1);"
630 text "RetReg=(StgRetAddr)UNVEC(stop" <> h_stub_nm <>
631 text "DirectReturn,vtbl_" <> h_stub_nm <> text ");"
634 text "SpB -= BREL(1);" $$
635 text "*SpB = (W_)realWorldZh_closure;"
639 text "SpB -= BREL(1);" $$
640 text "*SpB = (W_)" <> nm <> semi
643 text "STK_CHK(LivenessReg,0," <> sz <> text ",0,0,0,0);"
646 hsep $ punctuate (text " + ") (text "1":(map sizer args))
648 sizer x = text "BYTES_TO_STGWORDS" <> parens (text "sizeof" <> parens x)
650 foreign_export_prefix :: String
651 foreign_export_prefix = "__fexp_"
653 mkCStub :: FAST_STRING -> SDoc -> [Type] -> Maybe Type -> CallConv -> (SDoc, SDoc)
654 mkCStub c_nm h_stub_nm args res cc =
655 ( hsep [ ptext SLIT("extern")
659 , parens (hsep (punctuate comma (zipWith (<+>) stubParamTypes stubArgs)))
666 , ptext c_nm <> parens (hsep (punctuate comma stubArgs))
667 , vcat (zipWith declVar stubParamTypes stubArgs)
669 , vcat (zipWith assignArgs param_names c_args)
670 , text "miniInterpret" <> parens (parens (text "StgFunPtr") <> h_stub_nm) <> semi
676 -- tedious hack to let us deal with caller-cleans-up-stack
677 -- discipline that the C calling convention uses.
679 | cc == cCallConv = ptext SLIT("void*") : cParamTypes
680 | otherwise = cParamTypes
682 | cc == cCallConv = ptext SLIT("_a0") : c_args
685 param_names = zipWith (\ i _ -> h_stub_nm <> text ('_':show i)) [1..] args
686 cParamTypes = map (text.showPrimRepToUser.typePrimRep) args
687 (cResType, cResDecl) =
689 Nothing -> (text "void", empty)
690 Just t -> (text (showPrimRepToUser (typePrimRep t)),
691 text "extern" <+> cResType <+> res_name <> semi)
694 | cc == cCallConv = empty
695 | otherwise = pprCallConv cc
698 vcat (zipWith mkExtern cParamTypes param_names) $$
700 text "extern void" <+> h_stub_nm <> text "();"
702 mkExtern ty nm = text "extern" <+> ty <+> nm <> semi
704 c_args = zipWith (\ _ n -> text ('a':show n)) args [0..]
706 assignArgs p_nm c_arg = p_nm <+> equals <+> c_arg <> semi
711 Just _ -> text "return" <+> res_name <> semi
715 Nothing -> (empty, empty)
716 Just t -> (h_stub_nm <> text "_res", ppr (typePrimRep t))
718 declVar :: SDoc -> SDoc -> SDoc
719 declVar ty var = ty <+> var <> semi
725 f :: Int -> Int -> Int -> IO Int
727 we'll emit the following stuff into the .hc file
739 STK_CHK(LivenessReg,0/*A*/,(SIZE_IN_WORDS(StgInt) +
740 SIZE_IN_WORDS(StgInt) +
741 SIZE_IN_WORDS(StgInt) + 1)/*B*/, 0, 0, 0/*prim*/, 0/*re-enter*/);
742 RetReg = (StgRetAddr) UNVEC(stopds_fDirectReturn,vtbl_stopds_f);
744 *SpB = (W_)__f_param_3;
746 *SpB = (W_)__f_param_2;
748 *SpB = (W_)__f_param_1;
751 *SpB = (W_) realWorldZh_closure;
753 Node = ds_f_helper_closure;
755 InfoPtr=(D_)(INFO_PTR(Node));
756 JMP_(ENTRY_CODE(InfoPtr));
760 STGFUN(stop_ds_fDirectReturn)
765 RESUME(miniInterpretEnd);
769 const W_ vtbl_stopds_f[] = {
770 (W_) stopds_fDirectReturn,
771 (W_) stopds_fDirectReturn,
772 (W_) stopds_fDirectReturn,
773 (W_) stopds_fDirectReturn,
774 (W_) stopds_fDirectReturn,
775 (W_) stopds_fDirectReturn,
776 (W_) stopds_fDirectReturn,
777 (W_) stopds_fDirectReturn
785 extern StgInt __f_param_1;
786 extern StgInt __f_param_2;
787 extern StgInt __f_param_3;
788 extern StgInt __f_res;
791 extern void miniInterpret(StgAddr);
802 miniInterpret((StgAddr)ds_f);