[project @ 2002-12-19 15:12:01 by simonmar]
[ghc-hetmet.git] / ghc / compiler / ghci / Linker.lhs
index 2b45436..a2e7b1b 100644 (file)
@@ -16,9 +16,10 @@ necessary.
 {-# OPTIONS -optc-DNON_POSIX_SOURCE #-}
 
 module Linker ( HValue, initLinker, showLinkerState,
-               linkPackages, linkLibraries,
-               linkModules, unload, extendLinkEnv, linkExpr,
-               LibrarySpec(..)
+               linkLibraries, linkExpr,
+               unload, extendLinkEnv, 
+               LibrarySpec(..),
+               linkPackages,
        ) where
 
 #include "../includes/config.h"
@@ -27,34 +28,29 @@ module Linker ( HValue, initLinker, showLinkerState,
 import ObjLink         ( loadDLL, loadObj, unloadObj, resolveObjs, initLinker )
 import ByteCodeLink    ( HValue, ClosureEnv, extendClosureEnv, linkBCO )
 import ByteCodeItbls   ( ItblEnv )
-import ByteCodeAsm     ( CompiledByteCode(..), bcosFreeNames,
-                         UnlinkedBCO, UnlinkedBCOExpr, nameOfUnlinkedBCO )
+import ByteCodeAsm     ( CompiledByteCode(..), bcoFreeNames, UnlinkedBCO(..))
 
-import Packages                ( PackageConfig(..), PackageName, PackageConfigMap, lookupPkg,
-                         packageDependents, packageNameString )
-import DriverState     ( v_Library_paths, v_Cmdline_libraries, getPackageConfigMap )
-
-import HscTypes                ( Linkable(..), isObjectLinkable, nameOfObject, byteCodeOfObject,
-                         Unlinked(..), isInterpretable, isObject,
-                         HscEnv(..), PersistentCompilerState(..), ExternalPackageState(..),
-                         HomePackageTable, PackageIfaceTable, ModIface(..), HomeModInfo(..) )
+import Packages
+import DriverState     ( v_Library_paths, v_Opt_l, getStaticOpts )
+import Finder          ( findModule, findLinkable )
+import HscTypes
 import Name            ( Name,  nameModule, isExternalName )
 import NameEnv
 import NameSet         ( nameSetToList )
-import Module          ( Module, ModuleName, moduleName, lookupModuleEnvByName )
+import Module
 import FastString      ( FastString(..), unpackFS )
+import ListSetOps      ( minusList )
 import CmdLineOpts     ( DynFlags(verbosity) )
 import BasicTypes      ( SuccessFlag(..), succeeded, failed )
 import Outputable
 import Panic            ( GhcException(..) )
 import Util             ( zipLazy, global )
-import ErrUtils                ( Message )
 
 -- Standard libraries
 import Control.Monad   ( when, filterM, foldM )
 
 import Data.IORef      ( IORef, readIORef, writeIORef )
-import Data.List       ( partition )
+import Data.List       ( partition, nub )
 
 import System.IO       ( putStr, putStrLn, hPutStrLn, stderr, fixIO )
 import System.Directory        ( doesFileExist )
@@ -167,7 +163,7 @@ showLinkerState
 
 \begin{code}
 linkExpr :: HscEnv -> PersistentCompilerState
-        -> UnlinkedBCOExpr -> IO HValue          -- IO BCO# really
+        -> UnlinkedBCO -> IO HValue
 
 -- Link a single expression, *including* first linking packages and 
 -- modules that this expression depends on.
@@ -175,12 +171,12 @@ linkExpr :: HscEnv -> PersistentCompilerState
 -- Raises an IO exception if it can't find a compiled version of the
 -- dependents to link.
 
-linkExpr hsc_env pcs (root_ul_bco, aux_ul_bcos)
-   =   -- Find what packages and linkables are required
-     case getLinkDeps hpt pit needed_mods of {
-       Left msg -> dieWith (msg $$ ptext SLIT("When linking an expression")) ;
-       Right (lnks, pkgs) -> do {
+linkExpr hsc_env pcs root_ul_bco
+  = do {  
+       -- Find what packages and linkables are required
+     (lnks, pkgs) <- getLinkDeps hpt pit needed_mods ;
 
+       -- Link the packages and modules required
      linkPackages dflags pkgs
    ; ok <-  linkModules dflags lnks
    ; if failed ok then
@@ -193,61 +189,85 @@ linkExpr hsc_env pcs (root_ul_bco, aux_ul_bcos)
         ce = closure_env pls
 
        -- Link the necessary packages and linkables
-   ; (_, (root_hval:_)) <- linkSomeBCOs False ie ce all_bcos
+   ; (_, (root_hval:_)) <- linkSomeBCOs False ie ce [root_ul_bco]
    ; return root_hval
-   }}}
+   }}
    where
      pit    = eps_PIT (pcs_EPS pcs)
      hpt    = hsc_HPT hsc_env
      dflags = hsc_dflags hsc_env
