[project @ 2002-09-03 15:32:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / ghci / ByteCodeLink.lhs
index 76b56d6..0ca24f8 100644 (file)
@@ -16,7 +16,7 @@ module ByteCodeLink ( UnlinkedBCO, UnlinkedBCOExpr, assembleBCO,
 #include "HsVersions.h"
 
 import Outputable
-import Name            ( Name, getName, nameModule, toRdrName, isGlobalName )
+import Name            ( Name, getName, nameModule, toRdrName, isExternalName )
 import RdrName         ( rdrNameOcc, rdrNameModule )
 import OccName         ( occNameString )
 import FiniteMap       ( FiniteMap, addListToFM, filterFM,
@@ -24,42 +24,39 @@ import FiniteMap    ( FiniteMap, addListToFM, filterFM,
 import CoreSyn
 import Literal         ( Literal(..) )
 import PrimOp          ( PrimOp, primOpOcc )
-import PrimRep         ( PrimRep(..) )
+import PrimRep         ( PrimRep(..), isFollowableRep )
 import Constants       ( wORD_SIZE )
 import Module          ( ModuleName, moduleName, moduleNameFS )
 import Linker          ( lookupSymbol )
-import FastString      ( FastString(..) )
+import FastString      ( FastString(..), unpackFS )
 import ByteCodeInstr   ( BCInstr(..), ProtoBCO(..) )
 import ByteCodeItbls   ( ItblEnv, ItblPtr )
 import FiniteMap
 import Panic            ( GhcException(..) )
+import Util             ( notNull )
 
 import Control.Monad   ( when, foldM )
 import Control.Monad.ST        ( runST )
 import Data.Array.IArray ( array )
 
-import GHC.Word                ( Word )
+import GHC.Word                ( Word(..) )
 import Data.Array.MArray ( MArray, newArray_, readArray, writeArray )
 import Data.Array.ST   ( castSTUArray )
 import Data.Array.Base ( UArray(..) )
-import Foreign.Ptr     ( Ptr, nullPtr )
-import Foreign         ( Word16, Ptr(..), free )
+import Foreign.Ptr     ( nullPtr )
+import Foreign         ( Word16, free )
 import System.Mem.Weak  ( addFinalizer )
 import Data.Int                ( Int64 )
 
 import System.IO       ( fixIO )
 import Control.Exception ( throwDyn )
 
-import GlaExts         ( BCO#, newBCO#, unsafeCoerce#, 
+import GHC.Exts                ( BCO#, newBCO#, unsafeCoerce#, 
                          ByteArray#, Array#, addrToHValue#, mkApUpd0# )
 
-#if __GLASGOW_HASKELL__ >= 503
 import GHC.Arr         ( Array(..) )
 import GHC.IOBase      ( IO(..) )
-#else
-import PrelArr         ( Array(..) )
-import PrelIOBase      ( IO(..) )
-#endif
+import GHC.Ptr         ( Ptr(..) )
 \end{code}
 
 %************************************************************************
@@ -103,7 +100,7 @@ linkSomeBCOs toplevs_only ie ce_in ul_bcos
                                in  mapM (linkBCO ie ce_out) ul_bcos )
 
         let ce_all_additions = zip nms hvals
-            ce_top_additions = filter (isGlobalName.fst) ce_all_additions
+            ce_top_additions = filter (isExternalName.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 
@@ -122,7 +119,10 @@ linkSomeBCOs toplevs_only ie ce_in ul_bcos
 data UnlinkedBCO
    = UnlinkedBCO Name
                  (SizedSeq Word16)              -- insns
-                 (SizedSeq Word)                -- literals
+                 (SizedSeq (Either Word FastString))    -- literals
+                       -- Either literal words or a pointer to a asciiz
+                       -- string, denoting a label whose *address* should
+                       -- be determined at link time
                  (SizedSeq (Either Name PrimOp)) -- ptrs
                  (SizedSeq Name)                -- itbl refs
 
@@ -150,7 +150,7 @@ data HValue     = HValue  -- dummy type, actually a pointer to some Real Code.
 -- the command line).
 filterNameMap :: [ModuleName] -> FiniteMap Name a -> FiniteMap Name a
 filterNameMap mods env 
-   = filterFM (\n _ -> isGlobalName n 
+   = filterFM (\n _ -> isExternalName n 
                        && moduleName (nameModule n) `elem` mods) env
 \end{code}
 
@@ -191,7 +191,7 @@ assembleBCO (ProtoBCO nm instrs origin malloced)
      in
      do  -- pass 2: generate the instruction, ptr and nonptr bits
          insns <- return emptySS :: IO (SizedSeq Word16)
-         lits  <- return emptySS :: IO (SizedSeq Word)
+         lits  <- return emptySS :: IO (SizedSeq (Either Word FastString))
          ptrs  <- return emptySS :: IO (SizedSeq (Either Name PrimOp))
          itbls <- return emptySS :: IO (SizedSeq Name)
          let init_asm_state = (insns,lits,ptrs,itbls)
@@ -203,7 +203,7 @@ assembleBCO (ProtoBCO nm instrs origin malloced)
          -- 8 Aug 01: Finalisers aren't safe when attached to non-primitive
          -- objects, since they might get run too early.  Disable this until
          -- we figure out what to do.
-         -- when (not (null malloced)) (addFinalizer ul_bco (mapM_ zonk malloced))
+         -- when (notNull malloced) (addFinalizer ul_bco (mapM_ zonk malloced))
 
          return ul_bco
      where
@@ -211,8 +211,10 @@ assembleBCO (ProtoBCO nm instrs origin malloced)
                            free ptr
 
 -- instrs nonptrs ptrs itbls
-type AsmState = (SizedSeq Word16, SizedSeq Word, 
-                 SizedSeq (Either Name PrimOp), SizedSeq Name)
+type AsmState = (SizedSeq Word16, 
+                 SizedSeq (Either Word FastString),
+                 SizedSeq (Either Name PrimOp), 
+                 SizedSeq Name)
 
 data SizedSeq a = SizedSeq !Int [a]
 emptySS = SizedSeq 0 []
@@ -311,27 +313,31 @@ mkBits findLabel st proto_insns
 
        float (st_i0,st_l0,st_p0,st_I0) f
           = do let ws = mkLitF f
-               st_l1 <- addListToSS st_l0 ws
+               st_l1 <- addListToSS st_l0 (map Left ws)
                return (sizeSS st_l0, (st_i0,st_l1,st_p0,st_I0))
 
        double (st_i0,st_l0,st_p0,st_I0) d
           = do let ws = mkLitD d
-               st_l1 <- addListToSS st_l0 ws
+               st_l1 <- addListToSS st_l0 (map Left ws)
                return (sizeSS st_l0, (st_i0,st_l1,st_p0,st_I0))
 
        int (st_i0,st_l0,st_p0,st_I0) i
           = do let ws = mkLitI i
-               st_l1 <- addListToSS st_l0 ws
+               st_l1 <- addListToSS st_l0 (map Left ws)
                return (sizeSS st_l0, (st_i0,st_l1,st_p0,st_I0))
 
        int64 (st_i0,st_l0,st_p0,st_I0) i
           = do let ws = mkLitI64 i
-               st_l1 <- addListToSS st_l0 ws
+               st_l1 <- addListToSS st_l0 (map Left ws)
                return (sizeSS st_l0, (st_i0,st_l1,st_p0,st_I0))
 
        addr (st_i0,st_l0,st_p0,st_I0) a
           = do let ws = mkLitPtr a
-               st_l1 <- addListToSS st_l0 ws
+               st_l1 <- addListToSS st_l0 (map Left ws)
+               return (sizeSS st_l0, (st_i0,st_l1,st_p0,st_I0))
+
+       litlabel (st_i0,st_l0,st_p0,st_I0) fs
+          = do st_l1 <- addListToSS st_l0 [Right fs]
                return (sizeSS st_l0, (st_i0,st_l1,st_p0,st_I0))
 
        ptr (st_i0,st_l0,st_p0,st_I0) p
@@ -342,6 +348,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 (MachLabel fs)  = litlabel st fs
        literal st (MachWord w)    = int st (fromIntegral w)
        literal st (MachInt j)     = int st (fromIntegral j)
        literal st (MachFloat r)   = float st (fromRational r)
@@ -356,7 +363,6 @@ mkBits findLabel st proto_insns
             where
                ret_itbl_addr 
                   = case pk of
-                       PtrRep    -> stg_ctoi_ret_R1p_info
                        WordRep   -> stg_ctoi_ret_R1n_info
                        IntRep    -> stg_ctoi_ret_R1n_info
                        AddrRep   -> stg_ctoi_ret_R1n_info
@@ -364,7 +370,11 @@ mkBits findLabel st proto_insns
                        FloatRep  -> stg_ctoi_ret_F1_info
                        DoubleRep -> stg_ctoi_ret_D1_info
                        VoidRep   -> stg_ctoi_ret_V_info
-                       other     -> pprPanic "ByteCodeLink.ctoi_itbl" (ppr pk)
+                       other | isFollowableRep pk -> stg_ctoi_ret_R1p_info
+                               -- Includes ArrayRep, ByteArrayRep, as well as
+                               -- the obvious PtrRep
+                            | otherwise
+                            -> pprPanic "ByteCodeLink.ctoi_itbl" (ppr pk)
 
        itoc_itbl st pk
           = addr st ret_itbl_addr
@@ -377,9 +387,10 @@ mkBits findLabel st proto_insns
                        AddrRep   -> stg_gc_unbx_r1_info
                        FloatRep  -> stg_gc_f1_info
                        DoubleRep -> stg_gc_d1_info
-                       VoidRep   -> nullPtr
-                       -- Interpreter.c spots this special case
-                       other     -> pprPanic "ByteCodeLink.itoc_itbl" (ppr pk)
+                       VoidRep   -> nullPtr    -- Interpreter.c spots this special case
+                       other | isFollowableRep pk -> stg_gc_unpt_r1_info
+                            | otherwise
+                           -> pprPanic "ByteCodeLink.itoc_itbl" (ppr pk)
                      
 foreign label "stg_ctoi_ret_R1p_info" stg_ctoi_ret_R1p_info :: Ptr ()
 foreign label "stg_ctoi_ret_R1n_info" stg_ctoi_ret_R1n_info :: Ptr ()
@@ -388,6 +399,7 @@ foreign label "stg_ctoi_ret_D1_info"  stg_ctoi_ret_D1_info :: Ptr ()
 foreign label "stg_ctoi_ret_V_info"   stg_ctoi_ret_V_info :: Ptr ()
 
 foreign label "stg_gc_unbx_r1_info" stg_gc_unbx_r1_info :: Ptr ()
+foreign label "stg_gc_unpt_r1_info" stg_gc_unpt_r1_info :: Ptr ()
 foreign label "stg_gc_f1_info"      stg_gc_f1_info :: Ptr ()
 foreign label "stg_gc_d1_info"      stg_gc_d1_info :: Ptr ()
 
@@ -431,7 +443,7 @@ instrSize16s instr
 mkLitI   :: Int    -> [Word]
 mkLitF   :: Float  -> [Word]
 mkLitD   :: Double -> [Word]
-mkLitPtr :: Ptr ()   -> [Word]
+mkLitPtr :: Ptr () -> [Word]
 mkLitI64 :: Int64  -> [Word]
 
 mkLitF f
@@ -521,8 +533,9 @@ linkBCO ie ce (UnlinkedBCO nm insnsSS literalsSS ptrsSS itblsSS)
         ptrs     <- listFromSS ptrsSS
         itbls    <- listFromSS itblsSS
 
-        linked_ptrs  <- mapM (lookupCE ce) ptrs
-        linked_itbls <- mapM (lookupIE ie) itbls
+        linked_ptrs     <- mapM (lookupCE ce) ptrs
+        linked_itbls    <- mapM (lookupIE ie) itbls
+        linked_literals <- mapM lookupLiteral literals
 
         let n_insns    = sizeSS insnsSS
             n_literals = sizeSS literalsSS
@@ -545,7 +558,7 @@ linkBCO ie ce (UnlinkedBCO nm insnsSS literalsSS ptrsSS itblsSS)
                         :: UArray Int Word16
             insns_barr = case insns_arr of UArray lo hi barr -> barr
 
-            literals_arr = array (0, n_literals-1) (indexify literals)
+            literals_arr = array (0, n_literals-1) (indexify linked_literals)
                            :: UArray Int Word
             literals_barr = case literals_arr of UArray lo hi barr -> barr
 
@@ -566,6 +579,20 @@ newBCO a b c d
    = IO (\s -> case newBCO# a b c d s of (# s1, bco #) -> (# s1, BCO bco #))
 
 
+lookupLiteral :: Either Word FastString -> IO Word
+lookupLiteral (Left w) = return w
+lookupLiteral (Right addr_of_label_string)
+   = do let label_to_find = unpackFS addr_of_label_string
+        m <- lookupSymbol label_to_find 
+        case m of
+           -- Can't be bothered to find the official way to convert Addr# to Word#;
+           -- the FFI/Foreign designers make it too damn difficult
+           -- Hence we apply the Blunt Instrument, which works correctly
+           -- on all reasonable architectures anyway
+           Just (Ptr addr) -> return (W# (unsafeCoerce# addr))
+           Nothing         -> linkFail "ByteCodeLink: can't find label" 
+                                       label_to_find
+
 lookupCE :: ClosureEnv -> Either Name PrimOp -> IO HValue
 lookupCE ce (Right primop)
    = do let sym_to_find = primopToCLabel primop "closure"
@@ -578,7 +605,7 @@ lookupCE ce (Left nm)
    = case lookupFM ce nm of
         Just aa -> return aa
         Nothing 
-           -> ASSERT2(isGlobalName nm, ppr nm)
+           -> ASSERT2(isExternalName nm, ppr nm)
              do let sym_to_find = nameToCLabel nm "closure"
                  m <- lookupSymbol sym_to_find
                  case m of
@@ -623,13 +650,13 @@ linkFail who what
 -- HACKS!!!  ToDo: cleaner
 nameToCLabel :: Name -> String{-suffix-} -> String
 nameToCLabel n suffix
-   = _UNPK_(moduleNameFS (rdrNameModule rn)) 
+   = unpackFS(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
+   = let str = "GHCziPrimopWrappers_" ++ occNameString (primOpOcc primop) ++ '_':suffix
      in --trace ("primopToCLabel: " ++ str)
         str