[project @ 2001-02-06 12:00:17 by sewardj]
[ghc-hetmet.git] / ghc / compiler / ghci / ByteCodeGen.lhs
index b9e0002..883416e 100644 (file)
@@ -14,7 +14,8 @@ module ByteCodeGen ( UnlinkedBCO, UnlinkedBCOExpr, ItblEnv, ClosureEnv, HValue,
 
 import Outputable
 import Name            ( Name, getName, mkSysLocalName )
-import Id              ( Id, idType, isDataConId_maybe, mkVanillaId )
+import Id              ( Id, idType, isDataConId_maybe, mkVanillaId,
+                         isPrimOpId_maybe, idPrimRep )
 import OrdList         ( OrdList, consOL, snocOL, appOL, unitOL, 
                          nilOL, toOL, concatOL, fromOL )
 import FiniteMap       ( FiniteMap, addListToFM, listToFM,
@@ -23,6 +24,7 @@ import CoreSyn
 import PprCore         ( pprCoreExpr )
 import Literal         ( Literal(..), literalPrimRep )
 import PrimRep         ( PrimRep(..) )
+import PrimOp          ( PrimOp(..)  )
 import CoreFVs         ( freeVars )
 import Type            ( typePrimRep )
 import DataCon         ( dataConTag, fIRST_TAG, dataConTyCon, dataConWrapId )
@@ -37,18 +39,18 @@ 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 )
-import Addr            ( addrToInt, writeCharOffAddr )
+import Addr            ( Addr(..), addrToInt, writeCharOffAddr )
 import CTypes          ( CInt )
 
 import PrelBase                ( Int(..) )
-import PrelAddr                ( Addr(..) )
 import PrelGHC         ( ByteArray# )
 import IOExts          ( unsafePerformIO )
 import PrelIOBase      ( IO(..) )
@@ -128,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}
 
@@ -168,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 []
@@ -209,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))
@@ -297,7 +322,7 @@ schemeE d s p (fvs, AnnLet binds b)
 
          -- ToDo: don't build thunks for things with no free variables
          buildThunk dd ([], size, id, off)
-            = PUSH_G (getName id) 
+            = PUSH_G (Left (getName id))
               `consOL` unitOL (MKAP (off+size-1) size)
          buildThunk dd ((fv:fvs), size, id, off)
             = case pushAtom True dd p' (AnnVar fv) of
@@ -329,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)
@@ -353,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
@@ -408,7 +435,7 @@ schemeT d s p app
 
    -- Handle case 1
    | is_con_call && null args_r_to_l
-   = (PUSH_G (getName con) `consOL` mkSLIDE 1 (d-s))
+   = (PUSH_G (Left (getName con)) `consOL` mkSLIDE 1 (d-s))
      `snocOL` ENTER
 
    -- Cases 2 and 3
@@ -420,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
@@ -470,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)))
 
 
@@ -537,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
@@ -570,7 +600,18 @@ mkUnpackCode vars d p
 -- 6 stack has valid words 0 .. 5.
 
 pushAtom :: Bool -> Int -> BCEnv -> AnnExpr' Id VarSet -> (BCInstrList, Int)
-pushAtom tagged d p (AnnVar v) 
+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"
+        other     -> (unitOL (PUSH_G (Right primop)), 1)
+
+   | otherwise
    = let str = "\npushAtom " ++ showSDocDebug (ppr v) 
                ++ " :: " ++ showSDocDebug (pprType (idType v))
                ++ ", depth = " ++ show d
@@ -586,7 +627,7 @@ pushAtom tagged d p (AnnVar v)
          result
             = case lookupBCEnv_maybe p v of
                  Just d_v -> (toOL (nOfThem nwords (PUSH_L (d-d_v+sz_t-2))), nwords)
-                 Nothing  -> ASSERT(sz_t == 1) (unitOL (PUSH_G nm), nwords)
+                 Nothing  -> ASSERT(sz_t == 1) (unitOL (PUSH_G (Left nm)), nwords)
 
          nm = case isDataConId_maybe v of
                  Just c  -> getName c
@@ -605,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
@@ -629,10 +671,10 @@ pushAtom False d p (AnnLit lit)
                             let n = I# l
                             -- CAREFUL!  Chars are 32 bits in ghc 4.09+
                             in  unsafePerformIO (
-                                   do a@(Ptr addr) <- mallocBytes (n+1)
-                                      strncpy a ba (fromIntegral n)
-                                      writeCharOffAddr addr n '\0'
-                                      return addr
+                                   do (Ptr a#) <- mallocBytes (n+1)
+                                      strncpy (Ptr a#) ba (fromIntegral n)
+                                      writeCharOffAddr (A# a#) n '\0'
+                                      return (A# a#)
                                    )
                          _ -> panic "StgInterp.lit2expr: unhandled string constant type"
 
@@ -652,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)))