-     all_bcos   = root_ul_bco : aux_ul_bcos
-     free_names = nameSetToList (bcosFreeNames all_bcos)
-  
+     free_names = nameSetToList (bcoFreeNames root_ul_bco)
+
      needed_mods :: [Module]
      needed_mods = [ nameModule n | n <- free_names, isExternalName n ]
  
 dieWith msg = throwDyn (UsageError (showSDoc msg))
 
 getLinkDeps :: HomePackageTable -> PackageIfaceTable
-           -> [Module]                                 -- If you need these
-           -> Either Message
-                     ([Linkable], [PackageName])       -- ... then link these first
+           -> [Module]                         -- If you need these
+           -> IO ([Linkable], [PackageName])   -- ... then link these first
+-- Fails with an IO exception if it can't find enough files
 
+getLinkDeps hpt pit mods
 -- Find all the packages and linkables that a set of modules depends on
+ = do {        pls <- readIORef v_PersistentLinkerState ;
+       let {
+       -- 1.  Find the dependent home-pkg-modules/packages from each iface
+           (mods_s, pkgs_s) = unzip (map get_deps mods) ;
+
+       -- 2.  Exclude ones already linked
+       --      Main reason: avoid findModule calls in get_linkable
+           mods_needed = nub (concat mods_s) `minusList` linked_mods     ;
+           pkgs_needed = nub (concat pkgs_s) `minusList` pkgs_loaded pls ;
+
+           linked_mods = map linkableModName (objs_loaded pls ++ bcos_loaded pls)
+       } ;
+       
+       -- 3.  For each dependent module, find its linkable
+       --     This will either be in the HPT or (in the case of one-shot
+       --     compilation) we may need to use maybe_getFileLinkable
+       lnks_needed <- mapM get_linkable mods_needed ;
 
-getLinkDeps hpt pit mods
-  = go []      -- Linkables so far
-       []      -- Packages so far
-       []      -- Modules dealt with
-       (map moduleName mods)   -- The usage info that we use for 
-                               -- dependencies has ModuleNames not Modules
+       return (lnks_needed, pkgs_needed) }
   where
-     go lnks pkgs _        [] = Right (lnks,pkgs)
-     go lnks pkgs mods_done (mod:mods) 
-       | mod `elem` mods_done 
-       =       -- Already dealt with
-         go lnks pkgs mods_done mods   
-
-       | Just mod_info <- lookupModuleEnvByName hpt mod 
-       =       -- OK, so it's a home module
-         let
-            mod_deps = [m | (m,_,_,_) <- mi_usages (hm_iface mod_info)]
-               -- Get the modules that this one depends on
-         in
-         go (hm_linkable mod_info : lnks) pkgs (mod : mods_done) (mod_deps ++ mods)
-
-       | Just pkg_iface <- lookupModuleEnvByName pit mod 
-       =       -- It's a package module, so add it to the package list
-         let
-            pkg_name = mi_package pkg_iface
-            pkgs' | pkg_name `elem` pkgs = pkgs
-                  | otherwise            = pkg_name : pkgs
-         in
-         go lnks pkgs' (mod : mods_done) mods
-
+    get_deps :: Module -> ([ModuleName],[PackageName])
+       -- Get the things needed for the specified module
+       -- This is rather similar to the code in RnNames.importsFromImportDecl
+    get_deps mod
+       | isHomeModule (mi_module iface) 
+       = (moduleName mod : [m | (m,_) <- dep_mods deps], dep_pkgs deps)
        | otherwise
