2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-2000
4 \section[StgInterp]{Translates STG syntax to interpretable form, and run it}
11 filterRdrNameEnv, -- :: [ModuleName] -> FiniteMap RdrName a
12 -- -> FiniteMap RdrName a
14 linkIModules, -- :: ItblEnv -> ClosureEnv
15 -- -> [([UnlinkedIBind], ItblEnv)]
16 -- -> IO ([LinkedIBind], ItblEnv, ClosureEnv)
18 iExprToHValue, -- :: ItblEnv -> ClosureEnv
19 -- -> UnlinkedIExpr -> HValue
21 stgBindsToInterpSyn,-- :: [StgBinding]
22 -- -> [TyCon] -> [Class]
23 -- -> IO ([UnlinkedIBind], ItblEnv)
25 stgExprToInterpSyn, -- :: StgExpr
26 -- -> IO UnlinkedIExpr
28 interp -- :: LinkedIExpr -> HValue
31 {- -----------------------------------------------------------------------------
34 - link should be in the IO monad, so it can modify the symtabs as it
37 - need a way to remove the bindings for a module from the symtabs.
38 maybe the symtabs should be indexed by module first.
40 - change the representation to something less verbose (?).
42 - converting string literals to Addr# is horrible and introduces
43 a memory leak. See if something can be done about this.
45 - lots of assumptions about word size vs. double size etc.
47 ----------------------------------------------------------------------------- -}
49 #include "HsVersions.h"
52 import Id ( Id, idPrimRep )
55 import PrimOp ( PrimOp(..) )
56 import PrimRep ( PrimRep(..) )
57 import Literal ( Literal(..) )
58 import Type ( Type, typePrimRep, deNoteType, repType, funResultTy )
59 import DataCon ( DataCon, dataConTag, dataConRepArgTys )
60 import ClosureInfo ( mkVirtHeapOffsets )
61 import Module ( ModuleName )
62 import Name ( toRdrName )
66 import {-# SOURCE #-} MCI_make_constr
68 import IOExts ( unsafePerformIO, unsafeInterleaveIO, fixIO ) -- ToDo: remove
69 import PrelGHC --( unsafeCoerce#, dataToTag#,
70 -- indexPtrOffClosure#, indexWordOffClosure# )
71 import PrelAddr ( Addr(..) )
72 import PrelFloat ( Float(..), Double(..) )
75 import GlaExts ( Int(..) )
76 import Module ( moduleNameFS )
78 import TyCon ( TyCon, isDataTyCon, tyConDataCons, tyConFamilySize )
79 import Class ( Class, classTyCon )
83 import RdrName ( RdrName, rdrNameModule, rdrNameOcc, isUnqual )
85 import Panic ( panic )
86 import OccName ( occNameString )
87 import ErrUtils ( showPass, dumpIfSet_dyn )
88 import CmdLineOpts ( DynFlags, DynFlag(..) )
94 -- ---------------------------------------------------------------------------
95 -- Environments needed by the linker
96 -- ---------------------------------------------------------------------------
98 type ItblEnv = FiniteMap RdrName (Ptr StgInfoTable)
99 type ClosureEnv = FiniteMap RdrName HValue
100 emptyClosureEnv = emptyFM
102 -- remove all entries for a given set of modules from the environment
103 filterRdrNameEnv :: [ModuleName] -> FiniteMap RdrName a -> FiniteMap RdrName a
104 filterRdrNameEnv mods env
105 = filterFM (\n _ -> rdrNameModule n `notElem` mods) env
107 -- ---------------------------------------------------------------------------
108 -- Turn an UnlinkedIExpr into a value we can run, for the interpreter
109 -- ---------------------------------------------------------------------------
111 iExprToHValue :: ItblEnv -> ClosureEnv -> UnlinkedIExpr -> IO HValue
112 iExprToHValue ie ce expr
113 = do linked_expr <- linkIExpr ie ce expr
114 return (interp linked_expr)
116 -- ---------------------------------------------------------------------------
117 -- Convert STG to an unlinked interpretable
118 -- ---------------------------------------------------------------------------
120 -- visible from outside
121 stgBindsToInterpSyn :: DynFlags
123 -> [TyCon] -> [Class]
124 -> IO ([UnlinkedIBind], ItblEnv)
125 stgBindsToInterpSyn dflags binds local_tycons local_classes
126 = do showPass dflags "StgToInterp"
127 let ibinds = concatMap (translateBind emptyUniqSet) binds
128 let tycs = local_tycons ++ map classTyCon local_classes
129 dumpIfSet_dyn dflags Opt_D_dump_InterpSyn
130 "Convert To InterpSyn" (vcat (map pprIBind ibinds))
131 itblenv <- mkITbls tycs
132 return (ibinds, itblenv)
134 stgExprToInterpSyn :: DynFlags
137 stgExprToInterpSyn dflags expr
138 = do showPass dflags "StgToInterp"
139 let iexpr = stg2expr emptyUniqSet expr
140 dumpIfSet_dyn dflags Opt_D_dump_InterpSyn
141 "Convert To InterpSyn" (pprIExpr iexpr)
144 translateBind :: UniqSet Id -> StgBinding -> [UnlinkedIBind]
145 translateBind ie (StgNonRec v e) = [IBind v (rhs2expr ie e)]
146 translateBind ie (StgRec vs_n_es) = [IBind v (rhs2expr ie' e) | (v,e) <- vs_n_es]
147 where ie' = addListToUniqSet ie (map fst vs_n_es)
149 isRec (StgNonRec _ _) = False
150 isRec (StgRec _) = True
152 rhs2expr :: UniqSet Id -> StgRhs -> UnlinkedIExpr
153 rhs2expr ie (StgRhsClosure ccs binfo srt fvs uflag args rhs)
156 rhsExpr = stg2expr (addListToUniqSet ie args) rhs
157 rhsRep = repOfStgExpr rhs
158 mkLambdas [] = rhsExpr
159 mkLambdas [v] = mkLam (repOfId v) rhsRep v rhsExpr
160 mkLambdas (v:vs) = mkLam (repOfId v) RepP v (mkLambdas vs)
161 rhs2expr ie (StgRhsCon ccs dcon args)
162 = conapp2expr ie dcon args
164 conapp2expr :: UniqSet Id -> DataCon -> [StgArg] -> UnlinkedIExpr
165 conapp2expr ie dcon args
166 = mkConApp con_rdrname reps exprs
168 con_rdrname = toRdrName dcon
169 exprs = map (arg2expr ie) inHeapOrder
170 reps = map repOfArg inHeapOrder
171 inHeapOrder = toHeapOrder args
173 toHeapOrder :: [StgArg] -> [StgArg]
175 = let (_, _, rearranged_w_offsets) = mkVirtHeapOffsets getArgPrimRep args
176 (rearranged, offsets) = unzip rearranged_w_offsets
180 foreign label "PrelBase_Izh_con_info" prelbase_Izh_con_info :: Addr
182 -- Handle most common cases specially; do the rest with a generic
183 -- mechanism (deferred till later :)
184 mkConApp :: RdrName -> [Rep] -> [UnlinkedIExpr] -> UnlinkedIExpr
185 mkConApp nm [] [] = ConApp nm
186 mkConApp nm [RepI] [a1] = ConAppI nm a1
187 mkConApp nm [RepP] [a1] = ConAppP nm a1
188 mkConApp nm [RepP,RepP] [a1,a2] = ConAppPP nm a1 a2
189 mkConApp nm reps args = ConAppGen nm args
191 mkLam RepP RepP = LamPP
192 mkLam RepI RepP = LamIP
193 mkLam RepP RepI = LamPI
194 mkLam RepI RepI = LamII
195 mkLam repa repr = pprPanic "StgInterp.mkLam" (ppr repa <+> ppr repr)
197 mkApp RepP RepP = AppPP
198 mkApp RepI RepP = AppIP
199 mkApp RepP RepI = AppPI
200 mkApp RepI RepI = AppII
201 mkApp repa repr = pprPanic "StgInterp.mkApp" (ppr repa <+> ppr repr)
204 repOfId = primRep2Rep . idPrimRep
209 -- genuine lifted types
212 -- all these are unboxed, fit into a word, and we assume they
213 -- all have the same call/return convention.
221 -- these are pretty dodgy: really pointers, but
222 -- we can't let the compiler build thunks with these reps.
223 ForeignObjRep -> RepP
224 StableNameRep -> RepP
232 other -> pprPanic "primRep2Rep" (ppr other)
234 repOfStgExpr :: StgExpr -> Rep
239 StgCase scrut live liveR bndr srt alts
240 -> case altRhss alts of
241 (a:_) -> repOfStgExpr a
242 [] -> panic "repOfStgExpr: no alts"
246 -> repOfApp ((deNoteType.repType.idType) var) (length args)
248 StgPrimApp op args res_ty
249 -> (primRep2Rep.typePrimRep) res_ty
251 StgLet binds body -> repOfStgExpr body
252 StgLetNoEscape live liveR binds body -> repOfStgExpr body
254 StgConApp con args -> RepP -- by definition
257 -> pprPanic "repOfStgExpr" (ppr other)
259 altRhss (StgAlgAlts tycon alts def)
260 = [rhs | (dcon,bndrs,uses,rhs) <- alts] ++ defRhs def
261 altRhss (StgPrimAlts tycon alts def)
262 = [rhs | (lit,rhs) <- alts] ++ defRhs def
265 defRhs (StgBindDefault rhs)
268 -- returns the Rep of the result of applying ty to n args.
269 repOfApp :: Type -> Int -> Rep
270 repOfApp ty 0 = (primRep2Rep.typePrimRep) ty
271 repOfApp ty n = repOfApp (funResultTy ty) (n-1)
283 MachStr _ -> RepI -- because it's a ptr outside the heap
284 other -> pprPanic "repOfLit" (ppr lit)
286 lit2expr :: Literal -> UnlinkedIExpr
289 MachInt i -> case fromIntegral i of I# i -> LitI i
290 MachWord i -> case fromIntegral i of I# i -> LitI i
291 MachAddr i -> case fromIntegral i of I# i -> LitI i
292 MachChar i -> case fromIntegral i of I# i -> LitI i
293 MachFloat f -> case fromRational f of F# f -> LitF f
294 MachDouble f -> case fromRational f of D# f -> LitD f
297 CharStr s i -> LitI (addr2Int# s)
300 -- sigh, a string in the heap is no good to us. We need a
301 -- static C pointer, since the type of a string literal is
302 -- Addr#. So, copy the string into C land and introduce a
303 -- memory leak at the same time.
305 -- CAREFUL! Chars are 32 bits in ghc 4.09+
306 case unsafePerformIO (do a@(Ptr addr) <- mallocBytes (n+1)
307 strncpy a ba (fromIntegral n)
308 writeCharOffAddr addr n '\0'
310 of A# a -> LitI (addr2Int# a)
312 _ -> error "StgInterp.lit2expr: unhandled string constant type"
314 other -> pprPanic "lit2expr" (ppr lit)
316 stg2expr :: UniqSet Id -> StgExpr -> UnlinkedIExpr
320 -> mkVar ie (repOfId var) var
323 -> mkAppChain ie (repOfStgExpr stgexpr) (mkVar ie (repOfId var) var) args
327 StgCase scrut live liveR bndr srt (StgPrimAlts ty alts def)
328 | repOfStgExpr scrut /= RepP
329 -> mkCasePrim (repOfStgExpr stgexpr)
330 bndr (stg2expr ie scrut)
331 (map (doPrimAlt ie') alts)
334 pprPanic "stg2expr(StgCase,prim)" (ppr (repOfStgExpr scrut) $$ (case scrut of (StgApp v _) -> ppr v <+> ppr (idType v) <+> ppr (idPrimRep v)) $$ ppr stgexpr)
335 where ie' = addOneToUniqSet ie bndr
337 StgCase scrut live liveR bndr srt (StgAlgAlts tycon alts def)
338 | repOfStgExpr scrut == RepP
339 -> mkCaseAlg (repOfStgExpr stgexpr)
340 bndr (stg2expr ie scrut)
341 (map (doAlgAlt ie') alts)
343 where ie' = addOneToUniqSet ie bndr
346 StgPrimApp op args res_ty
347 -> mkPrimOp (repOfStgExpr stgexpr) op (map (arg2expr ie) args)
350 -> conapp2expr ie dcon args
352 StgLet binds@(StgNonRec v e) body
353 -> mkNonRec (repOfStgExpr stgexpr)
354 (head (translateBind ie binds))
355 (stg2expr (addOneToUniqSet ie v) body)
357 StgLet binds@(StgRec bs) body
358 -> mkRec (repOfStgExpr stgexpr)
359 (translateBind ie binds)
360 (stg2expr (addListToUniqSet ie (map fst bs)) body)
362 -- treat let-no-escape just like let.
363 StgLetNoEscape _ _ binds body
364 -> stg2expr ie (StgLet binds body)
367 -> pprPanic "stg2expr" (ppr stgexpr)
369 doPrimAlt ie (lit,rhs)
370 = AltPrim (lit2expr lit) (stg2expr ie rhs)
371 doAlgAlt ie (dcon,vars,uses,rhs)
372 = AltAlg (dataConTag dcon - 1)
373 (map id2VaaRep (toHeapOrder vars))
374 (stg2expr (addListToUniqSet ie vars) rhs)
377 = let (_,_,rearranged_w_offsets) = mkVirtHeapOffsets idPrimRep vars
378 (rearranged,offsets) = unzip rearranged_w_offsets
382 def2expr ie StgNoDefault = Nothing
383 def2expr ie (StgBindDefault rhs) = Just (stg2expr ie rhs)
385 mkAppChain ie result_rep so_far []
387 mkAppChain ie result_rep so_far [a]
388 = mkApp (repOfArg a) result_rep so_far (arg2expr ie a)
389 mkAppChain ie result_rep so_far (a:as)
390 = mkAppChain ie result_rep (mkApp (repOfArg a) RepP so_far (arg2expr ie a)) as
392 mkCasePrim RepI = CasePrimI
393 mkCasePrim RepP = CasePrimP
395 mkCaseAlg RepI = CaseAlgI
396 mkCaseAlg RepP = CaseAlgP
398 -- any var that isn't in scope is turned into a Native
400 | var `elementOfUniqSet` ie =
406 | otherwise = Native (toRdrName var)
410 mkNonRec RepI = NonRecI
411 mkNonRec RepP = NonRecP
413 mkPrimOp RepI = PrimOpI
414 mkPrimOp RepP = PrimOpP
416 arg2expr :: UniqSet Id -> StgArg -> UnlinkedIExpr
417 arg2expr ie (StgVarArg v) = mkVar ie (repOfId v) v
418 arg2expr ie (StgLitArg lit) = lit2expr lit
419 arg2expr ie (StgTypeArg ty) = pprPanic "arg2expr" (ppr ty)
421 repOfArg :: StgArg -> Rep
422 repOfArg (StgVarArg v) = repOfId v
423 repOfArg (StgLitArg lit) = repOfLit lit
424 repOfArg (StgTypeArg ty) = pprPanic "repOfArg" (ppr ty)
426 id2VaaRep var = (var, repOfId var)
429 -- ---------------------------------------------------------------------------
430 -- Link interpretables into something we can run
431 -- ---------------------------------------------------------------------------
433 linkIModules :: ItblEnv -- incoming global itbl env; returned updated
434 -> ClosureEnv -- incoming global closure env; returned updated
435 -> [([UnlinkedIBind], ItblEnv)]
436 -> IO ([LinkedIBind], ItblEnv, ClosureEnv)
437 linkIModules gie gce mods = do
438 let (bindss, ies) = unzip mods
439 binds = concat bindss
440 top_level_binders = map (toRdrName.binder) binds
441 final_gie = foldr plusFM gie ies
443 (new_binds, new_gce) <-
444 fixIO (\ ~(new_binds, new_gce) -> do
446 new_binds <- linkIBinds final_gie new_gce binds
448 let new_rhss = map (\b -> evalP (bindee b) emptyUFM) new_binds
449 let new_gce = addListToFM gce (zip top_level_binders new_rhss)
451 return (new_binds, new_gce))
453 return (new_binds, final_gie, new_gce)
456 -- We're supposed to augment the environments with the values of any
457 -- external functions/info tables we need as we go along, but that's a
458 -- lot of hassle so for now I'll look up external things as they crop
459 -- up and not cache them in the source symbol tables. The interpreted
460 -- code will still be referenced in the source symbol tables.
462 linkIBinds :: ItblEnv -> ClosureEnv -> [UnlinkedIBind] -> IO [LinkedIBind]
463 linkIBinds ie ce binds = mapM (linkIBind ie ce) binds
465 linkIBind ie ce (IBind bndr expr)
466 = do expr <- linkIExpr ie ce expr
467 return (IBind bndr expr)
469 linkIExpr :: ItblEnv -> ClosureEnv -> UnlinkedIExpr -> IO LinkedIExpr
470 linkIExpr ie ce expr = case expr of
472 CaseAlgP bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgP
473 CaseAlgI bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgI
474 CaseAlgF bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgF
475 CaseAlgD bndr expr alts dflt -> linkAlgCase ie ce bndr expr alts dflt CaseAlgD
477 CasePrimP bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimP
478 CasePrimI bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimI
479 CasePrimF bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimF
480 CasePrimD bndr expr alts dflt -> linkPrimCase ie ce bndr expr alts dflt CasePrimD
482 ConApp con -> lookupNullaryCon ie con
484 ConAppI con arg0 -> do
485 con' <- lookupCon ie con
486 arg' <- linkIExpr ie ce arg0
487 return (ConAppI con' arg')
489 ConAppP con arg0 -> do
490 con' <- lookupCon ie con
491 arg' <- linkIExpr ie ce arg0
492 return (ConAppP con' arg')
494 ConAppPP con arg0 arg1 -> do
495 con' <- lookupCon ie con
496 arg0' <- linkIExpr ie ce arg0
497 arg1' <- linkIExpr ie ce arg1
498 return (ConAppPP con' arg0' arg1')
500 ConAppGen con args -> do
501 con <- lookupCon ie con
502 args <- mapM (linkIExpr ie ce) args
503 return (ConAppGen con args)
505 PrimOpI op args -> linkPrimOp ie ce PrimOpI op args
506 PrimOpP op args -> linkPrimOp ie ce PrimOpP op args
508 NonRecP bind expr -> linkNonRec ie ce NonRecP bind expr
509 NonRecI bind expr -> linkNonRec ie ce NonRecI bind expr
510 NonRecF bind expr -> linkNonRec ie ce NonRecF bind expr
511 NonRecD bind expr -> linkNonRec ie ce NonRecD bind expr
513 RecP binds expr -> linkRec ie ce RecP binds expr
514 RecI binds expr -> linkRec ie ce RecI binds expr
515 RecF binds expr -> linkRec ie ce RecF binds expr
516 RecD binds expr -> linkRec ie ce RecD binds expr
518 LitI i -> return (LitI i)
519 LitF i -> return (LitF i)
520 LitD i -> return (LitD i)
522 Native var -> lookupNative ce var
524 VarP v -> lookupVar ce VarP v
525 VarI v -> lookupVar ce VarI v
526 VarF v -> lookupVar ce VarF v
527 VarD v -> lookupVar ce VarD v
529 LamPP bndr expr -> linkLam ie ce LamPP bndr expr
530 LamPI bndr expr -> linkLam ie ce LamPI bndr expr
531 LamPF bndr expr -> linkLam ie ce LamPF bndr expr
532 LamPD bndr expr -> linkLam ie ce LamPD bndr expr
533 LamIP bndr expr -> linkLam ie ce LamIP bndr expr
534 LamII bndr expr -> linkLam ie ce LamII bndr expr
535 LamIF bndr expr -> linkLam ie ce LamIF bndr expr
536 LamID bndr expr -> linkLam ie ce LamID bndr expr
537 LamFP bndr expr -> linkLam ie ce LamFP bndr expr
538 LamFI bndr expr -> linkLam ie ce LamFI bndr expr
539 LamFF bndr expr -> linkLam ie ce LamFF bndr expr
540 LamFD bndr expr -> linkLam ie ce LamFD bndr expr
541 LamDP bndr expr -> linkLam ie ce LamDP bndr expr
542 LamDI bndr expr -> linkLam ie ce LamDI bndr expr
543 LamDF bndr expr -> linkLam ie ce LamDF bndr expr
544 LamDD bndr expr -> linkLam ie ce LamDD bndr expr
546 AppPP fun arg -> linkApp ie ce AppPP fun arg
547 AppPI fun arg -> linkApp ie ce AppPI fun arg
548 AppPF fun arg -> linkApp ie ce AppPF fun arg
549 AppPD fun arg -> linkApp ie ce AppPD fun arg
550 AppIP fun arg -> linkApp ie ce AppIP fun arg
551 AppII fun arg -> linkApp ie ce AppII fun arg
552 AppIF fun arg -> linkApp ie ce AppIF fun arg
553 AppID fun arg -> linkApp ie ce AppID fun arg
554 AppFP fun arg -> linkApp ie ce AppFP fun arg
555 AppFI fun arg -> linkApp ie ce AppFI fun arg
556 AppFF fun arg -> linkApp ie ce AppFF fun arg
557 AppFD fun arg -> linkApp ie ce AppFD fun arg
558 AppDP fun arg -> linkApp ie ce AppDP fun arg
559 AppDI fun arg -> linkApp ie ce AppDI fun arg
560 AppDF fun arg -> linkApp ie ce AppDF fun arg
561 AppDD fun arg -> linkApp ie ce AppDD fun arg
563 linkAlgCase ie ce bndr expr alts dflt con
564 = do expr <- linkIExpr ie ce expr
565 alts <- mapM (linkAlgAlt ie ce) alts
566 dflt <- linkDefault ie ce dflt
567 return (con bndr expr alts dflt)
569 linkPrimCase ie ce bndr expr alts dflt con
570 = do expr <- linkIExpr ie ce expr
571 alts <- mapM (linkPrimAlt ie ce) alts
572 dflt <- linkDefault ie ce dflt
573 return (con bndr expr alts dflt)
575 linkAlgAlt ie ce (AltAlg tag args rhs)
576 = do rhs <- linkIExpr ie ce rhs
577 return (AltAlg tag args rhs)
579 linkPrimAlt ie ce (AltPrim lit rhs)
580 = do rhs <- linkIExpr ie ce rhs
581 lit <- linkIExpr ie ce lit
582 return (AltPrim lit rhs)
584 linkDefault ie ce Nothing = return Nothing
585 linkDefault ie ce (Just expr)
586 = do expr <- linkIExpr ie ce expr
589 linkNonRec ie ce con bind expr
590 = do expr <- linkIExpr ie ce expr
591 bind <- linkIBind ie ce bind
592 return (con bind expr)
594 linkRec ie ce con binds expr
595 = do expr <- linkIExpr ie ce expr
596 binds <- linkIBinds ie ce binds
597 return (con binds expr)
599 linkLam ie ce con bndr expr
600 = do expr <- linkIExpr ie ce expr
601 return (con bndr expr)
603 linkApp ie ce con fun arg
604 = do fun <- linkIExpr ie ce fun
605 arg <- linkIExpr ie ce arg
608 linkPrimOp ie ce con op args
609 = do args <- mapM (linkIExpr ie ce) args
613 case lookupFM ie con of
614 Just (Ptr addr) -> return addr
616 -- try looking up in the object files.
617 m <- lookupSymbol (rdrNameToCLabel con "con_info")
619 Just addr -> return addr
620 Nothing -> pprPanic "linkIExpr" (ppr con)
622 -- nullary constructors don't have normal _con_info tables.
623 lookupNullaryCon ie con =
624 case lookupFM ie con of
625 Just (Ptr addr) -> return (ConApp addr)
627 -- try looking up in the object files.
628 m <- lookupSymbol (rdrNameToCLabel con "closure")
630 Just (A# addr) -> return (Native (unsafeCoerce# addr))
631 Nothing -> pprPanic "lookupNullaryCon" (ppr con)
634 lookupNative ce var =
635 unsafeInterleaveIO (do
636 case lookupFM ce var of
637 Just e -> return (Native e)
639 -- try looking up in the object files.
640 let lbl = (rdrNameToCLabel var "closure")
641 m <- lookupSymbol lbl
643 Just (A# addr) -> return (Native (unsafeCoerce# addr))
644 Nothing -> pprPanic "linkIExpr" (ppr var)
647 -- some VarI/VarP refer to top-level interpreted functions; we change
648 -- them into Natives here.
650 unsafeInterleaveIO (do
651 case lookupFM ce (toRdrName v) of
652 Nothing -> return (f v)
653 Just e -> return (Native e)
656 -- HACK!!! ToDo: cleaner
657 rdrNameToCLabel :: RdrName -> String{-suffix-} -> String
658 rdrNameToCLabel rn suffix
659 | isUnqual rn = pprPanic "rdrNameToCLabel" (ppr rn)
661 _UNPK_(moduleNameFS (rdrNameModule rn))
662 ++ '_':occNameString(rdrNameOcc rn) ++ '_':suffix
664 -- ---------------------------------------------------------------------------
665 -- The interpreter proper
666 -- ---------------------------------------------------------------------------
668 -- The dynamic environment contains everything boxed.
669 -- eval* functions which look up values in it will know the
670 -- representation of the thing they are looking up, so they
671 -- can cast/unbox it as necessary.
673 -- ---------------------------------------------------------------------------
674 -- Evaluator for things of boxed (pointer) representation
675 -- ---------------------------------------------------------------------------
677 interp :: LinkedIExpr -> HValue
678 interp iexpr = unsafeCoerce# (evalP iexpr emptyUFM)
680 evalP :: LinkedIExpr -> UniqFM boxed -> boxed
684 -- | trace ("evalP: " ++ showExprTag expr) False
685 | trace ("evalP:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
686 = error "evalP: ?!?!"
689 evalP (Native p) de = unsafeCoerce# p
691 -- First try the dynamic env. If that fails, assume it's a top-level
692 -- binding and look in the static env. That gives an Expr, which we
693 -- must convert to a boxed thingy by applying evalP to it. Because
694 -- top-level bindings are always ptr-rep'd (either lambdas or boxed
695 -- CAFs), it's always safe to use evalP.
697 = case lookupUFM de v of
699 Nothing -> error ("evalP: lookupUFM " ++ show v)
701 -- Deal with application of a function returning a pointer rep
702 -- to arguments of any persuasion. Note that the function itself
703 -- always has pointer rep.
704 evalP (AppIP e1 e2) de = unsafeCoerce# (evalP e1 de) (evalI e2 de)
705 evalP (AppPP e1 e2) de = unsafeCoerce# (evalP e1 de) (evalP e2 de)
706 evalP (AppFP e1 e2) de = unsafeCoerce# (evalP e1 de) (evalF e2 de)
707 evalP (AppDP e1 e2) de = unsafeCoerce# (evalP e1 de) (evalD e2 de)
709 -- Lambdas always return P-rep, but we need to do different things
710 -- depending on both the argument and result representations.
712 = unsafeCoerce# (\ xP -> evalP b (addToUFM de x xP))
714 = unsafeCoerce# (\ xP -> evalI b (addToUFM de x xP))
716 = unsafeCoerce# (\ xP -> evalF b (addToUFM de x xP))
718 = unsafeCoerce# (\ xP -> evalD b (addToUFM de x xP))
720 = unsafeCoerce# (\ xI -> evalP b (addToUFM de x (unsafeCoerce# (I# xI))))
722 = unsafeCoerce# (\ xI -> evalI b (addToUFM de x (unsafeCoerce# (I# xI))))
724 = unsafeCoerce# (\ xI -> evalF b (addToUFM de x (unsafeCoerce# (I# xI))))
726 = unsafeCoerce# (\ xI -> evalD b (addToUFM de x (unsafeCoerce# (I# xI))))
728 = unsafeCoerce# (\ xI -> evalP b (addToUFM de x (unsafeCoerce# (F# xI))))
730 = unsafeCoerce# (\ xI -> evalI b (addToUFM de x (unsafeCoerce# (F# xI))))
732 = unsafeCoerce# (\ xI -> evalF b (addToUFM de x (unsafeCoerce# (F# xI))))
734 = unsafeCoerce# (\ xI -> evalD b (addToUFM de x (unsafeCoerce# (F# xI))))
736 = unsafeCoerce# (\ xI -> evalP b (addToUFM de x (unsafeCoerce# (D# xI))))
738 = unsafeCoerce# (\ xI -> evalI b (addToUFM de x (unsafeCoerce# (D# xI))))
740 = unsafeCoerce# (\ xI -> evalF b (addToUFM de x (unsafeCoerce# (D# xI))))
742 = unsafeCoerce# (\ xI -> evalD b (addToUFM de x (unsafeCoerce# (D# xI))))
745 -- NonRec, Rec, CaseAlg and CasePrim are the same for all result reps,
746 -- except in the sense that we go on and evaluate the body with whichever
747 -- evaluator was used for the expression as a whole.
748 evalP (NonRecP bind e) de
749 = evalP e (augment_nonrec bind de)
750 evalP (RecP binds b) de
751 = evalP b (augment_rec binds de)
752 evalP (CaseAlgP bndr expr alts def) de
753 = case helper_caseAlg bndr expr alts def de of
754 (rhs, de') -> evalP rhs de'
755 evalP (CasePrimP bndr expr alts def) de
756 = case helper_casePrim bndr expr alts def de of
757 (rhs, de') -> evalP rhs de'
759 evalP (ConApp (A# itbl)) de
760 = mci_make_constr0 itbl
762 evalP (ConAppI (A# itbl) a1) de
763 = case evalI a1 de of i1 -> mci_make_constrI itbl i1
765 evalP (ConAppP (A# itbl) a1) de
766 = evalP (ConAppGen (A# itbl) [a1]) de
767 -- = let p1 = evalP a1 de
768 -- in mci_make_constrP itbl p1
770 evalP (ConAppPP (A# itbl) a1 a2) de
771 = let p1 = evalP a1 de
773 in mci_make_constrPP itbl p1 p2
775 evalP (ConAppGen itbl args) de
776 = let c = case itbl of A# a# -> mci_make_constr a# in
777 c `seq` loop c 1#{-leave room for hdr-} args
779 loop :: a{-closure-} -> Int# -> [LinkedIExpr] -> a
783 RepP -> let c' = setPtrOffClosure c off (evalP a de)
784 in c' `seq` loop c' (off +# 1#) as
785 RepI -> case evalI a de of { i# ->
786 let c' = setIntOffClosure c off i#
787 in c' `seq` loop c' (off +# 1#) as }
788 RepF -> case evalF a de of { f# ->
789 let c' = setFloatOffClosure c off f#
790 in c' `seq` loop c' (off +# 1#) as }
791 RepD -> case evalD a de of { d# ->
792 let c' = setDoubleOffClosure c off d#
793 in c' `seq` loop c' (off +# 2#) as }
796 = error ("evalP: unhandled case: " ++ showExprTag other)
798 --------------------------------------------------------
799 --- Evaluator for things of Int# representation
800 --------------------------------------------------------
802 -- Evaluate something which has an unboxed Int rep
803 evalI :: LinkedIExpr -> UniqFM boxed -> Int#
807 -- | trace ("evalI: " ++ showExprTag expr) False
808 | trace ("evalI:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
809 = error "evalI: ?!?!"
812 evalI (LitI i#) de = i#
815 case lookupUFM de v of
816 Just e -> case unsafeCoerce# e of I# i -> i
817 Nothing -> error ("evalI: lookupUFM " ++ show v)
819 -- Deal with application of a function returning an Int# rep
820 -- to arguments of any persuasion. Note that the function itself
821 -- always has pointer rep.
822 evalI (AppII e1 e2) de
823 = unsafeCoerce# (evalP e1 de) (evalI e2 de)
824 evalI (AppPI e1 e2) de
825 = unsafeCoerce# (evalP e1 de) (evalP e2 de)
826 evalI (AppFI e1 e2) de
827 = unsafeCoerce# (evalP e1 de) (evalF e2 de)
828 evalI (AppDI e1 e2) de
829 = unsafeCoerce# (evalP e1 de) (evalD e2 de)
831 -- NonRec, Rec, CaseAlg and CasePrim are the same for all result reps,
832 -- except in the sense that we go on and evaluate the body with whichever
833 -- evaluator was used for the expression as a whole.
834 evalI (NonRecI bind b) de
835 = evalI b (augment_nonrec bind de)
836 evalI (RecI binds b) de
837 = evalI b (augment_rec binds de)
838 evalI (CaseAlgI bndr expr alts def) de
839 = case helper_caseAlg bndr expr alts def de of
840 (rhs, de') -> evalI rhs de'
841 evalI (CasePrimI bndr expr alts def) de
842 = case helper_casePrim bndr expr alts def de of
843 (rhs, de') -> evalI rhs de'
845 -- evalI can't be applied to a lambda term, by defn, since those
848 evalI (PrimOpI IntAddOp [e1,e2]) de = evalI e1 de +# evalI e2 de
849 evalI (PrimOpI IntSubOp [e1,e2]) de = evalI e1 de -# evalI e2 de
851 --evalI (NonRec (IBind v e) b) de
852 -- = evalI b (augment de v (eval e de))
855 = error ("evalI: unhandled case: " ++ showExprTag other)
857 --------------------------------------------------------
858 --- Evaluator for things of Float# representation
859 --------------------------------------------------------
861 -- Evaluate something which has an unboxed Int rep
862 evalF :: LinkedIExpr -> UniqFM boxed -> Float#
866 -- | trace ("evalF: " ++ showExprTag expr) False
867 | trace ("evalF:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
868 = error "evalF: ?!?!"
871 evalF (LitF f#) de = f#
874 case lookupUFM de v of
875 Just e -> case unsafeCoerce# e of F# i -> i
876 Nothing -> error ("evalF: lookupUFM " ++ show v)
878 -- Deal with application of a function returning an Int# rep
879 -- to arguments of any persuasion. Note that the function itself
880 -- always has pointer rep.
881 evalF (AppIF e1 e2) de
882 = unsafeCoerce# (evalP e1 de) (evalI e2 de)
883 evalF (AppPF e1 e2) de
884 = unsafeCoerce# (evalP e1 de) (evalP e2 de)
885 evalF (AppFF e1 e2) de
886 = unsafeCoerce# (evalP e1 de) (evalF e2 de)
887 evalF (AppDF e1 e2) de
888 = unsafeCoerce# (evalP e1 de) (evalD e2 de)
890 -- NonRec, Rec, CaseAlg and CasePrim are the same for all result reps,
891 -- except in the sense that we go on and evaluate the body with whichever
892 -- evaluator was used for the expression as a whole.
893 evalF (NonRecF bind b) de
894 = evalF b (augment_nonrec bind de)
895 evalF (RecF binds b) de
896 = evalF b (augment_rec binds de)
897 evalF (CaseAlgF bndr expr alts def) de
898 = case helper_caseAlg bndr expr alts def de of
899 (rhs, de') -> evalF rhs de'
900 evalF (CasePrimF bndr expr alts def) de
901 = case helper_casePrim bndr expr alts def de of
902 (rhs, de') -> evalF rhs de'
904 -- evalF can't be applied to a lambda term, by defn, since those
907 evalF (PrimOpF op _) de
908 = error ("evalF: unhandled primop: " ++ showSDoc (ppr op))
911 = error ("evalF: unhandled case: " ++ showExprTag other)
913 --------------------------------------------------------
914 --- Evaluator for things of Double# representation
915 --------------------------------------------------------
917 -- Evaluate something which has an unboxed Int rep
918 evalD :: LinkedIExpr -> UniqFM boxed -> Double#
922 -- | trace ("evalD: " ++ showExprTag expr) False
923 | trace ("evalD:\n" ++ showSDoc (pprIExpr expr) ++ "\n") False
924 = error "evalD: ?!?!"
927 evalD (LitD d#) de = d#
930 case lookupUFM de v of
931 Just e -> case unsafeCoerce# e of D# i -> i
932 Nothing -> error ("evalD: lookupUFM " ++ show v)
934 -- Deal with application of a function returning an Int# rep
935 -- to arguments of any persuasion. Note that the function itself
936 -- always has pointer rep.
937 evalD (AppID e1 e2) de
938 = unsafeCoerce# (evalP e1 de) (evalI e2 de)
939 evalD (AppPD e1 e2) de
940 = unsafeCoerce# (evalP e1 de) (evalP e2 de)
941 evalD (AppFD e1 e2) de
942 = unsafeCoerce# (evalP e1 de) (evalF e2 de)
943 evalD (AppDD e1 e2) de
944 = unsafeCoerce# (evalP e1 de) (evalD e2 de)
946 -- NonRec, Rec, CaseAlg and CasePrim are the same for all result reps,
947 -- except in the sense that we go on and evaluate the body with whichever
948 -- evaluator was used for the expression as a whole.
949 evalD (NonRecD bind b) de
950 = evalD b (augment_nonrec bind de)
951 evalD (RecD binds b) de
952 = evalD b (augment_rec binds de)
953 evalD (CaseAlgD bndr expr alts def) de
954 = case helper_caseAlg bndr expr alts def de of
955 (rhs, de') -> evalD rhs de'
956 evalD (CasePrimD bndr expr alts def) de
957 = case helper_casePrim bndr expr alts def de of
958 (rhs, de') -> evalD rhs de'
960 -- evalD can't be applied to a lambda term, by defn, since those
963 evalD (PrimOpD op _) de
964 = error ("evalD: unhandled primop: " ++ showSDoc (ppr op))
967 = error ("evalD: unhandled case: " ++ showExprTag other)
969 --------------------------------------------------------
970 --- Helper bits and pieces
971 --------------------------------------------------------
973 -- Find the Rep of any Expr
974 repOf :: LinkedIExpr -> Rep
976 repOf (LamPP _ _) = RepP
977 repOf (LamPI _ _) = RepP
978 repOf (LamPF _ _) = RepP
979 repOf (LamPD _ _) = RepP
980 repOf (LamIP _ _) = RepP
981 repOf (LamII _ _) = RepP
982 repOf (LamIF _ _) = RepP
983 repOf (LamID _ _) = RepP
984 repOf (LamFP _ _) = RepP
985 repOf (LamFI _ _) = RepP
986 repOf (LamFF _ _) = RepP
987 repOf (LamFD _ _) = RepP
988 repOf (LamDP _ _) = RepP
989 repOf (LamDI _ _) = RepP
990 repOf (LamDF _ _) = RepP
991 repOf (LamDD _ _) = RepP
993 repOf (AppPP _ _) = RepP
994 repOf (AppPI _ _) = RepI
995 repOf (AppPF _ _) = RepF
996 repOf (AppPD _ _) = RepD
997 repOf (AppIP _ _) = RepP
998 repOf (AppII _ _) = RepI
999 repOf (AppIF _ _) = RepF
1000 repOf (AppID _ _) = RepD
1001 repOf (AppFP _ _) = RepP
1002 repOf (AppFI _ _) = RepI
1003 repOf (AppFF _ _) = RepF
1004 repOf (AppFD _ _) = RepD
1005 repOf (AppDP _ _) = RepP
1006 repOf (AppDI _ _) = RepI
1007 repOf (AppDF _ _) = RepF
1008 repOf (AppDD _ _) = RepD
1010 repOf (NonRecP _ _) = RepP
1011 repOf (NonRecI _ _) = RepI
1012 repOf (NonRecF _ _) = RepF
1013 repOf (NonRecD _ _) = RepD
1015 repOf (RecP _ _) = RepP
1016 repOf (RecI _ _) = RepI
1017 repOf (RecF _ _) = RepF
1018 repOf (RecD _ _) = RepD
1020 repOf (LitI _) = RepI
1021 repOf (LitF _) = RepF
1022 repOf (LitD _) = RepD
1024 repOf (Native _) = RepP
1026 repOf (VarP _) = RepP
1027 repOf (VarI _) = RepI
1028 repOf (VarF _) = RepF
1029 repOf (VarD _) = RepD
1031 repOf (PrimOpP _ _) = RepP
1032 repOf (PrimOpI _ _) = RepI
1033 repOf (PrimOpF _ _) = RepF
1034 repOf (PrimOpD _ _) = RepD
1036 repOf (ConApp _) = RepP
1037 repOf (ConAppI _ _) = RepP
1038 repOf (ConAppP _ _) = RepP
1039 repOf (ConAppPP _ _ _) = RepP
1040 repOf (ConAppGen _ _) = RepP
1042 repOf (CaseAlgP _ _ _ _) = RepP
1043 repOf (CaseAlgI _ _ _ _) = RepI
1044 repOf (CaseAlgF _ _ _ _) = RepF
1045 repOf (CaseAlgD _ _ _ _) = RepD
1047 repOf (CasePrimP _ _ _ _) = RepP
1048 repOf (CasePrimI _ _ _ _) = RepI
1049 repOf (CasePrimF _ _ _ _) = RepF
1050 repOf (CasePrimD _ _ _ _) = RepD
1053 = error ("repOf: unhandled case: " ++ showExprTag other)
1055 -- how big (in words) is one of these
1056 repSizeW :: Rep -> Int
1061 -- Evaluate an expression, using the appropriate evaluator,
1062 -- then box up the result. Note that it's only safe to use this
1063 -- to create values to put in the environment. You can't use it
1064 -- to create a value which might get passed to native code since that
1065 -- code will have no idea that unboxed things have been boxed.
1066 eval :: LinkedIExpr -> UniqFM boxed -> boxed
1068 = case repOf expr of
1069 RepI -> unsafeCoerce# (I# (evalI expr de))
1070 RepP -> evalP expr de
1071 RepF -> unsafeCoerce# (F# (evalF expr de))
1072 RepD -> unsafeCoerce# (D# (evalD expr de))
1074 -- Evaluate the scrutinee of a case, select an alternative,
1075 -- augment the environment appropriately, and return the alt
1076 -- and the augmented environment.
1077 helper_caseAlg :: Id -> LinkedIExpr -> [LinkedAltAlg] -> Maybe LinkedIExpr
1079 -> (LinkedIExpr, UniqFM boxed)
1080 helper_caseAlg bndr expr alts def de
1081 = let exprEv = evalP expr de
1083 exprEv `seq` -- vitally important; otherwise exprEv is never eval'd
1084 case select_altAlg (tagOf exprEv) alts def of
1085 (vars,rhs) -> (rhs, augment_from_constr (addToUFM de bndr exprEv)
1088 helper_casePrim :: Var -> LinkedIExpr -> [LinkedAltPrim] -> Maybe LinkedIExpr
1090 -> (LinkedIExpr, UniqFM boxed)
1091 helper_casePrim bndr expr alts def de
1092 = case repOf expr of
1093 RepI -> case evalI expr de of
1094 i# -> (select_altPrim alts def (LitI i#),
1095 addToUFM de bndr (unsafeCoerce# (I# i#)))
1096 RepF -> case evalF expr de of
1097 f# -> (select_altPrim alts def (LitF f#),
1098 addToUFM de bndr (unsafeCoerce# (F# f#)))
1099 RepD -> case evalD expr de of
1100 d# -> (select_altPrim alts def (LitD d#),
1101 addToUFM de bndr (unsafeCoerce# (D# d#)))
1104 augment_from_constr :: UniqFM boxed -> a -> ([(Id,Rep)],Int) -> UniqFM boxed
1105 augment_from_constr de con ([],offset)
1107 augment_from_constr de con ((v,rep):vs,offset)
1110 RepP -> indexPtrOffClosure con offset
1111 RepI -> unsafeCoerce# (I# (indexIntOffClosure con offset))
1112 RepF -> unsafeCoerce# (F# (indexFloatOffClosure con offset))
1113 RepD -> unsafeCoerce# (D# (indexDoubleOffClosure con offset))
1115 augment_from_constr (addToUFM de v v_binding) con
1116 (vs,offset + repSizeW rep)
1118 -- Augment the environment for a non-recursive let.
1119 augment_nonrec :: LinkedIBind -> UniqFM boxed -> UniqFM boxed
1120 augment_nonrec (IBind v e) de = addToUFM de v (eval e de)
1122 -- Augment the environment for a recursive let.
1123 augment_rec :: [LinkedIBind] -> UniqFM boxed -> UniqFM boxed
1124 augment_rec binds de
1125 = let vars = map binder binds
1126 rhss = map bindee binds
1127 rhs_vs = map (\rhs -> eval rhs de') rhss
1128 de' = addListToUFM de (zip vars rhs_vs)
1132 -- a must be a constructor?
1134 tagOf x = I# (dataToTag# x)
1136 select_altAlg :: Int -> [LinkedAltAlg] -> Maybe LinkedIExpr -> ([(Id,Rep)],LinkedIExpr)
1137 select_altAlg tag [] Nothing = error "select_altAlg: no match and no default?!"
1138 select_altAlg tag [] (Just def) = ([],def)
1139 select_altAlg tag ((AltAlg tagNo vars rhs):alts) def
1142 else select_altAlg tag alts def
1144 -- literal may only be a literal, not an arbitrary expression
1145 select_altPrim :: [LinkedAltPrim] -> Maybe LinkedIExpr -> LinkedIExpr -> LinkedIExpr
1146 select_altPrim [] Nothing literal = error "select_altPrim: no match and no default?!"
1147 select_altPrim [] (Just def) literal = def
1148 select_altPrim ((AltPrim lit rhs):alts) def literal
1149 = if eqLits lit literal
1151 else select_altPrim alts def literal
1153 eqLits (LitI i1#) (LitI i2#) = i1# ==# i2#
1155 -- ----------------------------------------------------------------------
1156 -- Grotty inspection and creation of closures
1157 -- ----------------------------------------------------------------------
1159 -- a is a constructor
1160 indexPtrOffClosure :: a -> Int -> b
1161 indexPtrOffClosure con (I# offset)
1162 = case indexPtrOffClosure# con offset of (# x #) -> x
1164 indexIntOffClosure :: a -> Int -> Int#
1165 indexIntOffClosure con (I# offset)
1166 = case wordToInt (W# (indexWordOffClosure# con offset)) of I# i# -> i#
1168 indexFloatOffClosure :: a -> Int -> Float#
1169 indexFloatOffClosure con (I# offset)
1170 = unsafeCoerce# (indexWordOffClosure# con offset)
1171 -- TOCK TOCK TOCK! Those GHC developers are crazy.
1173 indexDoubleOffClosure :: a -> Int -> Double#
1174 indexDoubleOffClosure con (I# offset)
1175 = unsafeCoerce# (panic "indexDoubleOffClosure")
1177 setPtrOffClosure :: a -> Int# -> b -> a
1178 setPtrOffClosure a i b = case setPtrOffClosure# a i b of (# c #) -> c
1180 setIntOffClosure :: a -> Int# -> Int# -> a
1181 setIntOffClosure a i b = case setWordOffClosure# a i (int2Word# b) of (# c #) -> c
1183 setFloatOffClosure :: a -> Int# -> Float# -> a
1184 setFloatOffClosure a i b = case setWordOffClosure# a i (unsafeCoerce# b) of (# c #) -> c
1186 setDoubleOffClosure :: a -> Int# -> Double# -> a
1187 setDoubleOffClosure a i b = unsafeCoerce# (panic "setDoubleOffClosure")
1189 ------------------------------------------------------------------------
1190 --- Manufacturing of info tables for DataCons defined in this module ---
1191 ------------------------------------------------------------------------
1193 #if __GLASGOW_HASKELL__ <= 408
1196 type ItblPtr = Ptr StgInfoTable
1199 -- Make info tables for the data decls in this module
1200 mkITbls :: [TyCon] -> IO ItblEnv
1201 mkITbls [] = return emptyFM
1202 mkITbls (tc:tcs) = do itbls <- mkITbl tc
1203 itbls2 <- mkITbls tcs
1204 return (itbls `plusFM` itbls2)
1206 mkITbl :: TyCon -> IO ItblEnv
1208 -- | trace ("TYCON: " ++ showSDoc (ppr tc)) False
1210 | not (isDataTyCon tc)
1212 | n == length dcs -- paranoia; this is an assertion.
1213 = make_constr_itbls dcs
1215 dcs = tyConDataCons tc
1216 n = tyConFamilySize tc
1219 cONSTR = 1 -- as defined in ghc/includes/ClosureTypes.h
1221 -- Assumes constructors are numbered from zero, not one
1222 make_constr_itbls :: [DataCon] -> IO ItblEnv
1223 make_constr_itbls cons
1225 = do is <- mapM mk_vecret_itbl (zip cons [0..])
1226 return (listToFM is)
1228 = do is <- mapM mk_dirret_itbl (zip cons [0..])
1229 return (listToFM is)
1231 mk_vecret_itbl (dcon, conNo)
1232 = mk_itbl dcon conNo (vecret_entry conNo)
1233 mk_dirret_itbl (dcon, conNo)
1234 = mk_itbl dcon conNo mci_constr_entry
1236 mk_itbl :: DataCon -> Int -> Addr -> IO (RdrName,ItblPtr)
1237 mk_itbl dcon conNo entry_addr
1238 = let (tot_wds, ptr_wds, _)
1239 = mkVirtHeapOffsets typePrimRep (dataConRepArgTys dcon)
1241 nptrs = tot_wds - ptr_wds
1242 itbl = StgInfoTable {
1243 ptrs = fromIntegral ptrs, nptrs = fromIntegral nptrs,
1244 tipe = fromIntegral cONSTR,
1245 srtlen = fromIntegral conNo,
1246 code0 = fromIntegral code0, code1 = fromIntegral code1,
1247 code2 = fromIntegral code2, code3 = fromIntegral code3,
1248 code4 = fromIntegral code4, code5 = fromIntegral code5,
1249 code6 = fromIntegral code6, code7 = fromIntegral code7
1251 -- Make a piece of code to jump to "entry_label".
1252 -- This is the only arch-dependent bit.
1253 -- On x86, if entry_label has an address 0xWWXXYYZZ,
1254 -- emit movl $0xWWXXYYZZ,%eax ; jmp *%eax
1256 -- B8 ZZ YY XX WW FF E0
1257 (code0,code1,code2,code3,code4,code5,code6,code7)
1258 = (0xB8, byte 0 entry_addr_w, byte 1 entry_addr_w,
1259 byte 2 entry_addr_w, byte 3 entry_addr_w,
1263 entry_addr_w :: Word32
1264 entry_addr_w = fromIntegral (addrToInt entry_addr)
1267 putStrLn ("SIZE of itbl is " ++ show (sizeOf itbl))
1268 putStrLn ("# ptrs of itbl is " ++ show ptrs)
1269 putStrLn ("# nptrs of itbl is " ++ show nptrs)
1271 return (toRdrName dcon, addr `plusPtr` 8)
1274 byte :: Int -> Word32 -> Word32
1275 byte 0 w = w .&. 0xFF
1276 byte 1 w = (w `shiftR` 8) .&. 0xFF
1277 byte 2 w = (w `shiftR` 16) .&. 0xFF
1278 byte 3 w = (w `shiftR` 24) .&. 0xFF
1281 vecret_entry 0 = mci_constr1_entry
1282 vecret_entry 1 = mci_constr2_entry
1283 vecret_entry 2 = mci_constr3_entry
1284 vecret_entry 3 = mci_constr4_entry
1285 vecret_entry 4 = mci_constr5_entry
1286 vecret_entry 5 = mci_constr6_entry
1287 vecret_entry 6 = mci_constr7_entry
1288 vecret_entry 7 = mci_constr8_entry
1290 -- entry point for direct returns for created constr itbls
1291 foreign label "stg_mci_constr_entry" mci_constr_entry :: Addr
1292 -- and the 8 vectored ones
1293 foreign label "stg_mci_constr1_entry" mci_constr1_entry :: Addr
1294 foreign label "stg_mci_constr2_entry" mci_constr2_entry :: Addr
1295 foreign label "stg_mci_constr3_entry" mci_constr3_entry :: Addr
1296 foreign label "stg_mci_constr4_entry" mci_constr4_entry :: Addr
1297 foreign label "stg_mci_constr5_entry" mci_constr5_entry :: Addr
1298 foreign label "stg_mci_constr6_entry" mci_constr6_entry :: Addr
1299 foreign label "stg_mci_constr7_entry" mci_constr7_entry :: Addr
1300 foreign label "stg_mci_constr8_entry" mci_constr8_entry :: Addr
1304 data Constructor = Constructor Int{-ptrs-} Int{-nptrs-}
1307 -- Ultra-minimalist version specially for constructors
1308 data StgInfoTable = StgInfoTable {
1313 code0, code1, code2, code3, code4, code5, code6, code7 :: Word8
1317 instance Storable StgInfoTable where
1320 = (sum . map (\f -> f itbl))
1321 [fieldSz ptrs, fieldSz nptrs, fieldSz srtlen, fieldSz tipe,
1322 fieldSz code0, fieldSz code1, fieldSz code2, fieldSz code3,
1323 fieldSz code4, fieldSz code5, fieldSz code6, fieldSz code7]
1326 = (sum . map (\f -> f itbl))
1327 [fieldAl ptrs, fieldAl nptrs, fieldAl srtlen, fieldAl tipe,
1328 fieldAl code0, fieldAl code1, fieldAl code2, fieldAl code3,
1329 fieldAl code4, fieldAl code5, fieldAl code6, fieldAl code7]
1332 = do a1 <- store (ptrs itbl) (castPtr a0)
1333 a2 <- store (nptrs itbl) a1
1334 a3 <- store (tipe itbl) a2
1335 a4 <- store (srtlen itbl) a3
1336 a5 <- store (code0 itbl) a4
1337 a6 <- store (code1 itbl) a5
1338 a7 <- store (code2 itbl) a6
1339 a8 <- store (code3 itbl) a7
1340 a9 <- store (code4 itbl) a8
1341 aA <- store (code5 itbl) a9
1342 aB <- store (code6 itbl) aA
1343 aC <- store (code7 itbl) aB
1347 = do (a1,ptrs) <- load (castPtr a0)
1348 (a2,nptrs) <- load a1
1349 (a3,tipe) <- load a2
1350 (a4,srtlen) <- load a3
1351 (a5,code0) <- load a4
1352 (a6,code1) <- load a5
1353 (a7,code2) <- load a6
1354 (a8,code3) <- load a7
1355 (a9,code4) <- load a8
1356 (aA,code5) <- load a9
1357 (aB,code6) <- load aA
1358 (aC,code7) <- load aB
1359 return StgInfoTable { ptrs = ptrs, nptrs = nptrs,
1360 srtlen = srtlen, tipe = tipe,
1361 code0 = code0, code1 = code1, code2 = code2,
1362 code3 = code3, code4 = code4, code5 = code5,
1363 code6 = code6, code7 = code7 }
1365 fieldSz :: (Storable a, Storable b) => (a -> b) -> a -> Int
1366 fieldSz sel x = sizeOf (sel x)
1368 fieldAl :: (Storable a, Storable b) => (a -> b) -> a -> Int
1369 fieldAl sel x = alignment (sel x)
1371 store :: Storable a => a -> Ptr a -> IO (Ptr b)
1372 store x addr = do poke addr x
1373 return (castPtr (addr `plusPtr` sizeOf x))
1375 load :: Storable a => Ptr a -> IO (Ptr b, a)
1376 load addr = do x <- peek addr
1377 return (castPtr (addr `plusPtr` sizeOf x), x)
1379 -----------------------------------------------------------------------------q
1381 foreign import "strncpy" strncpy :: Ptr a -> ByteArray# -> CInt -> IO ()