[project @ 2001-02-06 14:01:22 by simonmar]
[ghc-hetmet.git] / ghc / compiler / ghci / ByteCodeLink.lhs
index 99d0bc2..dce5253 100644 (file)
@@ -5,27 +5,28 @@
 
 \begin{code}
 module ByteCodeLink ( UnlinkedBCO, UnlinkedBCOExpr, assembleBCO,
-                     ClosureEnv, HValue, linkSomeBCOs, filterNameMap
+                     ClosureEnv, HValue, linkSomeBCOs, filterNameMap,
+                     iNTERP_STACK_CHECK_THRESH
                   ) where
 
 #include "HsVersions.h"
 
 import Outputable
-import Name            ( Name, getName, nameModule, toRdrName )
+import Name            ( Name, getName, nameModule, toRdrName, isGlobalName )
 import RdrName         ( rdrNameOcc, rdrNameModule )
 import OccName         ( occNameString )
 import FiniteMap       ( FiniteMap, addListToFM, filterFM,
                          addToFM, lookupFM, emptyFM )
 import CoreSyn
 import Literal         ( Literal(..) )
+import PrimOp          ( PrimOp, primOpOcc )
 import PrimRep         ( PrimRep(..) )
-import Util            ( global )
 import Constants       ( wORD_SIZE )
 import Module          ( ModuleName, moduleName, moduleNameFS )
 import Linker          ( lookupSymbol )
 import FastString      ( FastString(..) )
 import ByteCodeInstr   ( BCInstr(..), ProtoBCO(..) )
-import ByteCodeItbls   ( ItblEnv )
+import ByteCodeItbls   ( ItblEnv, ItblPtr )
 
 
 import Monad           ( foldM )
@@ -36,13 +37,12 @@ import MArray               ( castSTUArray,
                          newIntArray, writeIntArray,
                          newAddrArray, writeAddrArray )
 import Foreign         ( Word16, Ptr(..) )
-import Addr            ( Word )
+import Addr            ( Word, Addr )
 
 import PrelBase                ( Int(..) )
