d7a477bfdc17459cf78ec201b02b4cf223948b46
[ghc-hetmet.git] / ghc / compiler / ghci / ByteCodeGen.lhs
1 %
2 % (c) The University of Glasgow 2002
3 %
4 \section[ByteCodeGen]{Generate bytecode from Core}
5
6 \begin{code}
7 module ByteCodeGen ( UnlinkedBCO, byteCodeGen, coreExprToBCOs ) where
8
9 #include "HsVersions.h"
10
11 import ByteCodeInstr
12 import ByteCodeFFI      ( mkMarshalCode, moan64 )
13 import ByteCodeAsm      ( CompiledByteCode(..), UnlinkedBCO, 
14                           assembleBCO, assembleBCOs, iNTERP_STACK_CHECK_THRESH )
15 import ByteCodeLink     ( lookupStaticPtr )
16
17 import Outputable
18 import Name             ( Name, getName, mkSystemName )
19 import Id
20 import FiniteMap
21 import ForeignCall      ( ForeignCall(..), CCallTarget(..), CCallSpec(..) )
22 import HscTypes         ( TypeEnv, typeEnvTyCons, typeEnvClasses )
23 import CoreUtils        ( exprType )
24 import CoreSyn
25 import PprCore          ( pprCoreExpr )
26 import Literal          ( Literal(..), literalPrimRep )
27 import PrimRep
28 import PrimOp           ( PrimOp(..) )
29 import CoreFVs          ( freeVars )
30 import Type             ( typePrimRep, isUnLiftedType, splitTyConApp_maybe )
31 import DataCon          ( DataCon, dataConTag, fIRST_TAG, dataConTyCon, 
32                           isUnboxedTupleCon, isNullaryDataCon, dataConWorkId,
33                           dataConRepArity )
34 import TyCon            ( tyConFamilySize, isDataTyCon, tyConDataCons,
35                           isUnboxedTupleTyCon )
36 import Class            ( Class, classTyCon )
37 import Type             ( Type, repType, splitFunTys, dropForAlls, pprType )
38 import Util
39 import DataCon          ( dataConRepArity )
40 import Var              ( isTyVar )
41 import VarSet           ( VarSet, varSetElems )
42 import TysPrim          ( arrayPrimTyCon, mutableArrayPrimTyCon,
43                           byteArrayPrimTyCon, mutableByteArrayPrimTyCon
44                         )
45 import PrimRep          ( isFollowableRep )
46 import CmdLineOpts      ( DynFlags, DynFlag(..) )
47 import ErrUtils         ( showPass, dumpIfSet_dyn )
48 import Unique           ( mkPseudoUnique3 )
49 import FastString       ( FastString(..), unpackFS )
50 import Panic            ( GhcException(..) )
51 import SMRep            ( arrWordsHdrSize, arrPtrsHdrSize, StgWord )
52 import Bitmap           ( intsToReverseBitmap, mkBitmap )
53 import OrdList
54 import Constants        ( wORD_SIZE )
55
56 import Data.List        ( intersperse, sortBy, zip4, zip5, partition )
57 import Foreign          ( Ptr, castPtr, mallocBytes, pokeByteOff, Word8 )
58 import Foreign.C        ( CInt )
59 import Control.Exception        ( throwDyn )
60
61 import GHC.Exts         ( Int(..), ByteArray# )
62
63 import Control.Monad    ( when )
64 import Data.Char        ( ord, chr )
65
66 -- -----------------------------------------------------------------------------
67 -- Generating byte code for a complete module 
68
69 byteCodeGen :: DynFlags
70             -> [CoreBind]
71             -> TypeEnv
72             -> IO CompiledByteCode
73 byteCodeGen dflags binds type_env
74    = do showPass dflags "ByteCodeGen"
75         let  local_tycons  = typeEnvTyCons  type_env
76              local_classes = typeEnvClasses type_env
77              tycs = local_tycons ++ map classTyCon local_classes
78
79         let flatBinds = [ (bndr, freeVars rhs) 
80                         | (bndr, rhs) <- flattenBinds binds]
81
82         (BcM_State final_ctr mallocd, proto_bcos)
83            <- runBc (mapM schemeTopBind flatBinds)
84
85         when (notNull mallocd)
86              (panic "ByteCodeGen.byteCodeGen: missing final emitBc?")
87
88         dumpIfSet_dyn dflags Opt_D_dump_BCOs
89            "Proto-BCOs" (vcat (intersperse (char ' ') (map ppr proto_bcos)))
90
91         assembleBCOs proto_bcos tycs
92         
93 -- -----------------------------------------------------------------------------
94 -- Generating byte code for an expression
95
96 -- Returns: (the root BCO for this expression, 
97 --           a list of auxilary BCOs resulting from compiling closures)
98 coreExprToBCOs :: DynFlags
99                -> CoreExpr
100                -> IO UnlinkedBCO
101 coreExprToBCOs dflags expr
102  = do showPass dflags "ByteCodeGen"
103
104       -- create a totally bogus name for the top-level BCO; this
105       -- should be harmless, since it's never used for anything
106       let invented_name  = mkSystemName (mkPseudoUnique3 0) FSLIT("ExprTopLevel")
107           invented_id    = mkLocalId invented_name (panic "invented_id's type")
108           
109       (BcM_State final_ctr mallocd, proto_bco) 
110          <- runBc (schemeTopBind (invented_id, freeVars expr))
111
112       when (notNull mallocd)
113            (panic "ByteCodeGen.coreExprToBCOs: missing final emitBc?")
114
115       dumpIfSet_dyn dflags Opt_D_dump_BCOs "Proto-BCOs" (ppr proto_bco)
116
117       assembleBCO proto_bco
118
119
120 -- -----------------------------------------------------------------------------
121 -- Compilation schema for the bytecode generator
122
123 type BCInstrList = OrdList BCInstr
124
125 type Sequel = Int       -- back off to this depth before ENTER
126
127 -- Maps Ids to the offset from the stack _base_ so we don't have
128 -- to mess with it after each push/pop.
129 type BCEnv = FiniteMap Id Int   -- To find vars on the stack
130
131 ppBCEnv :: BCEnv -> SDoc
132 ppBCEnv p
133    = text "begin-env"
134      $$ nest 4 (vcat (map pp_one (sortBy cmp_snd (fmToList p))))
135      $$ text "end-env"
136      where
137         pp_one (var, offset) = int offset <> colon <+> ppr var <+> ppr (idPrimRep var)
138         cmp_snd x y = compare (snd x) (snd y)
139
140 -- Create a BCO and do a spot of peephole optimisation on the insns
141 -- at the same time.
142 mkProtoBCO
143    :: name
144    -> BCInstrList
145    -> Either  [AnnAlt Id VarSet] (AnnExpr Id VarSet)
146    -> Int
147    -> Int
148    -> [StgWord]
149    -> Bool      -- True <=> is a return point, rather than a function
150    -> [Ptr ()]
151    -> ProtoBCO name
152 mkProtoBCO nm instrs_ordlist origin arity bitmap_size bitmap
153   is_ret mallocd_blocks
154    = ProtoBCO {
155         protoBCOName = nm,
156         protoBCOInstrs = maybe_with_stack_check,
157         protoBCOBitmap = bitmap,
158         protoBCOBitmapSize = bitmap_size,
159         protoBCOArity = arity,
160         protoBCOExpr = origin,
161         protoBCOPtrs = mallocd_blocks
162       }
163      where
164         -- Overestimate the stack usage (in words) of this BCO,
165         -- and if >= iNTERP_STACK_CHECK_THRESH, add an explicit
166         -- stack check.  (The interpreter always does a stack check
167         -- for iNTERP_STACK_CHECK_THRESH words at the start of each
168         -- BCO anyway, so we only need to add an explicit on in the
169         -- (hopefully rare) cases when the (overestimated) stack use
170         -- exceeds iNTERP_STACK_CHECK_THRESH.
171         maybe_with_stack_check
172            | is_ret = peep_d
173                 -- don't do stack checks at return points;
174                 -- everything is aggregated up to the top BCO
175                 -- (which must be a function)
176            | stack_overest >= 65535
177            = pprPanic "mkProtoBCO: stack use won't fit in 16 bits" 
178                       (int stack_overest)
179            | stack_overest >= iNTERP_STACK_CHECK_THRESH
180            = STKCHECK stack_overest : peep_d
181            | otherwise
182            = peep_d     -- the supposedly common case
183              
184         stack_overest = sum (map bciStackUse peep_d)
185
186         -- Merge local pushes
187         peep_d = peep (fromOL instrs_ordlist)
188
189         peep (PUSH_L off1 : PUSH_L off2 : PUSH_L off3 : rest)
190            = PUSH_LLL off1 (off2-1) (off3-2) : peep rest
191         peep (PUSH_L off1 : PUSH_L off2 : rest)
192            = PUSH_LL off1 (off2-1) : peep rest
193         peep (i:rest)
194            = i : peep rest
195         peep []
196            = []
197
198 argBits :: [PrimRep] -> [Bool]
199 argBits [] = []
200 argBits (rep : args)
201   | isFollowableRep rep = False : argBits args
202   | otherwise = take (getPrimRepSize rep) (repeat True) ++ argBits args
203
204 -- -----------------------------------------------------------------------------
205 -- schemeTopBind
206
207 -- Compile code for the right-hand side of a top-level binding
208
209 schemeTopBind :: (Id, AnnExpr Id VarSet) -> BcM (ProtoBCO Name)
210
211
212 schemeTopBind (id, rhs)
213   | Just data_con <- isDataConWorkId_maybe id,
214     isNullaryDataCon data_con
215   =     -- Special case for the worker of a nullary data con.
216         -- It'll look like this:        Nil = /\a -> Nil a
217         -- If we feed it into schemeR, we'll get 
218         --      Nil = Nil
219         -- because mkConAppCode treats nullary constructor applications
220         -- by just re-using the single top-level definition.  So
221         -- for the worker itself, we must allocate it directly.
222     emitBc (mkProtoBCO (getName id) (toOL [PACK data_con 0, ENTER])
223                        (Right rhs) 0 0 [{-no bitmap-}] False{-not alts-})
224
225   | otherwise
226   = schemeR [{- No free variables -}] (id, rhs)
227
228 -- -----------------------------------------------------------------------------
229 -- schemeR
230
231 -- Compile code for a right-hand side, to give a BCO that,
232 -- when executed with the free variables and arguments on top of the stack,
233 -- will return with a pointer to the result on top of the stack, after
234 -- removing the free variables and arguments.
235 --
236 -- Park the resulting BCO in the monad.  Also requires the
237 -- variable to which this value was bound, so as to give the
238 -- resulting BCO a name. 
239
240 schemeR :: [Id]                 -- Free vars of the RHS, ordered as they
241                                 -- will appear in the thunk.  Empty for
242                                 -- top-level things, which have no free vars.
243         -> (Id, AnnExpr Id VarSet)
244         -> BcM (ProtoBCO Name)
245 schemeR fvs (nm, rhs) 
246 {-
247    | trace (showSDoc (
248               (char ' '
249                $$ (ppr.filter (not.isTyVar).varSetElems.fst) rhs
250                $$ pprCoreExpr (deAnnotate rhs)
251                $$ char ' '
252               ))) False
253    = undefined
254    | otherwise
255 -}
256    = schemeR_wrk fvs nm rhs (collect [] rhs)
257
258 collect xs (_, AnnNote note e) = collect xs e
259 collect xs (_, AnnLam x e)     = collect (if isTyVar x then xs else (x:xs)) e
260 collect xs (_, not_lambda)     = (reverse xs, not_lambda)
261
262 schemeR_wrk fvs nm original_body (args, body)
263    = let 
264          all_args  = reverse args ++ fvs
265          arity     = length all_args
266          -- all_args are the args in reverse order.  We're compiling a function
267          -- \fv1..fvn x1..xn -> e 
268          -- i.e. the fvs come first
269
270          szsw_args = map idSizeW all_args
271          szw_args  = sum szsw_args
272          p_init    = listToFM (zip all_args (mkStackOffsets 0 szsw_args))
273
274          -- make the arg bitmap
275          bits = argBits (reverse (map idPrimRep all_args))
276          bitmap_size = length bits
277          bitmap = mkBitmap bits
278      in
279      schemeE szw_args 0 p_init body             `thenBc` \ body_code ->
280      emitBc (mkProtoBCO (getName nm) body_code (Right original_body)
281                 arity bitmap_size bitmap False{-not alts-})
282
283
284 fvsToEnv :: BCEnv -> VarSet -> [Id]
285 -- Takes the free variables of a right-hand side, and
286 -- delivers an ordered list of the local variables that will
287 -- be captured in the thunk for the RHS
288 -- The BCEnv argument tells which variables are in the local
289 -- environment: these are the ones that should be captured
290 --
291 -- The code that constructs the thunk, and the code that executes
292 -- it, have to agree about this layout
293 fvsToEnv p fvs = [v | v <- varSetElems fvs, 
294                       isId v,           -- Could be a type variable
295                       v `elemFM` p]
296
297 -- -----------------------------------------------------------------------------
298 -- schemeE
299
300 -- Compile code to apply the given expression to the remaining args
301 -- on the stack, returning a HNF.
302 schemeE :: Int -> Sequel -> BCEnv -> AnnExpr' Id VarSet -> BcM BCInstrList
303
304 -- Delegate tail-calls to schemeT.
305 schemeE d s p e@(AnnApp f a) 
306    = schemeT d s p e
307
308 schemeE d s p e@(AnnVar v)
309    | not (isUnLiftedType v_type)
310    =  -- Lifted-type thing; push it in the normal way
311      schemeT d s p e
312
313    | otherwise
314    = -- Returning an unlifted value.  
315      -- Heave it on the stack, SLIDE, and RETURN.
316      pushAtom d p (AnnVar v)    `thenBc` \ (push, szw) ->
317      returnBc (push                     -- value onto stack
318                `appOL`  mkSLIDE szw (d-s)       -- clear to sequel
319                `snocOL` RETURN_UBX v_rep)       -- go
320    where
321       v_type = idType v
322       v_rep = typePrimRep v_type
323
324 schemeE d s p (AnnLit literal)
325    = pushAtom d p (AnnLit literal)      `thenBc` \ (push, szw) ->
326      let l_rep = literalPrimRep literal
327      in  returnBc (push                         -- value onto stack
328                    `appOL`  mkSLIDE szw (d-s)   -- clear to sequel
329                    `snocOL` RETURN_UBX l_rep)   -- go
330
331
332 schemeE d s p (AnnLet (AnnNonRec x (_,rhs)) (_,body))
333    | (AnnVar v, args_r_to_l) <- splitApp rhs,
334      Just data_con <- isDataConWorkId_maybe v,
335      dataConRepArity data_con == length args_r_to_l
336    =    -- Special case for a non-recursive let whose RHS is a 
337         -- saturatred constructor application.
338         -- Just allocate the constructor and carry on
339      mkConAppCode d s p data_con args_r_to_l    `thenBc` \ alloc_code ->
340      schemeE (d+1) s (addToFM p x d) body       `thenBc` \ body_code ->
341      returnBc (alloc_code `appOL` body_code)
342
343 -- General case for let.  Generates correct, if inefficient, code in
344 -- all situations.
345 schemeE d s p (AnnLet binds (_,body))
346    = let (xs,rhss) = case binds of AnnNonRec x rhs  -> ([x],[rhs])
347                                    AnnRec xs_n_rhss -> unzip xs_n_rhss
348          n_binds = length xs
349
350          fvss  = map (fvsToEnv p' . fst) rhss
351
352          -- Sizes of free vars
353          sizes = map (\rhs_fvs -> sum (map idSizeW rhs_fvs)) fvss
354
355          -- the arity of each rhs
356          arities = map (length . fst . collect []) rhss
357
358          -- This p', d' defn is safe because all the items being pushed
359          -- are ptrs, so all have size 1.  d' and p' reflect the stack
360          -- after the closures have been allocated in the heap (but not
361          -- filled in), and pointers to them parked on the stack.
362          p'    = addListToFM p (zipE xs (mkStackOffsets d (nOfThem n_binds 1)))
363          d'    = d + n_binds
364          zipE  = zipEqual "schemeE"
365
366          -- ToDo: don't build thunks for things with no free variables
367          build_thunk dd [] size bco off
368             = returnBc (PUSH_BCO bco
369                         `consOL` unitOL (MKAP (off+size) size))
370          build_thunk dd (fv:fvs) size bco off = do
371               (push_code, pushed_szw) <- pushAtom dd p' (AnnVar fv) 
372               more_push_code <- build_thunk (dd+pushed_szw) fvs size bco off
373               returnBc (push_code `appOL` more_push_code)
374
375          alloc_code = toOL (zipWith mkAlloc sizes arities)
376            where mkAlloc sz 0     = ALLOC_AP sz
377                  mkAlloc sz arity = ALLOC_PAP arity sz
378
379          compile_bind d' fvs x rhs size off = do
380                 bco <- schemeR fvs (x,rhs)
381                 build_thunk d' fvs size bco off
382
383          compile_binds = 
384             [ compile_bind d' fvs x rhs size n
385             | (fvs, x, rhs, size, n) <- 
386                 zip5 fvss xs rhss sizes [n_binds, n_binds-1 .. 1]
387             ]
388      in do
389      body_code <- schemeE d' s p' body
390      thunk_codes <- sequence compile_binds
391      returnBc (alloc_code `appOL` concatOL thunk_codes `appOL` body_code)
392
393
394
395 schemeE d s p (AnnCase scrut bndr [(DataAlt dc, [bind1, bind2], rhs)])
396    | isUnboxedTupleCon dc && VoidRep == typePrimRep (idType bind1)
397         -- Convert 
398         --      case .... of x { (# VoidRep'd-thing, a #) -> ... }
399         -- to
400         --      case .... of a { DEFAULT -> ... }
401         -- becuse the return convention for both are identical.
402         --
403         -- Note that it does not matter losing the void-rep thing from the
404         -- envt (it won't be bound now) because we never look such things up.
405
406    = --trace "automagic mashing of case alts (# VoidRep, a #)" $
407      doCase d s p scrut bind2 [(DEFAULT, [], rhs)] True{-unboxed tuple-}
408
409    | isUnboxedTupleCon dc && VoidRep == typePrimRep (idType bind2)
410    = --trace "automagic mashing of case alts (# a, VoidRep #)" $
411      doCase d s p scrut bind1 [(DEFAULT, [], rhs)] True{-unboxed tuple-}
412
413 schemeE d s p (AnnCase scrut bndr [(DataAlt dc, [bind1], rhs)])
414    | isUnboxedTupleCon dc
415         -- Similarly, convert
416         --      case .... of x { (# a #) -> ... }
417         -- to
418         --      case .... of a { DEFAULT -> ... }
419    = --trace "automagic mashing of case alts (# a #)"  $
420      doCase d s p scrut bind1 [(DEFAULT, [], rhs)] True{-unboxed tuple-}
421
422 schemeE d s p (AnnCase scrut bndr alts)
423    = doCase d s p scrut bndr alts False{-not an unboxed tuple-}
424
425 schemeE d s p (AnnNote note (_, body))
426    = schemeE d s p body
427
428 schemeE d s p other
429    = pprPanic "ByteCodeGen.schemeE: unhandled case" 
430                (pprCoreExpr (deAnnotate' other))
431
432
433 -- Compile code to do a tail call.  Specifically, push the fn,
434 -- slide the on-stack app back down to the sequel depth,
435 -- and enter.  Four cases:
436 --
437 -- 0.  (Nasty hack).
438 --     An application "GHC.Prim.tagToEnum# <type> unboxed-int".
439 --     The int will be on the stack.  Generate a code sequence
440 --     to convert it to the relevant constructor, SLIDE and ENTER.
441 --
442 -- 1.  The fn denotes a ccall.  Defer to generateCCall.
443 --
444 -- 2.  (Another nasty hack).  Spot (# a::VoidRep, b #) and treat
445 --     it simply as  b  -- since the representations are identical
446 --     (the VoidRep takes up zero stack space).  Also, spot
447 --     (# b #) and treat it as  b.
448 --
449 -- 3.  Application of a constructor, by defn saturated.
450 --     Split the args into ptrs and non-ptrs, and push the nonptrs, 
451 --     then the ptrs, and then do PACK and RETURN.
452 --
453 -- 4.  Otherwise, it must be a function call.  Push the args
454 --     right to left, SLIDE and ENTER.
455
456 schemeT :: Int          -- Stack depth
457         -> Sequel       -- Sequel depth
458         -> BCEnv        -- stack env
459         -> AnnExpr' Id VarSet 
460         -> BcM BCInstrList
461
462 schemeT d s p app
463
464 --   | trace ("schemeT: env in = \n" ++ showSDocDebug (ppBCEnv p)) False
465 --   = panic "schemeT ?!?!"
466
467 --   | trace ("\nschemeT\n" ++ showSDoc (pprCoreExpr (deAnnotate' app)) ++ "\n") False
468 --   = error "?!?!" 
469
470    -- Case 0
471    | Just (arg, constr_names) <- maybe_is_tagToEnum_call
472    = pushAtom d p arg                   `thenBc` \ (push, arg_words) ->
473      implement_tagToId constr_names     `thenBc` \ tagToId_sequence ->
474      returnBc (push `appOL`  tagToId_sequence            
475                     `appOL`  mkSLIDE 1 (d+arg_words-s)
476                     `snocOL` ENTER)
477
478    -- Case 1
479    | Just (CCall ccall_spec) <- isFCallId_maybe fn
480    = generateCCall d s p ccall_spec fn args_r_to_l
481
482    -- Case 2: Constructor application
483    | Just con <- maybe_saturated_dcon,
484      isUnboxedTupleCon con
485    = case args_r_to_l of
486         [arg1,arg2] | isVoidRepAtom arg1 -> 
487                   unboxedTupleReturn d s p arg2
488         [arg1,arg2] | isVoidRepAtom arg2 -> 
489                   unboxedTupleReturn d s p arg1
490         _other -> unboxedTupleException
491
492    -- Case 3: Ordinary data constructor
493    | Just con <- maybe_saturated_dcon
494    = mkConAppCode d s p con args_r_to_l `thenBc` \ alloc_con ->
495      returnBc (alloc_con         `appOL` 
496                mkSLIDE 1 (d - s) `snocOL`
497                ENTER)
498
499    -- Case 4: Tail call of function 
500    | otherwise
501    = doTailCall d s p fn args_r_to_l
502
503    where
504       -- Detect and extract relevant info for the tagToEnum kludge.
505       maybe_is_tagToEnum_call
506          = let extract_constr_Names ty
507                  | Just (tyc, []) <- splitTyConApp_maybe (repType ty),
508                    isDataTyCon tyc
509                    = map (getName . dataConWorkId) (tyConDataCons tyc)
510                    -- NOTE: use the worker name, not the source name of
511                    -- the DataCon.  See DataCon.lhs for details.
512                  | otherwise
513                    = panic "maybe_is_tagToEnum_call.extract_constr_Ids"
514            in
515            case app of
516               (AnnApp (_, AnnApp (_, AnnVar v) (_, AnnType t)) arg)
517                  -> case isPrimOpId_maybe v of
518                        Just TagToEnumOp -> Just (snd arg, extract_constr_Names t)
519                        other            -> Nothing
520               other -> Nothing
521
522         -- Extract the args (R->L) and fn
523         -- The function will necessarily be a variable, 
524         -- because we are compiling a tail call
525       (AnnVar fn, args_r_to_l) = splitApp app
526
527       -- Only consider this to be a constructor application iff it is
528       -- saturated.  Otherwise, we'll call the constructor wrapper.
529       n_args = length args_r_to_l
530       maybe_saturated_dcon  
531         = case isDataConWorkId_maybe fn of
532                 Just con | dataConRepArity con == n_args -> Just con
533                 _ -> Nothing
534
535 -- -----------------------------------------------------------------------------
536 -- Generate code to build a constructor application, 
537 -- leaving it on top of the stack
538
539 mkConAppCode :: Int -> Sequel -> BCEnv
540              -> DataCon                 -- The data constructor
541              -> [AnnExpr' Id VarSet]    -- Args, in *reverse* order
542              -> BcM BCInstrList
543
544 mkConAppCode orig_d s p con []  -- Nullary constructor
545   = ASSERT( isNullaryDataCon con )
546     returnBc (unitOL (PUSH_G (getName (dataConWorkId con))))
547         -- Instead of doing a PACK, which would allocate a fresh
548         -- copy of this constructor, use the single shared version.
549
550 mkConAppCode orig_d s p con args_r_to_l 
551   = ASSERT( dataConRepArity con == length args_r_to_l )
552     do_pushery orig_d (non_ptr_args ++ ptr_args)
553  where
554         -- The args are already in reverse order, which is the way PACK
555         -- expects them to be.  We must push the non-ptrs after the ptrs.
556       (ptr_args, non_ptr_args) = partition isPtrAtom args_r_to_l
557
558       do_pushery d (arg:args)
559          = pushAtom d p arg                     `thenBc` \ (push, arg_words) ->
560            do_pushery (d+arg_words) args        `thenBc` \ more_push_code ->
561            returnBc (push `appOL` more_push_code)
562       do_pushery d []
563          = returnBc (unitOL (PACK con n_arg_words))
564          where
565            n_arg_words = d - orig_d
566
567
568 -- -----------------------------------------------------------------------------
569 -- Returning an unboxed tuple with one non-void component (the only
570 -- case we can handle).
571 --
572 -- Remember, we don't want to *evaluate* the component that is being
573 -- returned, even if it is a pointed type.  We always just return.
574
575 unboxedTupleReturn
576         :: Int -> Sequel -> BCEnv
577         -> AnnExpr' Id VarSet -> BcM BCInstrList
578 unboxedTupleReturn d s p arg = do
579   (push, sz) <- pushAtom d p arg
580   returnBc (push `appOL`
581             mkSLIDE sz (d-s) `snocOL`
582             RETURN_UBX (atomRep arg))
583
584 -- -----------------------------------------------------------------------------
585 -- Generate code for a tail-call
586
587 doTailCall
588         :: Int -> Sequel -> BCEnv
589         -> Id -> [AnnExpr' Id VarSet]
590         -> BcM BCInstrList
591 doTailCall init_d s p fn args
592   = do_pushes init_d args (map (primRepToArgRep.atomRep) args)
593   where
594   do_pushes d [] reps = do
595         ASSERTM( null reps )
596         (push_fn, sz) <- pushAtom d p (AnnVar fn)
597         ASSERTM( sz == 1 )
598         returnBc (push_fn `appOL` (
599                   mkSLIDE ((d-init_d) + 1) (init_d - s) `appOL`
600                   unitOL ENTER))
601   do_pushes d args reps = do
602       let (push_apply, n, rest_of_reps) = findPushSeq reps
603           (these_args, rest_of_args) = splitAt n args
604       (next_d, push_code) <- push_seq d these_args
605       instrs <- do_pushes (next_d + 1) rest_of_args rest_of_reps 
606                 --                ^^^ for the PUSH_APPLY_ instruction
607       returnBc (push_code `appOL` (push_apply `consOL` instrs))
608
609   push_seq d [] = return (d, nilOL)
610   push_seq d (arg:args) = do
611     (push_code, sz) <- pushAtom d p arg 
612     (final_d, more_push_code) <- push_seq (d+sz) args
613     return (final_d, push_code `appOL` more_push_code)
614
615 -- v. similar to CgStackery.findMatch, ToDo: merge
616 findPushSeq (RepP: RepP: RepP: RepP: RepP: RepP: RepP: rest)
617   = (PUSH_APPLY_PPPPPPP, 7, rest)
618 findPushSeq (RepP: RepP: RepP: RepP: RepP: RepP: rest)
619   = (PUSH_APPLY_PPPPPP, 6, rest)
620 findPushSeq (RepP: RepP: RepP: RepP: RepP: rest)
621   = (PUSH_APPLY_PPPPP, 5, rest)
622 findPushSeq (RepP: RepP: RepP: RepP: rest)
623   = (PUSH_APPLY_PPPP, 4, rest)
624 findPushSeq (RepP: RepP: RepP: rest)
625   = (PUSH_APPLY_PPP, 3, rest)
626 findPushSeq (RepP: RepP: rest)
627   = (PUSH_APPLY_PP, 2, rest)
628 findPushSeq (RepP: rest)
629   = (PUSH_APPLY_P, 1, rest)
630 findPushSeq (RepV: rest)
631   = (PUSH_APPLY_V, 1, rest)
632 findPushSeq (RepN: rest)
633   = (PUSH_APPLY_N, 1, rest)
634 findPushSeq (RepF: rest)
635   = (PUSH_APPLY_F, 1, rest)
636 findPushSeq (RepD: rest)
637   = (PUSH_APPLY_D, 1, rest)
638 findPushSeq (RepL: rest)
639   = (PUSH_APPLY_L, 1, rest)
640 findPushSeq _
641   = panic "ByteCodeGen.findPushSeq"
642
643 -- -----------------------------------------------------------------------------
644 -- Case expressions
645
646 doCase  :: Int -> Sequel -> BCEnv
647         -> AnnExpr Id VarSet -> Id -> [AnnAlt Id VarSet]
648         -> Bool  -- True <=> is an unboxed tuple case, don't enter the result
649         -> BcM BCInstrList
650 doCase d s p (_,scrut)
651  bndr alts is_unboxed_tuple
652   = let
653         -- Top of stack is the return itbl, as usual.
654         -- underneath it is the pointer to the alt_code BCO.
655         -- When an alt is entered, it assumes the returned value is
656         -- on top of the itbl.
657         ret_frame_sizeW = 2
658
659         -- An unlifted value gets an extra info table pushed on top
660         -- when it is returned.
661         unlifted_itbl_sizeW | isAlgCase = 0
662                             | otherwise = 1
663
664         -- depth of stack after the return value has been pushed
665         d_bndr = d + ret_frame_sizeW + idSizeW bndr
666
667         -- depth of stack after the extra info table for an unboxed return
668         -- has been pushed, if any.  This is the stack depth at the
669         -- continuation.
670         d_alts = d_bndr + unlifted_itbl_sizeW
671
672         -- Env in which to compile the alts, not including
673         -- any vars bound by the alts themselves
674         p_alts = addToFM p bndr (d_bndr - 1)
675
676         bndr_ty = idType bndr
677         isAlgCase = not (isUnLiftedType bndr_ty) && not is_unboxed_tuple
678
679         -- given an alt, return a discr and code for it.
680         codeALt alt@(DEFAULT, _, (_,rhs))
681            = schemeE d_alts s p_alts rhs        `thenBc` \ rhs_code ->
682              returnBc (NoDiscr, rhs_code)
683         codeAlt alt@(discr, bndrs, (_,rhs))
684            -- primitive or nullary constructor alt: no need to UNPACK
685            | null real_bndrs = do
686                 rhs_code <- schemeE d_alts s p_alts rhs
687                 returnBc (my_discr alt, rhs_code)
688            -- algebraic alt with some binders
689            | ASSERT(isAlgCase) otherwise =
690              let
691                  (ptrs,nptrs) = partition (isFollowableRep.idPrimRep) real_bndrs
692                  ptr_sizes    = map idSizeW ptrs
693                  nptrs_sizes  = map idSizeW nptrs
694                  bind_sizes   = ptr_sizes ++ nptrs_sizes
695                  size         = sum ptr_sizes + sum nptrs_sizes
696                  -- the UNPACK instruction unpacks in reverse order...
697                  p' = addListToFM p_alts 
698                         (zip (reverse (ptrs ++ nptrs))
699                           (mkStackOffsets d_alts (reverse bind_sizes)))
700              in do
701              rhs_code <- schemeE (d_alts+size) s p' rhs
702              return (my_discr alt, unitOL (UNPACK size) `appOL` rhs_code)
703            where
704              real_bndrs = filter (not.isTyVar) bndrs
705
706
707         my_discr (DEFAULT, binds, rhs) = NoDiscr {-shouldn't really happen-}
708         my_discr (DataAlt dc, binds, rhs) 
709            | isUnboxedTupleCon dc
710            = unboxedTupleException
711            | otherwise
712            = DiscrP (dataConTag dc - fIRST_TAG)
713         my_discr (LitAlt l, binds, rhs)
714            = case l of MachInt i     -> DiscrI (fromInteger i)
715                        MachFloat r   -> DiscrF (fromRational r)
716                        MachDouble r  -> DiscrD (fromRational r)
717                        MachChar i    -> DiscrI (ord i)
718                        _ -> pprPanic "schemeE(AnnCase).my_discr" (ppr l)
719
720         maybe_ncons 
721            | not isAlgCase = Nothing
722            | otherwise 
723            = case [dc | (DataAlt dc, _, _) <- alts] of
724                 []     -> Nothing
725                 (dc:_) -> Just (tyConFamilySize (dataConTyCon dc))
726
727         -- the bitmap is relative to stack depth d, i.e. before the
728         -- BCO, info table and return value are pushed on.
729         -- This bit of code is v. similar to buildLivenessMask in CgBindery,
730         -- except that here we build the bitmap from the known bindings of
731         -- things that are pointers, whereas in CgBindery the code builds the
732         -- bitmap from the free slots and unboxed bindings.
733         -- (ToDo: merge?)
734         bitmap = intsToReverseBitmap d{-size-} (sortLt (<) rel_slots)
735           where
736           binds = fmToList p
737           rel_slots = concat (map spread binds)
738           spread (id, offset)
739                 | isFollowableRep (idPrimRep id) = [ rel_offset ]
740                 | otherwise = []
741                 where rel_offset = d - offset - 1
742
743      in do
744      alt_stuff <- mapM codeAlt alts
745      alt_final <- mkMultiBranch maybe_ncons alt_stuff
746      let 
747          alt_bco_name = getName bndr
748          alt_bco = mkProtoBCO alt_bco_name alt_final (Left alts)
749                         0{-no arity-} d{-bitmap size-} bitmap True{-is alts-}
750      -- in
751 --     trace ("case: bndr = " ++ showSDocDebug (ppr bndr) ++ "\ndepth = " ++ show d ++ "\nenv = \n" ++ showSDocDebug (ppBCEnv p) ++
752 --           "\n      bitmap = " ++ show bitmap) $ do
753      scrut_code <- schemeE (d + ret_frame_sizeW) (d + ret_frame_sizeW) p scrut
754      alt_bco' <- emitBc alt_bco
755      let push_alts
756             | isAlgCase = PUSH_ALTS alt_bco'
757             | otherwise = PUSH_ALTS_UNLIFTED alt_bco' (typePrimRep bndr_ty)
758      returnBc (push_alts `consOL` scrut_code)
759
760
761 -- -----------------------------------------------------------------------------
762 -- Deal with a CCall.
763
764 -- Taggedly push the args onto the stack R->L,
765 -- deferencing ForeignObj#s and adjusting addrs to point to
766 -- payloads in Ptr/Byte arrays.  Then, generate the marshalling
767 -- (machine) code for the ccall, and create bytecodes to call that and
768 -- then return in the right way.  
769
770 generateCCall :: Int -> Sequel          -- stack and sequel depths
771               -> BCEnv
772               -> CCallSpec              -- where to call
773               -> Id                     -- of target, for type info
774               -> [AnnExpr' Id VarSet]   -- args (atoms)
775               -> BcM BCInstrList
776
777 generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
778    = let 
779          -- useful constants
780          addr_sizeW = getPrimRepSize AddrRep
781
782          -- Get the args on the stack, with tags and suitably
783          -- dereferenced for the CCall.  For each arg, return the
784          -- depth to the first word of the bits for that arg, and the
785          -- PrimRep of what was actually pushed.
786
787          pargs d [] = returnBc []
788          pargs d (a:az) 
789             = let arg_ty = repType (exprType (deAnnotate' a))
790
791               in case splitTyConApp_maybe arg_ty of
792                     -- Don't push the FO; instead push the Addr# it
793                     -- contains.
794                     Just (t, _)
795                      | t == arrayPrimTyCon || t == mutableArrayPrimTyCon
796                        -> pargs (d + addr_sizeW) az     `thenBc` \ rest ->
797                           parg_ArrayishRep arrPtrsHdrSize d p a
798                                                         `thenBc` \ code ->
799                           returnBc ((code,AddrRep):rest)
800
801                      | t == byteArrayPrimTyCon || t == mutableByteArrayPrimTyCon
802                        -> pargs (d + addr_sizeW) az     `thenBc` \ rest ->
803                           parg_ArrayishRep arrWordsHdrSize d p a
804                                                         `thenBc` \ code ->
805                           returnBc ((code,AddrRep):rest)
806
807                     -- Default case: push taggedly, but otherwise intact.
808                     other
809                        -> pushAtom d p a                `thenBc` \ (code_a, sz_a) ->
810                           pargs (d+sz_a) az             `thenBc` \ rest ->
811                           returnBc ((code_a, atomRep a) : rest)
812
813          -- Do magic for Ptr/Byte arrays.  Push a ptr to the array on
814          -- the stack but then advance it over the headers, so as to
815          -- point to the payload.
816          parg_ArrayishRep hdrSizeW d p a
817             = pushAtom d p a `thenBc` \ (push_fo, _) ->
818               -- The ptr points at the header.  Advance it over the
819               -- header and then pretend this is an Addr#.
820               returnBc (push_fo `snocOL` 
821                         SWIZZLE 0 (hdrSizeW * getPrimRepSize WordRep
822                                             * wORD_SIZE))
823
824      in
825          pargs d0 args_r_to_l                   `thenBc` \ code_n_reps ->
826      let
827          (pushs_arg, a_reps_pushed_r_to_l) = unzip code_n_reps
828
829          push_args    = concatOL pushs_arg
830          d_after_args = d0 + sum (map getPrimRepSize a_reps_pushed_r_to_l)
831          a_reps_pushed_RAW
832             | null a_reps_pushed_r_to_l || head a_reps_pushed_r_to_l /= VoidRep
833             = panic "ByteCodeGen.generateCCall: missing or invalid World token?"
834             | otherwise
835             = reverse (tail a_reps_pushed_r_to_l)
836
837          -- Now: a_reps_pushed_RAW are the reps which are actually on the stack.
838          -- push_args is the code to do that.
839          -- d_after_args is the stack depth once the args are on.
840
841          -- Get the result rep.
842          (returns_void, r_rep)
843             = case maybe_getCCallReturnRep (idType fn) of
844                  Nothing -> (True,  VoidRep)
845                  Just rr -> (False, rr) 
846          {-
847          Because the Haskell stack grows down, the a_reps refer to 
848          lowest to highest addresses in that order.  The args for the call
849          are on the stack.  Now push an unboxed Addr# indicating
850          the C function to call.  Then push a dummy placeholder for the 
851          result.  Finally, emit a CCALL insn with an offset pointing to the 
852          Addr# just pushed, and a literal field holding the mallocville
853          address of the piece of marshalling code we generate.
854          So, just prior to the CCALL insn, the stack looks like this 
855          (growing down, as usual):
856                  
857             <arg_n>
858             ...
859             <arg_1>
860             Addr# address_of_C_fn
861             <placeholder-for-result#> (must be an unboxed type)
862
863          The interpreter then calls the marshall code mentioned
864          in the CCALL insn, passing it (& <placeholder-for-result#>), 
865          that is, the addr of the topmost word in the stack.
866          When this returns, the placeholder will have been
867          filled in.  The placeholder is slid down to the sequel
868          depth, and we RETURN.
869
870          This arrangement makes it simple to do f-i-dynamic since the Addr#
871          value is the first arg anyway.
872
873          The marshalling code is generated specifically for this
874          call site, and so knows exactly the (Haskell) stack
875          offsets of the args, fn address and placeholder.  It
876          copies the args to the C stack, calls the stacked addr,
877          and parks the result back in the placeholder.  The interpreter
878          calls it as a normal C call, assuming it has a signature
879             void marshall_code ( StgWord* ptr_to_top_of_stack )
880          -}
881          -- resolve static address
882          get_target_info
883             = case target of
884                  DynamicTarget
885                     -> returnBc (False, panic "ByteCodeGen.generateCCall(dyn)")
886                  StaticTarget target
887                     -> ioToBc (lookupStaticPtr target) `thenBc` \res ->
888                        returnBc (True, res)
889      in
890          get_target_info        `thenBc` \ (is_static, static_target_addr) ->
891      let
892
893          -- Get the arg reps, zapping the leading Addr# in the dynamic case
894          a_reps -- | trace (showSDoc (ppr a_reps_pushed_RAW)) False = error "???"
895                 | is_static = a_reps_pushed_RAW
896                 | otherwise = if null a_reps_pushed_RAW 
897                               then panic "ByteCodeGen.generateCCall: dyn with no args"
898                               else tail a_reps_pushed_RAW
899
900          -- push the Addr#
901          (push_Addr, d_after_Addr)
902             | is_static
903             = (toOL [PUSH_UBX (Right static_target_addr) addr_sizeW],
904                d_after_args + addr_sizeW)
905             | otherwise -- is already on the stack
906             = (nilOL, d_after_args)
907
908          -- Push the return placeholder.  For a call returning nothing,
909          -- this is a VoidRep (tag).
910          r_sizeW   = getPrimRepSize r_rep
911          d_after_r = d_after_Addr + r_sizeW
912          r_lit     = mkDummyLiteral r_rep
913          push_r    = (if   returns_void 
914                       then nilOL 
915                       else unitOL (PUSH_UBX (Left r_lit) r_sizeW))
916
917          -- generate the marshalling code we're going to call
918          r_offW       = 0 
919          addr_offW    = r_sizeW
920          arg1_offW    = r_sizeW + addr_sizeW
921          args_offW    = map (arg1_offW +) 
922                             (init (scanl (+) 0 (map getPrimRepSize a_reps)))
923      in
924          ioToBc (mkMarshalCode cconv
925                     (r_offW, r_rep) addr_offW
926                     (zip args_offW a_reps))     `thenBc` \ addr_of_marshaller ->
927          recordMallocBc addr_of_marshaller      `thenBc_`
928      let
929          -- Offset of the next stack frame down the stack.  The CCALL
930          -- instruction needs to describe the chunk of stack containing
931          -- the ccall args to the GC, so it needs to know how large it
932          -- is.  See comment in Interpreter.c with the CCALL instruction.
933          stk_offset   = d_after_r - s
934
935          -- do the call
936          do_call      = unitOL (CCALL stk_offset (castPtr addr_of_marshaller))
937          -- slide and return
938          wrapup       = mkSLIDE r_sizeW (d_after_r - r_sizeW - s)
939                         `snocOL` RETURN_UBX r_rep
940      in
941          --trace (show (arg1_offW, args_offW  ,  (map getPrimRepSize a_reps) )) $
942          returnBc (
943          push_args `appOL`
944          push_Addr `appOL` push_r `appOL` do_call `appOL` wrapup
945          )
946
947
948 -- Make a dummy literal, to be used as a placeholder for FFI return
949 -- values on the stack.
950 mkDummyLiteral :: PrimRep -> Literal
951 mkDummyLiteral pr
952    = case pr of
953         CharRep   -> MachChar (chr 0)
954         IntRep    -> MachInt 0
955         WordRep   -> MachWord 0
956         DoubleRep -> MachDouble 0
957         FloatRep  -> MachFloat 0
958         AddrRep   | getPrimRepSize AddrRep == getPrimRepSize WordRep -> MachWord 0
959         _         -> moan64 "mkDummyLiteral" (ppr pr)
960
961
962 -- Convert (eg) 
963 --     GHC.Prim.Char# -> GHC.Prim.State# GHC.Prim.RealWorld
964 --                   -> (# GHC.Prim.State# GHC.Prim.RealWorld, GHC.Prim.Int# #)
965 --
966 -- to  Just IntRep
967 -- and check that an unboxed pair is returned wherein the first arg is VoidRep'd.
968 --
969 -- Alternatively, for call-targets returning nothing, convert
970 --
971 --     GHC.Prim.Char# -> GHC.Prim.State# GHC.Prim.RealWorld
972 --                   -> (# GHC.Prim.State# GHC.Prim.RealWorld #)
973 --
974 -- to  Nothing
975
976 maybe_getCCallReturnRep :: Type -> Maybe PrimRep
977 maybe_getCCallReturnRep fn_ty
978    = let (a_tys, r_ty) = splitFunTys (dropForAlls fn_ty)
979          maybe_r_rep_to_go  
980             = if isSingleton r_reps then Nothing else Just (r_reps !! 1)
981          (r_tycon, r_reps) 
982             = case splitTyConApp_maybe (repType r_ty) of
983                       (Just (tyc, tys)) -> (tyc, map typePrimRep tys)
984                       Nothing -> blargh
985          ok = ( ( r_reps `lengthIs` 2 && VoidRep == head r_reps)
986                 || r_reps == [VoidRep] )
987               && isUnboxedTupleTyCon r_tycon
988               && case maybe_r_rep_to_go of
989                     Nothing    -> True
990                     Just r_rep -> r_rep /= PtrRep
991                                   -- if it was, it would be impossible 
992                                   -- to create a valid return value 
993                                   -- placeholder on the stack
994          blargh = pprPanic "maybe_getCCallReturn: can't handle:" 
995                            (pprType fn_ty)
996      in 
997      --trace (showSDoc (ppr (a_reps, r_reps))) $
998      if ok then maybe_r_rep_to_go else blargh
999
1000 -- Compile code which expects an unboxed Int on the top of stack,
1001 -- (call it i), and pushes the i'th closure in the supplied list 
1002 -- as a consequence.
1003 implement_tagToId :: [Name] -> BcM BCInstrList
1004 implement_tagToId names
1005    = ASSERT( notNull names )
1006      getLabelsBc (length names)                 `thenBc` \ labels ->
1007      getLabelBc                                 `thenBc` \ label_fail ->
1008      getLabelBc                                 `thenBc` \ label_exit ->
1009      zip4 labels (tail labels ++ [label_fail])
1010                  [0 ..] names                   `bind`   \ infos ->
1011      map (mkStep label_exit) infos              `bind`   \ steps ->
1012      returnBc (concatOL steps
1013                `appOL` 
1014                toOL [LABEL label_fail, CASEFAIL, LABEL label_exit])
1015      where
1016         mkStep l_exit (my_label, next_label, n, name_for_n)
1017            = toOL [LABEL my_label, 
1018                    TESTEQ_I n next_label, 
1019                    PUSH_G name_for_n, 
1020                    JMP l_exit]
1021
1022
1023 -- -----------------------------------------------------------------------------
1024 -- pushAtom
1025
1026 -- Push an atom onto the stack, returning suitable code & number of
1027 -- stack words used.
1028 --
1029 -- The env p must map each variable to the highest- numbered stack
1030 -- slot for it.  For example, if the stack has depth 4 and we
1031 -- tagged-ly push (v :: Int#) on it, the value will be in stack[4],
1032 -- the tag in stack[5], the stack will have depth 6, and p must map v
1033 -- to 5 and not to 4.  Stack locations are numbered from zero, so a
1034 -- depth 6 stack has valid words 0 .. 5.
1035
1036 pushAtom :: Int -> BCEnv -> AnnExpr' Id VarSet -> BcM (BCInstrList, Int)
1037
1038 pushAtom d p (AnnApp f (_, AnnType _))
1039    = pushAtom d p (snd f)
1040
1041 pushAtom d p (AnnNote note e)
1042    = pushAtom d p (snd e)
1043
1044 pushAtom d p (AnnLam x e) 
1045    | isTyVar x 
1046    = pushAtom d p (snd e)
1047
1048 pushAtom d p (AnnVar v)
1049
1050    | idPrimRep v == VoidRep
1051    = returnBc (nilOL, 0)
1052
1053    | isFCallId v
1054    = pprPanic "pushAtom: shouldn't get an FCallId here" (ppr v)
1055
1056    | Just primop <- isPrimOpId_maybe v
1057    = returnBc (unitOL (PUSH_PRIMOP primop), 1)
1058
1059    | Just d_v <- lookupBCEnv_maybe p v  -- v is a local variable
1060    = returnBc (toOL (nOfThem sz (PUSH_L (d-d_v+sz-2))), sz)
1061          -- d - d_v                 the number of words between the TOS 
1062          --                         and the 1st slot of the object
1063          --
1064          -- d - d_v - 1             the offset from the TOS of the 1st slot
1065          --
1066          -- d - d_v - 1 + sz - 1    the offset from the TOS of the last slot
1067          --                         of the object.
1068          --
1069          -- Having found the last slot, we proceed to copy the right number of
1070          -- slots on to the top of the stack.
1071
1072     | otherwise  -- v must be a global variable
1073     = ASSERT(sz == 1) 
1074       returnBc (unitOL (PUSH_G (getName v)), sz)
1075
1076     where
1077          sz = idSizeW v
1078
1079
1080 pushAtom d p (AnnLit lit)
1081    = case lit of
1082         MachLabel fs _ -> code CodePtrRep
1083         MachWord w     -> code WordRep
1084         MachInt i      -> code IntRep
1085         MachFloat r    -> code FloatRep
1086         MachDouble r   -> code DoubleRep
1087         MachChar c     -> code CharRep
1088         MachStr s      -> pushStr s
1089      where
1090         code rep
1091            = let size_host_words = getPrimRepSize rep
1092              in  returnBc (unitOL (PUSH_UBX (Left lit) size_host_words), 
1093                            size_host_words)
1094
1095         pushStr s 
1096            = let getMallocvilleAddr
1097                     = case s of
1098                          FastString _ l ba -> 
1099                             -- sigh, a string in the heap is no good to us.
1100                             -- We need a static C pointer, since the type of 
1101                             -- a string literal is Addr#.  So, copy the string 
1102                             -- into C land and remember the pointer so we can
1103                             -- free it later.
1104                             let n = I# l
1105                             -- CAREFUL!  Chars are 32 bits in ghc 4.09+
1106                             in  ioToBc (mallocBytes (n+1)) `thenBc` \ ptr ->
1107                                 recordMallocBc ptr         `thenBc_`
1108                                 ioToBc (
1109                                    do memcpy ptr ba (fromIntegral n)
1110                                       pokeByteOff ptr n (fromIntegral (ord '\0') :: Word8)
1111                                       return ptr
1112                                    )
1113                          other -> panic "ByteCodeGen.pushAtom.pushStr"
1114              in
1115                 getMallocvilleAddr `thenBc` \ addr ->
1116                 -- Get the addr on the stack, untaggedly
1117                    returnBc (unitOL (PUSH_UBX (Right addr) 1), 1)
1118
1119 pushAtom d p other
1120    = pprPanic "ByteCodeGen.pushAtom" 
1121               (pprCoreExpr (deAnnotate (undefined, other)))
1122
1123 foreign import ccall unsafe "memcpy"
1124  memcpy :: Ptr a -> ByteArray# -> CInt -> IO ()
1125
1126
1127 -- -----------------------------------------------------------------------------
1128 -- Given a bunch of alts code and their discrs, do the donkey work
1129 -- of making a multiway branch using a switch tree.
1130 -- What a load of hassle!
1131
1132 mkMultiBranch :: Maybe Int      -- # datacons in tycon, if alg alt
1133                                 -- a hint; generates better code
1134                                 -- Nothing is always safe
1135               -> [(Discr, BCInstrList)] 
1136               -> BcM BCInstrList
1137 mkMultiBranch maybe_ncons raw_ways
1138    = let d_way     = filter (isNoDiscr.fst) raw_ways
1139          notd_ways = naturalMergeSortLe 
1140                         (\w1 w2 -> leAlt (fst w1) (fst w2))
1141                         (filter (not.isNoDiscr.fst) raw_ways)
1142
1143          mkTree :: [(Discr, BCInstrList)] -> Discr -> Discr -> BcM BCInstrList
1144          mkTree [] range_lo range_hi = returnBc the_default
1145
1146          mkTree [val] range_lo range_hi
1147             | range_lo `eqAlt` range_hi 
1148             = returnBc (snd val)
1149             | otherwise
1150             = getLabelBc                                `thenBc` \ label_neq ->
1151               returnBc (mkTestEQ (fst val) label_neq 
1152                         `consOL` (snd val
1153                         `appOL`   unitOL (LABEL label_neq)
1154                         `appOL`   the_default))
1155
1156          mkTree vals range_lo range_hi
1157             = let n = length vals `div` 2
1158                   vals_lo = take n vals
1159                   vals_hi = drop n vals
1160                   v_mid = fst (head vals_hi)
1161               in
1162               getLabelBc                                `thenBc` \ label_geq ->
1163               mkTree vals_lo range_lo (dec v_mid)       `thenBc` \ code_lo ->
1164               mkTree vals_hi v_mid range_hi             `thenBc` \ code_hi ->
1165               returnBc (mkTestLT v_mid label_geq
1166                         `consOL` (code_lo
1167                         `appOL`   unitOL (LABEL label_geq)
1168                         `appOL`   code_hi))
1169  
1170          the_default 
1171             = case d_way of [] -> unitOL CASEFAIL
1172                             [(_, def)] -> def
1173
1174          -- None of these will be needed if there are no non-default alts
1175          (mkTestLT, mkTestEQ, init_lo, init_hi)
1176             | null notd_ways
1177             = panic "mkMultiBranch: awesome foursome"
1178             | otherwise
1179             = case fst (head notd_ways) of {
1180               DiscrI _ -> ( \(DiscrI i) fail_label -> TESTLT_I i fail_label,
1181                             \(DiscrI i) fail_label -> TESTEQ_I i fail_label,
1182                             DiscrI minBound,
1183                             DiscrI maxBound );
1184               DiscrF _ -> ( \(DiscrF f) fail_label -> TESTLT_F f fail_label,
1185                             \(DiscrF f) fail_label -> TESTEQ_F f fail_label,
1186                             DiscrF minF,
1187                             DiscrF maxF );
1188               DiscrD _ -> ( \(DiscrD d) fail_label -> TESTLT_D d fail_label,
1189                             \(DiscrD d) fail_label -> TESTEQ_D d fail_label,
1190                             DiscrD minD,
1191                             DiscrD maxD );
1192               DiscrP _ -> ( \(DiscrP i) fail_label -> TESTLT_P i fail_label,
1193                             \(DiscrP i) fail_label -> TESTEQ_P i fail_label,
1194                             DiscrP algMinBound,
1195                             DiscrP algMaxBound )
1196               }
1197
1198          (algMinBound, algMaxBound)
1199             = case maybe_ncons of
1200                  Just n  -> (0, n - 1)
1201                  Nothing -> (minBound, maxBound)
1202
1203          (DiscrI i1) `eqAlt` (DiscrI i2) = i1 == i2
1204          (DiscrF f1) `eqAlt` (DiscrF f2) = f1 == f2
1205          (DiscrD d1) `eqAlt` (DiscrD d2) = d1 == d2
1206          (DiscrP i1) `eqAlt` (DiscrP i2) = i1 == i2
1207          NoDiscr     `eqAlt` NoDiscr     = True
1208          _           `eqAlt` _           = False
1209
1210          (DiscrI i1) `leAlt` (DiscrI i2) = i1 <= i2
1211          (DiscrF f1) `leAlt` (DiscrF f2) = f1 <= f2
1212          (DiscrD d1) `leAlt` (DiscrD d2) = d1 <= d2
1213          (DiscrP i1) `leAlt` (DiscrP i2) = i1 <= i2
1214          NoDiscr     `leAlt` NoDiscr     = True
1215          _           `leAlt` _           = False
1216
1217          isNoDiscr NoDiscr = True
1218          isNoDiscr _       = False
1219
1220          dec (DiscrI i) = DiscrI (i-1)
1221          dec (DiscrP i) = DiscrP (i-1)
1222          dec other      = other         -- not really right, but if you
1223                 -- do cases on floating values, you'll get what you deserve
1224
1225          -- same snotty comment applies to the following
1226          minF, maxF :: Float
1227          minD, maxD :: Double
1228          minF = -1.0e37
1229          maxF =  1.0e37
1230          minD = -1.0e308
1231          maxD =  1.0e308
1232      in
1233          mkTree notd_ways init_lo init_hi
1234
1235
1236 -- -----------------------------------------------------------------------------
1237 -- Supporting junk for the compilation schemes
1238
1239 -- Describes case alts
1240 data Discr 
1241    = DiscrI Int
1242    | DiscrF Float
1243    | DiscrD Double
1244    | DiscrP Int
1245    | NoDiscr
1246
1247 instance Outputable Discr where
1248    ppr (DiscrI i) = int i
1249    ppr (DiscrF f) = text (show f)
1250    ppr (DiscrD d) = text (show d)
1251    ppr (DiscrP i) = int i
1252    ppr NoDiscr    = text "DEF"
1253
1254
1255 lookupBCEnv_maybe :: BCEnv -> Id -> Maybe Int
1256 lookupBCEnv_maybe = lookupFM
1257
1258 idSizeW :: Id -> Int
1259 idSizeW id = getPrimRepSize (typePrimRep (idType id))
1260
1261 unboxedTupleException :: a
1262 unboxedTupleException 
1263    = throwDyn 
1264         (Panic 
1265            ("Bytecode generator can't handle unboxed tuples.  Possibly due\n" ++
1266             "\tto foreign import/export decls in source.  Workaround:\n" ++
1267             "\tcompile this module to a .o file, then restart session."))
1268
1269
1270 mkSLIDE n d = if d == 0 then nilOL else unitOL (SLIDE n d)
1271 bind x f    = f x
1272
1273 splitApp :: AnnExpr' id ann -> (AnnExpr' id ann, [AnnExpr' id ann])
1274         -- The arguments are returned in *right-to-left* order
1275 splitApp (AnnApp (_,f) (_,a))
1276                | isTypeAtom a = splitApp f
1277                | otherwise    = case splitApp f of 
1278                                      (f', as) -> (f', a:as)
1279 splitApp (AnnNote n (_,e))    = splitApp e
1280 splitApp e                    = (e, [])
1281
1282
1283 isTypeAtom :: AnnExpr' id ann -> Bool
1284 isTypeAtom (AnnType _) = True
1285 isTypeAtom _           = False
1286
1287 isVoidRepAtom :: AnnExpr' id ann -> Bool
1288 isVoidRepAtom (AnnVar v)        = typePrimRep (idType v) == VoidRep
1289 isVoidRepAtom (AnnNote n (_,e)) = isVoidRepAtom e
1290 isVoidRepAtom _                 = False
1291
1292 atomRep :: AnnExpr' Id ann -> PrimRep
1293 atomRep (AnnVar v)    = typePrimRep (idType v)
1294 atomRep (AnnLit l)    = literalPrimRep l
1295 atomRep (AnnNote n b) = atomRep (snd b)
1296 atomRep (AnnApp f (_, AnnType _)) = atomRep (snd f)
1297 atomRep (AnnLam x e) | isTyVar x = atomRep (snd e)
1298 atomRep other = pprPanic "atomRep" (ppr (deAnnotate (undefined,other)))
1299
1300 isPtrAtom :: AnnExpr' Id ann -> Bool
1301 isPtrAtom e = isFollowableRep (atomRep e)
1302
1303 -- Let szsw be the sizes in words of some items pushed onto the stack,
1304 -- which has initial depth d'.  Return the values which the stack environment
1305 -- should map these items to.
1306 mkStackOffsets :: Int -> [Int] -> [Int]
1307 mkStackOffsets original_depth szsw
1308    = map (subtract 1) (tail (scanl (+) original_depth szsw))
1309
1310 -- -----------------------------------------------------------------------------
1311 -- The bytecode generator's monad
1312
1313 data BcM_State 
1314    = BcM_State { 
1315         nextlabel :: Int,               -- for generating local labels
1316         malloced  :: [Ptr ()] }         -- ptrs malloced for current BCO
1317                                         -- Should be free()d when it is GCd
1318
1319 newtype BcM r = BcM (BcM_State -> IO (BcM_State, r))
1320
1321 ioToBc :: IO a -> BcM a
1322 ioToBc io = BcM $ \st -> do 
1323   x <- io 
1324   return (st, x)
1325
1326 runBc :: BcM r -> IO (BcM_State, r)
1327 runBc (BcM m) = m (BcM_State 0 []) 
1328
1329 thenBc :: BcM a -> (a -> BcM b) -> BcM b
1330 thenBc (BcM expr) cont = BcM $ \st0 -> do
1331   (st1, q) <- expr st0
1332   let BcM k = cont q 
1333   (st2, r) <- k st1
1334   return (st2, r)
1335
1336 thenBc_ :: BcM a -> BcM b -> BcM b
1337 thenBc_ (BcM expr) (BcM cont) = BcM $ \st0 -> do
1338   (st1, q) <- expr st0
1339   (st2, r) <- cont st1
1340   return (st2, r)
1341
1342 returnBc :: a -> BcM a
1343 returnBc result = BcM $ \st -> (return (st, result))
1344
1345 instance Monad BcM where
1346   (>>=) = thenBc
1347   (>>)  = thenBc_
1348   return = returnBc
1349
1350 emitBc :: ([Ptr ()] -> ProtoBCO Name) -> BcM (ProtoBCO Name)
1351 emitBc bco
1352   = BcM $ \st -> return (st{malloced=[]}, bco (malloced st))
1353
1354 recordMallocBc :: Ptr a -> BcM ()
1355 recordMallocBc a
1356   = BcM $ \st -> return (st{malloced = castPtr a : malloced st}, ())
1357
1358 getLabelBc :: BcM Int
1359 getLabelBc
1360   = BcM $ \st -> return (st{nextlabel = 1 + nextlabel st}, nextlabel st)
1361
1362 getLabelsBc :: Int -> BcM [Int]
1363 getLabelsBc n
1364   = BcM $ \st -> let ctr = nextlabel st 
1365                  in return (st{nextlabel = ctr+n}, [ctr .. ctr+n-1])
1366 \end{code}