[project @ 2001-02-06 12:00:17 by sewardj]
[ghc-hetmet.git] / ghc / compiler / ghci / ByteCodeGen.lhs
index e85e20e..883416e 100644 (file)
@@ -15,7 +15,7 @@ module ByteCodeGen ( UnlinkedBCO, UnlinkedBCOExpr, ItblEnv, ClosureEnv, HValue,
 import Outputable
 import Name            ( Name, getName, mkSysLocalName )
 import Id              ( Id, idType, isDataConId_maybe, mkVanillaId,
-                         isPrimOpId_maybe )
+                         isPrimOpId_maybe, idPrimRep )
 import OrdList         ( OrdList, consOL, snocOL, appOL, unitOL, 
                          nilOL, toOL, concatOL, fromOL )
 import FiniteMap       ( FiniteMap, addListToFM, listToFM,
@@ -39,10 +39,11 @@ import ErrUtils             ( showPass, dumpIfSet_dyn )
 import Unique          ( mkPseudoUnique3 )
 import FastString      ( FastString(..) )
 import PprType         ( pprType )
-import ByteCodeInstr   ( BCInstr(..), ProtoBCO(..), nameOfProtoBCO )
+import ByteCodeInstr   ( BCInstr(..), ProtoBCO(..), nameOfProtoBCO, bciStackUse )
 import ByteCodeItbls   ( ItblEnv, mkITbls )
 import ByteCodeLink    ( UnlinkedBCO, UnlinkedBCOExpr, assembleBCO,
-                         ClosureEnv, HValue, linkSomeBCOs, filterNameMap )
+                         ClosureEnv, HValue, linkSomeBCOs, filterNameMap,
+                         iNTERP_STACK_CHECK_THRESH )
 
 import List            ( intersperse, sortBy )
 import Foreign         ( Ptr(..), mallocBytes )
@@ -129,15 +130,15 @@ linkIModules gie gce mods
    = do let (bcoss, ies) = unzip mods
             bcos = concat bcoss
             final_gie = foldr plusFM gie ies
-        (final_gce, linked_bcos) <- linkSomeBCOs final_gie gce bcos
+        (final_gce, linked_bcos) <- linkSomeBCOs True final_gie gce bcos
         return (linked_bcos, final_gie, final_gce)
 
 
 linkIExpr :: ItblEnv -> ClosureEnv -> UnlinkedBCOExpr
           -> IO HValue           -- IO BCO# really
 linkIExpr ie ce (root_ul_bco, aux_ul_bcos)
-   = do (aux_ce, _) <- linkSomeBCOs ie ce aux_ul_bcos
-        (_, [root_bco]) <- linkSomeBCOs ie aux_ce [root_ul_bco]
+   = do (aux_ce, _) <- linkSomeBCOs False ie ce aux_ul_bcos
+        (_, [root_bco]) <- linkSomeBCOs False ie aux_ce [root_ul_bco]
         return root_bco
 \end{code}
 
@@ -169,12 +170,35 @@ ppBCEnv p
 -- Create a BCO and do a spot of peephole optimisation on the insns
 -- at the same time.
 mkProtoBCO nm instrs_ordlist origin
-   = ProtoBCO nm (id {-peep-} (fromOL instrs_ordlist)) origin
+   = ProtoBCO nm maybe_with_stack_check origin
      where