-import PrelAddr                ( Addr(..) )
 import PrelGHC         ( BCO#, newBCO#, unsafeCoerce#, 
-                         ByteArray#, Array#, addrToHValue# )
-import IOExts          ( IORef, fixIO, readIORef, writeIORef )
+                         ByteArray#, Array#, addrToHValue#, mkApUpd0# )
+import IOExts          ( fixIO )
 import ArrayBase       
 import PrelArr         ( Array(..) )
 import PrelIOBase      ( IO(..) )
@@ -58,14 +58,23 @@ import PrelIOBase   ( IO(..) )
 \begin{code}
 
 -- Link a bunch of BCOs and return them + updated closure env.
-linkSomeBCOs :: ItblEnv -> ClosureEnv -> [UnlinkedBCO]
-                -> IO (ClosureEnv, [HValue])
-linkSomeBCOs ie ce_in ul_bcos
+linkSomeBCOs :: Bool   -- False <=> add _all_ BCOs to returned closure env
+                        -- True  <=> add only toplevel BCOs to closure env
+             -> ItblEnv 
+             -> ClosureEnv 
+             -> [UnlinkedBCO]
+             -> IO (ClosureEnv, [HValue])
+linkSomeBCOs toplevs_only ie ce_in ul_bcos
    = do let nms = map nameOfUnlinkedBCO ul_bcos
         hvals <- fixIO 
                     ( \ hvs -> let ce_out = addListToFM ce_in (zipLazily nms hvs)
                                in  mapM (linkBCO ie ce_out) ul_bcos )
-        let ce_out = addListToFM ce_in (zip nms hvals)
+
+        let ce_all_additions = zip nms hvals
+            ce_top_additions = filter (isGlobalName.fst) ce_all_additions
+            ce_additions     = if toplevs_only then ce_top_additions 
+                                               else ce_all_additions
+            ce_out = addListToFM ce_in ce_additions
         return (ce_out, hvals)
      where
         -- A lazier zip, in which no demand is propagated to the second
@@ -77,10 +86,10 @@ linkSomeBCOs ie ce_in ul_bcos
 
 data UnlinkedBCO
    = UnlinkedBCO Name
-                 (SizedSeq Word16)     -- insns
-                 (SizedSeq Word)       -- literals
-                 (SizedSeq Name)       -- ptrs
-                 (SizedSeq Name)       -- itbl refs
+                 (SizedSeq Word16)              -- insns
+                 (SizedSeq Word)                -- literals
+                 (SizedSeq (Either Name PrimOp)) -- ptrs
+                 (SizedSeq Name)                -- itbl refs
 
 nameOfUnlinkedBCO (UnlinkedBCO nm _ _ _ _) = nm
 
@@ -104,8 +113,7 @@ data HValue     = HValue  -- dummy type, actually a pointer to some Real Code.
 -- remove all entries for a given set of modules from the environment
 filterNameMap :: [ModuleName] -> FiniteMap Name a -> FiniteMap Name a
 filterNameMap mods env 
-   = filterFM (\n _ -> moduleName (nameModule n) `notElem` mods) env
-
+   = filterFM (\n _ -> moduleName (nameModule n) `elem` mods) env
 \end{code}
 
 %************************************************************************
@@ -146,7 +154,7 @@ assembleBCO (ProtoBCO nm instrs origin)
      do  -- pass 2: generate the instruction, ptr and nonptr bits
          insns <- return emptySS :: IO (SizedSeq Word16)
          lits  <- return emptySS :: IO (SizedSeq Word)
-         ptrs  <- return emptySS :: IO (SizedSeq Name)
+         ptrs  <- return emptySS :: IO (SizedSeq (Either Name PrimOp))
          itbls <- return emptySS :: IO (SizedSeq Name)
          let init_asm_state = (insns,lits,ptrs,itbls)
          (final_insns, final_lits, final_ptrs, final_itbls) 
@@ -155,7 +163,8 @@ assembleBCO (ProtoBCO nm instrs origin)
          return (UnlinkedBCO nm final_insns final_lits final_ptrs final_itbls)
 
 -- instrs nonptrs ptrs itbls
-type AsmState = (SizedSeq Word16, SizedSeq Word, SizedSeq Name, SizedSeq Name)
+type AsmState = (SizedSeq Word16, SizedSeq Word, 
+                 SizedSeq (Either Name PrimOp), SizedSeq Name)
 
 data SizedSeq a = SizedSeq !Int [a]
 emptySS = SizedSeq 0 []
@@ -179,12 +188,13 @@ mkBits findLabel st proto_insns
        doInstr st i
           = case i of
                ARGCHECK  n        -> instr2 st i_ARGCHECK n
+               STKCHECK  n        -> instr2 st i_STKCHECK n
                PUSH_L    o1       -> instr2 st i_PUSH_L o1
                PUSH_LL   o1 o2    -> instr3 st i_PUSH_LL o1 o2
                PUSH_LLL  o1 o2 o3 -> instr4 st i_PUSH_LLL o1 o2 o3
                PUSH_G    nm       -> do (p, st2) <- ptr st nm
                                         instr2 st2 i_PUSH_G p
-               PUSH_AS   nm pk    -> do (p, st2)  <- ptr st nm
+               PUSH_AS   nm pk    -> do (p, st2)  <- ptr st (Left nm)
                                         (np, st3) <- ctoi_itbl st2 pk
                                         instr3 st3 i_PUSH_AS p np
                PUSH_UBX  lit nws  -> do (np, st2) <- literal st lit
@@ -270,6 +280,7 @@ mkBits findLabel st proto_insns
           = do st_I1 <- addToSS st_I0 (getName dcon)
                return (sizeSS st_I0, (st_i0,st_l0,st_p0,st_I1))
 
+       literal st (MachWord w)   = int st (fromIntegral w)
        literal st (MachInt j)    = int st (fromIntegral j)
        literal st (MachFloat r)  = float st (fromRational r)
        literal st (MachDouble r) = double st (fromRational r)
@@ -279,9 +290,11 @@ mkBits findLabel st proto_insns
           = addr st ret_itbl_addr
             where
                ret_itbl_addr = case pk of
-                                  PtrRep    -> stg_ctoi_ret_R1_info
-                                  IntRep    -> stg_ctoi_ret_R1_info
-                                  CharRep   -> stg_ctoi_ret_R1_info
+                                  PtrRep    -> stg_ctoi_ret_R1p_info
+                                  WordRep   -> stg_ctoi_ret_R1n_info
+                                  IntRep    -> stg_ctoi_ret_R1n_info
+                                  AddrRep   -> stg_ctoi_ret_R1n_info
+                                  CharRep   -> stg_ctoi_ret_R1n_info
                                   FloatRep  -> stg_ctoi_ret_F1_info
                                   DoubleRep -> stg_ctoi_ret_D1_info
                                   _ -> pprPanic "mkBits.ctoi_itbl" (ppr pk)
@@ -290,13 +303,15 @@ mkBits findLabel st proto_insns
           = addr st ret_itbl_addr
             where
                ret_itbl_addr = case pk of
+                                  CharRep   -> stg_gc_unbx_r1_info
                                   IntRep    -> stg_gc_unbx_r1_info
                                   FloatRep  -> stg_gc_f1_info
                                   DoubleRep -> stg_gc_d1_info
                      
-foreign label "stg_ctoi_ret_R1_info" stg_ctoi_ret_R1_info :: Addr
-foreign label "stg_ctoi_ret_F1_info" stg_ctoi_ret_F1_info :: Addr
-foreign label "stg_ctoi_ret_D1_info" stg_ctoi_ret_D1_info :: Addr
+foreign label "stg_ctoi_ret_R1p_info" stg_ctoi_ret_R1p_info :: Addr
+foreign label "stg_ctoi_ret_R1n_info" stg_ctoi_ret_R1n_info :: Addr
+foreign label "stg_ctoi_ret_F1_info"  stg_ctoi_ret_F1_info :: Addr
+foreign label "stg_ctoi_ret_D1_info"  stg_ctoi_ret_D1_info :: Addr
 
 foreign label "stg_gc_unbx_r1_info" stg_gc_unbx_r1_info :: Addr
 foreign label "stg_gc_f1_info"      stg_gc_f1_info :: Addr
@@ -306,6 +321,7 @@ foreign label "stg_gc_d1_info"      stg_gc_d1_info :: Addr
 instrSize16s :: BCInstr -> Int
 instrSize16s instr
    = case instr of
+        STKCHECK _     -> 2
         ARGCHECK _     -> 2
         PUSH_L   _     -> 2
         PUSH_LL  _ _   -> 3
@@ -405,14 +421,6 @@ data BCO# = BCO# ByteArray#                -- instrs   :: array Word16#
                  ByteArray#            -- itbls    :: Array Addr#
 -}
 
