[project @ 2000-11-20 13:39:26 by sewardj]
[ghc-hetmet.git] / ghc / compiler / compMan / CmLink.lhs
1 %
2 % (c) The University of Glasgow, 2000
3 %
4 \section[CmLink]{Linker for GHCI}
5
6 \begin{code}
7 module CmLink ( Linkable(..),  Unlinked(..),
8                 filterModuleLinkables, 
9                 findModuleLinkable_maybe,
10                 modname_of_linkable, is_package_linkable,
11                 LinkResult(..),
12                 link, 
13                 unload,
14                 PersistentLinkerState{-abstractly!-}, emptyPLS,
15                 linkExpr
16   ) where
17
18
19 import Interpreter
20 import DriverPipeline
21 import CmTypes
22 import CmStaticInfo     ( GhciMode(..) )
23 import Outputable       ( SDoc )
24 import Digraph          ( SCC(..), flattenSCC )
25 import DriverUtil
26 import Module           ( ModuleName, PackageName )
27 import RdrName
28 import FiniteMap
29 import Outputable
30 import Panic            ( panic )
31
32 import Exception
33 import IO
34
35 #include "HsVersions.h"
36 \end{code}
37
38 \begin{code}
39 data PersistentLinkerState 
40    = PersistentLinkerState {
41
42 #ifdef GHCI
43         -- Current global mapping from RdrNames to closure addresses
44         closure_env :: ClosureEnv,
45
46         -- the current global mapping from RdrNames of DataCons to 
47         -- info table addresses.
48         -- When a new Unlinked is linked into the running image, or an existing
49         -- module in the image is replaced, the itbl_env must be updated
50         -- appropriately.
51         itbl_env    :: ItblEnv
52
53         -- notionally here, but really lives in the C part of the linker:
54         --            object_symtab :: FiniteMap String Addr
55 #else
56         dummy :: ()     --  sigh, can't have an empty record
57 #endif
58
59      }
60
61 data LinkResult 
62    = LinkOK   PersistentLinkerState
63    | LinkErrs PersistentLinkerState [SDoc]
64
65 findModuleLinkable_maybe :: [Linkable] -> ModuleName -> Maybe Linkable
66 findModuleLinkable_maybe lis mod 
67    = case [LM time nm us | LM time nm us <- lis, nm == mod] of
68         []   -> Nothing
69         [li] -> Just li
70         many -> pprPanic "findModuleLinkable" (ppr mod)
71
72
73 emptyPLS :: IO PersistentLinkerState
74 #ifdef GHCI
75 emptyPLS = return (PersistentLinkerState { closure_env = emptyFM, 
76                                            itbl_env    = emptyFM })
77 #else
78 emptyPLS = return (PersistentLinkerState {})
79 #endif
80 \end{code}
81
82 \begin{code}
83 link :: GhciMode                -- interactive or batch
84      -> Bool                    -- attempt linking in batch mode?
85      -> [Linkable]              -- only contains LMs, not LPs
86      -> PersistentLinkerState 
87      -> IO LinkResult
88
89 -- For the moment, in the batch linker, we don't bother to tell doLink
90 -- which packages to link -- it just tries all that are available.
91 -- batch_attempt_linking should only be *looked at* in batch mode.  It
92 -- should only be True if the upsweep was successful and someone
93 -- exports main, i.e., we have good reason to believe that linking
94 -- will succeed.
95
96 -- There will be (ToDo: are) two lists passed to link.  These
97 -- correspond to
98 --
99 --      1. The list of all linkables in the current home package.  This is
100 --         used by the batch linker to link the program, and by the interactive
101 --         linker to decide which modules from the previous link it can 
102 --         throw away.
103 --      2. The list of modules on which we just called "compile".  This list
104 --         is used by the interactive linker to decide which modules need
105 --         to be actually linked this time around (or unlinked and re-linked 
106 --         if the module was recompiled).
107
108 link mode batch_attempt_linking linkables pls1
109    = do hPutStrLn stderr "CmLink.link: linkables are ..."
110         hPutStrLn stderr (showSDoc (vcat (map ppr linkables)))
111         res <- link' mode batch_attempt_linking linkables pls1
112         hPutStrLn stderr "CmLink.link: done"
113         return res
114
115 link' Batch batch_attempt_linking linkables pls1
116    | batch_attempt_linking
117    = do let o_files = concatMap getOfiles linkables
118         doLink o_files
119         -- doLink only returns if it succeeds
120         return (LinkOK pls1)
121    | otherwise
122    = do hPutStrLn stderr "CmLink.link(batch): upsweep (partially?) failed OR main not exported;"
123         hPutStrLn stderr "               -- not doing linking"
124         return (LinkOK pls1)
125    where
126       getOfiles (LP _)    = panic "CmLink.link(getOfiles): shouldn't get package linkables"
127       getOfiles (LM _ _ us) = map nameOfObject (filter isObject us)
128
129 link' Interactive batch_attempt_linking linkables pls1
130     = linkObjs linkables pls1
131         
132
133 ppLinkableSCC :: SCC Linkable -> SDoc
134 ppLinkableSCC = ppr . flattenSCC
135
136
137 modname_of_linkable (LM _ nm _) = nm
138 modname_of_linkable (LP _)      = panic "modname_of_linkable: package"
139
140 is_package_linkable (LP _)     = True
141 is_package_linkable (LM _ _ _) = False
142
143 filterModuleLinkables :: (ModuleName -> Bool) 
144                       -> [Linkable] 
145                       -> [Linkable]
146 filterModuleLinkables p [] = []
147 filterModuleLinkables p (li:lis)
148    = case li of
149         LP _         -> retain
150         LM _ modnm _ -> if p modnm then retain else dump
151      where
152         dump   = filterModuleLinkables p lis
153         retain = li : dump
154
155 -----------------------------------------------------------------------------
156 -- Linker for interactive mode
157
158 #ifndef GHCI
159 linkObjs      = panic "CmLink.linkObjs: no interpreter"
160 unload        = panic "CmLink.unload: no interpreter"
161 lookupClosure = panic "CmLink.lookupClosure: no interpreter"
162 #else
163 linkObjs [] pls = linkFinish pls [] []
164 linkObjs (l@(LM _ _ uls) : ls) pls
165    | all isObject uls = do
166         mapM_ loadObj [ file | DotO file <- uls ] 
167         linkObjs ls pls
168    | all isInterpretable uls  = linkInterpretedCode (l:ls) [] [] pls
169    | otherwise                = invalidLinkable
170 linkObjs _ pls = 
171    throwDyn (OtherError "CmLink.linkObjs: found package linkable")
172
173  
174 linkInterpretedCode [] mods ul_trees pls = linkFinish pls mods ul_trees
175 linkInterpretedCode (LM _ m uls : ls) mods ul_trees pls
176    | all isInterpretable uls = 
177         linkInterpretedCode ls (m:mods) (uls++ul_trees) pls
178         
179    | any isObject uls
180         = throwDyn (OtherError "can't link object code that depends on interpreted code")
181    | otherwise = invalidLinkable
182 linkInterpretedCode _ _ _ pls = 
183    throwDyn (OtherError "CmLink.linkInterpretedCode: found package linkable")
184
185 invalidLinkable = throwDyn (OtherError "linkable doesn't contain entirely objects interpreted code")
186
187
188 -- link all the interpreted code in one go.  We first remove from the
189 -- various environments any previous versions of these modules.
190 linkFinish pls mods ul_trees = do
191    resolveObjs
192    let itbl_env'    = filterRdrNameEnv mods (itbl_env pls)
193        closure_env' = filterRdrNameEnv mods (closure_env pls)
194        stuff        = [ (trees,itbls) | Trees trees itbls <- ul_trees ]
195
196    (ibinds, new_itbl_env, new_closure_env) <-
197         linkIModules itbl_env' closure_env' stuff
198
199    let new_pls = PersistentLinkerState {
200                                   closure_env = new_closure_env,
201                                   itbl_env    = new_itbl_env
202                         }
203    putStrLn (showSDoc (vcat (map ppr (keysFM new_closure_env))))
204    return (LinkOK new_pls)
205
206 -- purge the current "linked image"
207 unload :: PersistentLinkerState -> IO PersistentLinkerState
208 unload pls = return pls{ closure_env = emptyFM, itbl_env = emptyFM }
209
210 linkExpr :: PersistentLinkerState -> UnlinkedIExpr -> IO HValue
211 linkExpr PersistentLinkerState{ itbl_env = ie, closure_env = ce } expr
212   = iExprToHValue ie ce expr
213 #endif
214 \end{code}