-       =       -- Not in either table
-         Left (ptext SLIT("Can't find compiled code for dependent module") <+> ppr mod)
+       = ([], mi_package iface : dep_pkgs deps)
+       where
+         iface = get_iface mod
+         deps  = mi_deps iface
+
+    get_iface mod = case lookupIface hpt pit mod of
+                           Just iface -> iface
+                           Nothing    -> pprPanic "getLinkDeps" (no_iface mod)
+    no_iface mod = ptext SLIT("No iface for") <+> ppr mod
+       -- This one is a GHC bug
+
+    no_obj mod = dieWith (ptext SLIT("No compiled code for") <+> ppr mod)
+       -- This one is a build-system bug
+
+    get_linkable mod_name      -- A home-package module
+       | Just mod_info <- lookupModuleEnvByName hpt mod_name 
+       = return (hm_linkable mod_info)
+       | otherwise     
+       =       -- It's not in the HPT because we are in one shot mode, 
+               -- so use the Finder to get a ModLocation...
+         do { mb_stuff <- findModule mod_name ;
+              case mb_stuff of {
+                 Nothing -> no_obj mod_name ;
+                 Just (_, loc) -> do {
+
+               -- ...and then find the linkable for it
+              mb_lnk <- findLinkable mod_name loc ;
+              case mb_lnk of {
+                 Nothing -> no_obj mod_name ;
+                 Just lnk -> return lnk
+         }}}} 
 \end{code}                       
 
 
@@ -364,7 +384,8 @@ linkLibraries :: DynFlags
 -- specified on the command line. 
 linkLibraries dflags objs
    = do        { lib_paths <- readIORef v_Library_paths
-       ; minus_ls  <- readIORef v_Cmdline_libraries
+       ; opt_l  <- getStaticOpts v_Opt_l
+       ; let minus_ls = [ lib | '-':'l':lib <- opt_l ]
         ; let cmdline_lib_specs = map Object objs ++ map DLL minus_ls
        
        ; if (null cmdline_lib_specs) then return () 
@@ -463,7 +484,7 @@ linkSomeBCOs :: Bool        -- False <=> add _all_ BCOs to returned closure env
                                        
 
 linkSomeBCOs toplevs_only ie ce_in ul_bcos
-   = do let nms = map nameOfUnlinkedBCO ul_bcos
+   = do let nms = map unlinkedBCOName ul_bcos
         hvals <- fixIO 
                     ( \ hvs -> let ce_out = extendClosureEnv ce_in (zipLazy nms hvs)
                                in  mapM (linkBCO ie ce_out) ul_bcos )
@@ -610,6 +631,13 @@ linkPackages :: DynFlags -> [PackageName] -> IO ()
 -- (unless of course they are already linked)
 -- The dependents are linked automatically, and it doesn't matter
 -- what order you specify the input packages.
+--
+-- NOTE: in fact, since each module tracks all the packages it depends on,
+--      we don't really need to use the package-config dependencies.
+-- However we do need the package-config stuff (to find aux libs etc),
+-- and following them lets us load libraries in the right order, which 
+-- perhaps makes the error message a bit more localised if we get a link
+-- failure.  So the dependency walking code is still here.
 
 linkPackages dflags new_pkgs
    = do        { pls     <- readIORef v_PersistentLinkerState
@@ -644,6 +672,7 @@ linkPackage dflags pkg
    = do 
         let dirs      =  Packages.library_dirs pkg
         let libs      =  Packages.hs_libraries pkg ++ extra_libraries pkg
+                               ++ [ lib | '-':'l':lib <- extra_ld_opts pkg ]
         classifieds   <- mapM (locateOneObj dirs) libs
 #ifdef darwin_TARGET_OS
         let fwDirs    =  Packages.framework_dirs pkg