-GLOBAL_VAR(v_cafTable, [], [HValue])
-
-addCAF :: HValue -> IO ()
-addCAF x = do xs <- readIORef v_cafTable
-              --putStrLn ("addCAF " ++ show (1 + length xs))
-              writeIORef v_cafTable (x:xs)
-
-
 linkBCO ie ce (UnlinkedBCO nm insnsSS literalsSS ptrsSS itblsSS)
    = do insns    <- listFromSS insnsSS
         literals <- listFromSS literalsSS
@@ -432,7 +440,7 @@ linkBCO ie ce (UnlinkedBCO nm insnsSS literalsSS ptrsSS itblsSS)
             ptrs_parr = case ptrs_arr of Array lo hi parr -> parr
 
             itbls_arr = array (0, n_itbls-1) (indexify linked_itbls)
-                        :: UArray Int Addr
+                        :: UArray Int ItblPtr
             itbls_barr = case itbls_arr of UArray lo hi barr -> barr
 
             insns_arr | n_insns > 65535
@@ -452,7 +460,9 @@ linkBCO ie ce (UnlinkedBCO nm insnsSS literalsSS ptrsSS itblsSS)
 
         BCO bco# <- newBCO insns_barr literals_barr ptrs_parr itbls_barr
 
-        return (unsafeCoerce# bco#)
+        -- WAS: return (unsafeCoerce# bco#)
+        case mkApUpd0# (unsafeCoerce# bco#) of
+           (# final_bco #) -> return final_bco
 
 
 data BCO = BCO BCO#
@@ -462,22 +472,27 @@ newBCO a b c d
    = IO (\s -> case newBCO# a b c d s of (# s1, bco #) -> (# s1, BCO bco #))
 
 
-lookupCE :: ClosureEnv -> Name -> IO HValue
-lookupCE ce nm 
+lookupCE :: ClosureEnv -> Either Name PrimOp -> IO HValue
+lookupCE ce (Right primop)
+   = do m <- lookupSymbol (primopToCLabel primop "closure")
+        case m of
+           Just (Ptr addr) -> case addrToHValue# addr of
+                                 (# hval #) -> return hval
+           Nothing -> pprPanic "ByteCodeGen.lookupCE(primop)" (ppr primop)
+lookupCE ce (Left nm)
    = case lookupFM ce nm of
         Just aa -> return aa
         Nothing 
            -> do m <- lookupSymbol (nameToCLabel nm "closure")
                  case m of
-                    Just (A# addr) -> case addrToHValue# addr of
-                                         (# hval #) -> do addCAF hval
-                                                          return hval
+                    Just (Ptr addr) -> case addrToHValue# addr of
+                                          (# hval #) -> return hval
                     Nothing        -> pprPanic "ByteCodeGen.lookupCE" (ppr nm)
 
-lookupIE :: ItblEnv -> Name -> IO Addr
+lookupIE :: ItblEnv -> Name -> IO (Ptr a)
 lookupIE ie con_nm 
    = case lookupFM ie con_nm of
-        Just (Ptr a) -> return a
+        Just (Ptr a) -> return (Ptr a)
         Nothing
            -> do -- try looking up in the object files.
                  m <- lookupSymbol (nameToCLabel con_nm "con_info")
@@ -490,13 +505,19 @@ lookupIE ie con_nm
                                 Just addr -> return addr
                                 Nothing -> pprPanic "ByteCodeGen.lookupIE" (ppr con_nm)
 
--- HACK!!!  ToDo: cleaner
+-- HACKS!!!  ToDo: cleaner
 nameToCLabel :: Name -> String{-suffix-} -> String
 nameToCLabel n suffix
    = _UNPK_(moduleNameFS (rdrNameModule rn)) 
      ++ '_':occNameString(rdrNameOcc rn) ++ '_':suffix
      where rn = toRdrName n
 
+primopToCLabel :: PrimOp -> String{-suffix-} -> String
+primopToCLabel primop suffix
+   = let str = "PrelPrimopWrappers_" ++ occNameString (primOpOcc primop) ++ '_':suffix
+     in --trace ("primopToCLabel: " ++ str)
+        str
+
 \end{code}
 
 %************************************************************************
@@ -534,5 +555,8 @@ i_TESTEQ_P = (bci_TESTEQ_P :: Int)
 i_CASEFAIL = (bci_CASEFAIL :: Int)
 i_ENTER    = (bci_ENTER :: Int)
 i_RETURN   = (bci_RETURN :: Int)
+i_STKCHECK = (bci_STKCHECK :: Int)
+
+iNTERP_STACK_CHECK_THRESH = (INTERP_STACK_CHECK_THRESH :: Int)
 
 \end{code}