[project @ 2001-03-27 14:10:34 by simonmar]
[ghc-hetmet.git] / ghc / compiler / ghci / ByteCodeLink.lhs
index 2792b3d..ac74052 100644 (file)
@@ -5,22 +5,23 @@
 
 \begin{code}
 module ByteCodeLink ( UnlinkedBCO, UnlinkedBCOExpr, assembleBCO,
-                     ClosureEnv, HValue, linkSomeBCOs, filterNameMap
+                     ClosureEnv, HValue, filterNameMap,
+                     linkIModules, linkIExpr,
+                     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, occNameUserString )
+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 )
@@ -37,12 +38,13 @@ import MArray               ( castSTUArray,
                          newIntArray, writeIntArray,
                          newAddrArray, writeAddrArray )
 import Foreign         ( Word16, Ptr(..) )
-import Addr            ( Word, Addr )
+import Addr            ( Word, Addr, nullAddr )
+import FiniteMap
 
 import PrelBase                ( Int(..) )
 import PrelGHC         ( BCO#, newBCO#, unsafeCoerce#, 
                          ByteArray#, Array#, addrToHValue#, mkApUpd0# )
-import IOExts          ( IORef, fixIO, readIORef, writeIORef )
+import IOExts          ( fixIO )
 import ArrayBase       
 import PrelArr         ( Array(..) )
 import PrelIOBase      ( IO(..) )
@@ -56,16 +58,47 @@ import PrelIOBase   ( IO(..) )
 %************************************************************************
 
 \begin{code}
+-- Linking stuff
+linkIModules :: ItblEnv    -- incoming global itbl env; returned updated
+            -> ClosureEnv -- incoming global closure env; returned updated
+            -> [([UnlinkedBCO], ItblEnv)]
+            -> IO ([HValue], ItblEnv, ClosureEnv)
+linkIModules gie gce mods 
+   = do let (bcoss, ies) = unzip mods
+            bcos = concat bcoss
+            final_gie = foldr plusFM gie ies
+        (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 False ie ce aux_ul_bcos
+        (_, [root_bco]) <- linkSomeBCOs False ie aux_ce [root_ul_bco]
+        return root_bco
 
 -- 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 = -- make sure we're not inserting duplicate names into the 
+                    -- closure environment, which leads to trouble.
+                    ASSERT (all (not . (`elemFM` ce_in)) (map fst ce_additions))
+                    addListToFM ce_in ce_additions
         return (ce_out, hvals)
      where
         -- A lazier zip, in which no demand is propagated to the second
@@ -101,11 +134,13 @@ instance Outputable UnlinkedBCO where
 type ClosureEnv = FiniteMap Name HValue
 data HValue     = HValue  -- dummy type, actually a pointer to some Real Code.
 
--- remove all entries for a given set of modules from the environment
+-- remove all entries for a given set of modules from the environment;
+-- note that this removes all local names too (ie. temporary bindings from
+-- the command line).
 filterNameMap :: [ModuleName] -> FiniteMap Name a -> FiniteMap Name a
 filterNameMap mods env 
-   = filterFM (\n _ -> moduleName (nameModule n) `notElem` mods) env
-
+   = filterFM (\n _ -> isGlobalName n && 
+                       moduleName (nameModule n) `elem` mods) env
 \end{code}
 
 %************************************************************************
@@ -180,6 +215,7 @@ 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
@@ -214,6 +250,7 @@ mkBits findLabel st proto_insns
                TESTLT_P  i l      -> instr3 st i_TESTLT_P i (findLabel l)
                TESTEQ_P  i l      -> instr3 st i_TESTEQ_P i (findLabel l)
                CASEFAIL           -> instr1 st i_CASEFAIL
+               JMP l              -> instr2 st i_JMP (findLabel l)
                ENTER              -> instr1 st i_ENTER
                RETURN rep         -> do (itbl_no,st2) <- itoc_itbl st rep
                                         instr2 st2 i_RETURN itbl_no
@@ -288,6 +325,7 @@ mkBits findLabel st proto_insns
                                   CharRep   -> stg_ctoi_ret_R1n_info
                                   FloatRep  -> stg_ctoi_ret_F1_info
                                   DoubleRep -> stg_ctoi_ret_D1_info
+                                  VoidRep   -> stg_ctoi_ret_V_info
                                   _ -> pprPanic "mkBits.ctoi_itbl" (ppr pk)
 
        itoc_itbl st pk
@@ -298,11 +336,14 @@ mkBits findLabel st proto_insns
                                   IntRep    -> stg_gc_unbx_r1_info
                                   FloatRep  -> stg_gc_f1_info
                                   DoubleRep -> stg_gc_d1_info
+                                  VoidRep   -> nullAddr  
+                                  -- Interpreter.c spots this special case
                      
 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_ctoi_ret_V_info"   stg_ctoi_ret_V_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
@@ -312,6 +353,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
@@ -335,6 +377,7 @@ instrSize16s instr
         TESTEQ_D _ _   -> 3
         TESTLT_P _ _   -> 3
         TESTEQ_P _ _   -> 3
+        JMP      _     -> 2
         CASEFAIL       -> 1
         ENTER          -> 1
         RETURN   _     -> 2
@@ -411,14 +454,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
@@ -475,8 +510,7 @@ lookupCE ce (Right primop)
    = do m <- lookupSymbol (primopToCLabel primop "closure")
         case m of
            Just (Ptr addr) -> case addrToHValue# addr of
-                                 (# hval #) -> do addCAF hval
-                                                  return hval
+                                 (# hval #) -> return hval
            Nothing -> pprPanic "ByteCodeGen.lookupCE(primop)" (ppr primop)
 lookupCE ce (Left nm)
    = case lookupFM ce nm of
@@ -485,8 +519,7 @@ lookupCE ce (Left nm)
            -> do m <- lookupSymbol (nameToCLabel nm "closure")
                  case m of
                     Just (Ptr addr) -> case addrToHValue# addr of
-                                          (# hval #) -> do addCAF hval
-                                                           return hval
+                                          (# hval #) -> return hval
                     Nothing        -> pprPanic "ByteCodeGen.lookupCE" (ppr nm)
 
 lookupIE :: ItblEnv -> Name -> IO (Ptr a)
@@ -555,5 +588,9 @@ 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)
+i_JMP      = (bci_JMP :: Int)
+
+iNTERP_STACK_CHECK_THRESH = (INTERP_STACK_CHECK_THRESH :: Int)
 
 \end{code}