+        -- Overestimate the stack usage (in words) of this BCO,
+        -- and if >= iNTERP_STACK_CHECK_THRESH, add an explicit
+        -- stack check.  (The interpreter always does a stack check
+        -- for iNTERP_STACK_CHECK_THRESH words at the start of each
+        -- BCO anyway, so we only need to add an explicit on in the
+        -- (hopefully rare) cases when the (overestimated) stack use
+        -- exceeds iNTERP_STACK_CHECK_THRESH.
+        maybe_with_stack_check
+           | stack_overest >= 65535
+           = pprPanic "mkProtoBCO: stack use won't fit in 16 bits" 
+                      (int stack_overest)
+           | stack_overest >= iNTERP_STACK_CHECK_THRESH
+           = (STKCHECK stack_overest) : peep_d
+           | otherwise
+           = peep_d    -- the supposedly common case
+             
+        stack_overest = sum (map bciStackUse peep_d)
+                        + 10 {- just to be really really sure -}
+
+
+        -- Merge local pushes
+        peep_d = peep (fromOL instrs_ordlist)
+
         peep (PUSH_L off1 : PUSH_L off2 : PUSH_L off3 : rest)
            = PUSH_LLL off1 (off2-1) (off3-2) : peep rest
         peep (PUSH_L off1 : PUSH_L off2 : rest)
-           = PUSH_LL off1 off2 : peep rest
+           = PUSH_LL off1 (off2-1) : peep rest
         peep (i:rest)
            = i : peep rest
         peep []
@@ -210,10 +234,10 @@ collect xs not_lambda
 
 schemeR_wrk is_top original_body nm (args, body)
    | Just dcon <- maybe_toplevel_null_con_rhs
-   = trace ("nullary constructor! " ++ showSDocDebug (ppr nm)) (
+   = --trace ("nullary constructor! " ++ showSDocDebug (ppr nm)) (
      emitBc (mkProtoBCO (getName nm) (toOL [PACK dcon 0, ENTER])
                                      (Right original_body))
-     )
+     --)
 
    | otherwise
    = let fvs       = filter (not.isTyVar) (varSetElems (fst original_body))
@@ -330,7 +354,7 @@ schemeE d s p (fvs, AnnCase scrut bndr alts)
         scrut_primrep = typePrimRep (idType bndr)
         isAlgCase
            = case scrut_primrep of
-                CharRep -> False ; AddrRep -> False
+                CharRep -> False ; AddrRep -> False ; WordRep -> False
                 IntRep -> False ; FloatRep -> False ; DoubleRep -> False
                 PtrRep -> True
                 other  -> pprPanic "ByteCodeGen.schemeE" (ppr other)
@@ -354,6 +378,8 @@ schemeE d s p (fvs, AnnCase scrut bndr alts)
            = case l of MachInt i     -> DiscrI (fromInteger i)
                        MachFloat r   -> DiscrF (fromRational r)
                        MachDouble r  -> DiscrD (fromRational r)
+                       MachChar i    -> DiscrI i
+                       _ -> pprPanic "schemeE(AnnCase).my_discr" (ppr l)
 
         maybe_ncons 
            | not isAlgCase = Nothing
@@ -421,10 +447,11 @@ schemeT d s p app
          (args_r_to_l_raw, fn) = chomp app
          chomp expr
             = case snd expr of
-                 AnnVar v   -> ([], v)
-                 AnnApp f a -> case chomp f of (az, f) -> (snd a:az, f)
-                 other      -> pprPanic "schemeT" 
-                                  (ppr (deAnnotate (panic "schemeT.chomp", other)))
+                 AnnVar v    -> ([], v)
+                 AnnApp f a  -> case chomp f of (az, f) -> (snd a:az, f)
+                 AnnNote n e -> chomp e
+                 other       -> pprPanic "schemeT" 
+                                   (ppr (deAnnotate (panic "schemeT.chomp", other)))
          
          args_r_to_l = filter (not.isTypeAtom) args_r_to_l_raw
          isTypeAtom (AnnType _) = True
@@ -471,6 +498,7 @@ atomRep (AnnVar v)    = typePrimRep (idType v)
 atomRep (AnnLit l)    = literalPrimRep l
 atomRep (AnnNote n b) = atomRep (snd b)
 atomRep (AnnApp f (_, AnnType _)) = atomRep (snd f)
+atomRep (AnnLam x e) | isTyVar x = atomRep (snd e)
 atomRep other = pprPanic "atomRep" (ppr (deAnnotate (undefined,other)))
 
 
@@ -538,6 +566,7 @@ mkUnpackCode vars d p
            = case npr of
                 IntRep -> approved ; FloatRep -> approved
                 DoubleRep -> approved ; AddrRep -> approved
+                CharRep -> approved
                 _ -> pprPanic "ByteCodeGen.mkUnpackCode" (ppr npr)
              where
                 approved = UPK_TAG usizeW (off_h-usizeW) off_s   `consOL` theRest
@@ -572,6 +601,11 @@ mkUnpackCode vars d p
 
 pushAtom :: Bool -> Int -> BCEnv -> AnnExpr' Id VarSet -> (BCInstrList, Int)
 pushAtom tagged d p (AnnVar v)
+
+   | idPrimRep v == VoidRep
+   = ASSERT(tagged)
+     (unitOL (PUSH_TAG 0), 1)
+
    | Just primop <- isPrimOpId_maybe v
    = case primop of
         CCallOp _ -> panic "pushAtom: byte code generator can't handle CCalls"
@@ -612,6 +646,7 @@ pushAtom True d p (AnnLit lit)
 
 pushAtom False d p (AnnLit lit)
    = case lit of
+        MachWord w   -> code WordRep
         MachInt i    -> code IntRep
         MachFloat r  -> code FloatRep
         MachDouble r -> code DoubleRep
@@ -659,6 +694,10 @@ pushAtom tagged d p (AnnApp f (_, AnnType _))
 pushAtom tagged d p (AnnNote note e)
    = pushAtom tagged d p (snd e)
 
+pushAtom tagged d p (AnnLam x e) 
+   | isTyVar x 
+   = pushAtom tagged d p (snd e)
+
 pushAtom tagged d p other
    = pprPanic "ByteCodeGen.pushAtom" 
               (pprCoreExpr (deAnnotate (undefined, other)))