| ... | 
... | 
@@ -28,6 +28,7 @@ module GHC.Linker.Loader | 
| 
28
 | 
28
 | 
    , withExtendedLoadedEnv
  | 
| 
29
 | 
29
 | 
    , extendLoadedEnv
  | 
| 
30
 | 
30
 | 
    , deleteFromLoadedEnv
  | 
| 
 
 | 
31
 | 
+   , lookupFromLoadedEnv
  | 
| 
31
 | 
32
 | 
    -- * Internals
  | 
| 
32
 | 
33
 | 
    , allocateBreakArrays
  | 
| 
33
 | 
34
 | 
    , rmDupLinkables
  | 
| ... | 
... | 
@@ -213,6 +214,15 @@ deleteFromLoadedEnv interp to_remove = | 
| 
213
 | 
214
 | 
     return $ modifyClosureEnv pls $ \ce ->
  | 
| 
214
 | 
215
 | 
       delListFromNameEnv ce to_remove
  | 
| 
215
 | 
216
 | 
 
  | 
| 
 
 | 
217
 | 
+-- | Have we already loaded a name into the interpreter?
  | 
| 
 
 | 
218
 | 
+lookupFromLoadedEnv :: Interp -> Name -> IO (Maybe ForeignHValue)
  | 
| 
 
 | 
219
 | 
+lookupFromLoadedEnv interp name = do
  | 
| 
 
 | 
220
 | 
+  mstate <- getLoaderState interp
  | 
| 
 
 | 
221
 | 
+  return $ do
  | 
| 
 
 | 
222
 | 
+    pls <- mstate
  | 
| 
 
 | 
223
 | 
+    res <- lookupNameEnv (closure_env (linker_env pls)) name
  | 
| 
 
 | 
224
 | 
+    return (snd res)
  | 
| 
 
 | 
225
 | 
+
  | 
| 
216
 | 
226
 | 
 -- | Load the module containing the given Name and get its associated 'HValue'.
  | 
| 
217
 | 
227
 | 
 --
  | 
| 
218
 | 
228
 | 
 -- Throws a 'ProgramError' if loading fails or the name cannot be found.
  | 
| ... | 
... | 
@@ -258,7 +268,7 @@ loadDependencies interp hsc_env pls span needed_mods = do | 
| 
258
 | 
268
 | 
 
  | 
| 
259
 | 
269
 | 
    -- Link the packages and modules required
  | 
| 
260
 | 
270
 | 
    pls1 <- loadPackages' interp hsc_env (ldUnits deps) pls
  | 
| 
261
 | 
 
 | 
-   (pls2, succ) <- loadModuleLinkables interp hsc_env pls1 (ldNeededLinkables deps)
  | 
| 
 
 | 
271
 | 
+   (pls2, succ) <- loadExternalModuleLinkables interp hsc_env pls1 (ldNeededLinkables deps)
  | 
| 
262
 | 
272
 | 
    let this_pkgs_loaded = udfmRestrictKeys all_pkgs_loaded $ getUniqDSet trans_pkgs_needed
  | 
| 
263
 | 
273
 | 
        all_pkgs_loaded = pkgs_loaded pls2
  | 
| 
264
 | 
274
 | 
        trans_pkgs_needed = unionManyUniqDSets (this_pkgs_needed : [ loaded_pkg_trans_deps pkg
  | 
| ... | 
... | 
@@ -684,42 +694,23 @@ get_reachable_nodes hsc_env mods | 
| 
684
 | 
694
 | 
 
  | 
| 
685
 | 
695
 | 
   ********************************************************************* -}
  | 
| 
686
 | 
696
 | 
 
  | 
| 
687
 | 
 
 | 
-loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([(Name, ForeignHValue)], [Linkable], PkgsLoaded)
  | 
| 
 
 | 
697
 | 
+-- | Load the dependencies of a linkable, and then load the linkable itself.
  | 
| 
 
 | 
698
 | 
+loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([Linkable], PkgsLoaded)
  | 
| 
688
 | 
699
 | 
 loadDecls interp hsc_env span linkable = do
  | 
| 
689
 | 
700
 | 
     -- Initialise the linker (if it's not been done already)
  | 
| 
690
 | 
701
 | 
     initLoaderState interp hsc_env
  | 
| 
691
 | 
702
 | 
 
  | 
| 
692
 | 
703
 | 
     -- Take lock for the actual work.
  | 
| 
693
 | 
704
 | 
     modifyLoaderState interp $ \pls0 -> do
  | 
| 
694
 | 
 
 | 
-      -- Link the foreign objects first; BCOs in linkable are ignored here.
  | 
| 
695
 | 
 
 | 
-      (pls1, objs_ok) <- loadObjects interp hsc_env pls0 [linkable]
  | 
| 
696
 | 
 
 | 
-      when (failed objs_ok) $ throwGhcExceptionIO $ ProgramError "loadDecls: failed to load foreign objects"
  | 
| 
697
 | 
 
 | 
-
  | 
| 
698
 | 
705
 | 
       -- Link the packages and modules required
  | 
| 
699
 | 
 
 | 
-      (pls, ok, links_needed, units_needed) <- loadDependencies interp hsc_env pls1 span needed_mods
  | 
| 
 
 | 
706
 | 
+      (pls, ok, links_needed, units_needed) <- loadDependencies interp hsc_env pls0 span needed_mods
  | 
| 
700
 | 
707
 | 
       if failed ok
  | 
| 
701
 | 
 
 | 
-        then throwGhcExceptionIO (ProgramError "")
  | 
| 
 
 | 
708
 | 
+        then throwGhcExceptionIO (ProgramError "could not load dependencies for decls")
  | 
| 
702
 | 
709
 | 
         else do
  | 
| 
703
 | 
 
 | 
-          -- Link the expression itself
  | 
| 
704
 | 
 
 | 
-          let le  = linker_env pls
  | 
| 
705
 | 
 
 | 
-          let lb  = linked_breaks pls
  | 
| 
706
 | 
 
 | 
-          le2_itbl_env <- linkITbls interp (itbl_env le) (concat $ map bc_itbls cbcs)
  | 
| 
707
 | 
 
 | 
-          le2_addr_env <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le) cbcs
  | 
| 
708
 | 
 
 | 
-          le2_breakarray_env <- allocateBreakArrays interp (breakarray_env lb) (catMaybes $ map bc_breaks cbcs)
  | 
| 
709
 | 
 
 | 
-          le2_ccs_env        <- allocateCCS         interp (ccs_env lb)        (catMaybes $ map bc_breaks cbcs)
  | 
| 
710
 | 
 
 | 
-          let le2 = le { itbl_env = le2_itbl_env
 | 
| 
711
 | 
 
 | 
-                       , addr_env = le2_addr_env }
  | 
| 
712
 | 
 
 | 
-          let lb2 = lb { breakarray_env = le2_breakarray_env
 | 
| 
713
 | 
 
 | 
-                       , ccs_env = le2_ccs_env }
  | 
| 
714
 | 
 
 | 
-
  | 
| 
715
 | 
 
 | 
-          -- Link the necessary packages and linkables
  | 
| 
716
 | 
 
 | 
-          new_bindings <- linkSomeBCOs interp (pkgs_loaded pls) le2 lb2 cbcs
  | 
| 
717
 | 
 
 | 
-          nms_fhvs <- makeForeignNamedHValueRefs interp new_bindings
  | 
| 
718
 | 
 
 | 
-          let ce2  = extendClosureEnv (closure_env le2) nms_fhvs
  | 
| 
719
 | 
 
 | 
-              !pls2 = pls { linker_env = le2 { closure_env = ce2 }
 | 
| 
720
 | 
 
 | 
-                          , linked_breaks = lb2 }
  | 
| 
721
 | 
 
 | 
-          mapM_ (linkSptEntry interp ce2) (concatMap bc_spt_entries cbcs)
  | 
| 
722
 | 
 
 | 
-          return (pls2, (nms_fhvs, links_needed, units_needed))
  | 
| 
 
 | 
710
 | 
+          (pls2, ok2) <- loadInternalModuleLinkables interp hsc_env pls [linkable]
  | 
| 
 
 | 
711
 | 
+          when (failed ok2) $
  | 
| 
 
 | 
712
 | 
+            throwGhcExceptionIO (ProgramError "could not load linkable for decls")
  | 
| 
 
 | 
713
 | 
+          return (pls2, (links_needed, units_needed))
  | 
| 
723
 | 
714
 | 
   where
  | 
| 
724
 | 
715
 | 
     cbcs = linkableBCOs linkable
  | 
| 
725
 | 
716
 | 
 
  | 
| ... | 
... | 
@@ -761,8 +752,29 @@ loadModule interp hsc_env mod = do | 
| 
761
 | 
752
 | 
 
  | 
| 
762
 | 
753
 | 
   ********************************************************************* -}
  | 
| 
763
 | 
754
 | 
 
  | 
| 
764
 | 
 
 | 
-loadModuleLinkables :: Interp -> HscEnv -> LoaderState -> [Linkable] -> IO (LoaderState, SuccessFlag)
  | 
| 
765
 | 
 
 | 
-loadModuleLinkables interp hsc_env pls linkables
  | 
| 
 
 | 
755
 | 
+-- | Which closures from a Linkable to add to the 'ClosureEnv' in the 'LoaderState'
  | 
| 
 
 | 
756
 | 
+data KeepModuleLinkableDefinitions = KeepAllDefinitions -- ^ Keep all definitions
  | 
| 
 
 | 
757
 | 
+                                   | KeepExternalDefinitions -- ^ Only keep external definitions
  | 
| 
 
 | 
758
 | 
+
  | 
| 
 
 | 
759
 | 
+-- | Interpret a 'KeepModuleLinkableDefinitions' specification to a predictate on 'Name'
  | 
| 
 
 | 
760
 | 
+keepDefinitions :: KeepModuleLinkableDefinitions -> (Name -> Bool)
  | 
| 
 
 | 
761
 | 
+keepDefinitions KeepAllDefinitions = const True
  | 
| 
 
 | 
762
 | 
+keepDefinitions KeepExternalDefinitions = isExternalName
  | 
| 
 
 | 
763
 | 
+
  | 
| 
 
 | 
764
 | 
+-- | Load a linkable from a module, and only add externally visible names to the
  | 
| 
 
 | 
765
 | 
+-- environment.
  | 
| 
 
 | 
766
 | 
+loadExternalModuleLinkables :: Interp -> HscEnv -> LoaderState -> [Linkable] -> IO (LoaderState, SuccessFlag)
  | 
| 
 
 | 
767
 | 
+loadExternalModuleLinkables interp hsc_env pls linkables =
  | 
| 
 
 | 
768
 | 
+  loadModuleLinkables interp hsc_env pls KeepExternalDefinitions linkables
  | 
| 
 
 | 
769
 | 
+
  | 
| 
 
 | 
770
 | 
+-- | Load a linkable from a module, and add all the names from the linkable into the
  | 
| 
 
 | 
771
 | 
+-- closure environment.
  | 
| 
 
 | 
772
 | 
+loadInternalModuleLinkables :: Interp -> HscEnv -> LoaderState -> [Linkable] -> IO (LoaderState, SuccessFlag)
  | 
| 
 
 | 
773
 | 
+loadInternalModuleLinkables interp hsc_env pls linkables  =
  | 
| 
 
 | 
774
 | 
+  loadModuleLinkables interp hsc_env pls KeepAllDefinitions linkables
  | 
| 
 
 | 
775
 | 
+
  | 
| 
 
 | 
776
 | 
+loadModuleLinkables :: Interp -> HscEnv -> LoaderState -> KeepModuleLinkableDefinitions -> [Linkable] -> IO (LoaderState, SuccessFlag)
  | 
| 
 
 | 
777
 | 
+loadModuleLinkables interp hsc_env pls keep_spec linkables
  | 
| 
766
 | 
778
 | 
   = mask_ $ do  -- don't want to be interrupted by ^C in here
  | 
| 
767
 | 
779
 | 
 
  | 
| 
768
 | 
780
 | 
         debugTraceMsg (hsc_logger hsc_env) 3 $
  | 
| ... | 
... | 
@@ -777,7 +789,7 @@ loadModuleLinkables interp hsc_env pls linkables | 
| 
777
 | 
789
 | 
         if failed ok_flag then
  | 
| 
778
 | 
790
 | 
                 return (pls1, Failed)
  | 
| 
779
 | 
791
 | 
           else do
  | 
| 
780
 | 
 
 | 
-                pls2 <- dynLinkBCOs interp pls1 bcos
  | 
| 
 
 | 
792
 | 
+                pls2 <- dynLinkBCOs interp pls1 keep_spec bcos
  | 
| 
781
 | 
793
 | 
                 return (pls2, Succeeded)
  | 
| 
782
 | 
794
 | 
   where
  | 
| 
783
 | 
795
 | 
     (objs, bcos) = partitionLinkables linkables
  | 
| ... | 
... | 
@@ -920,8 +932,8 @@ rmDupLinkables already ls | 
| 
920
 | 
932
 | 
   ********************************************************************* -}
  | 
| 
921
 | 
933
 | 
 
  | 
| 
922
 | 
934
 | 
 
  | 
| 
923
 | 
 
 | 
-dynLinkBCOs :: Interp -> LoaderState -> [Linkable] -> IO LoaderState
  | 
| 
924
 | 
 
 | 
-dynLinkBCOs interp pls bcos = do
  | 
| 
 
 | 
935
 | 
+dynLinkBCOs :: Interp -> LoaderState -> KeepModuleLinkableDefinitions -> [Linkable] -> IO LoaderState
  | 
| 
 
 | 
936
 | 
+dynLinkBCOs interp pls keep_spec bcos = do
  | 
| 
925
 | 
937
 | 
 
  | 
| 
926
 | 
938
 | 
         let (bcos_loaded', new_bcos) = rmDupLinkables (bcos_loaded pls) bcos
  | 
| 
927
 | 
939
 | 
             pls1                     = pls { bcos_loaded = bcos_loaded' }
 | 
| ... | 
... | 
@@ -945,7 +957,7 @@ dynLinkBCOs interp pls bcos = do | 
| 
945
 | 
957
 | 
         names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 lb2 cbcs
  | 
| 
946
 | 
958
 | 
 
  | 
| 
947
 | 
959
 | 
         -- We only want to add the external ones to the ClosureEnv
  | 
| 
948
 | 
 
 | 
-        let (to_add, to_drop) = partition (isExternalName.fst) names_and_refs
  | 
| 
 
 | 
960
 | 
+        let (to_add, to_drop) = partition (keepDefinitions keep_spec . fst) names_and_refs
  | 
| 
949
 | 
961
 | 
 
  | 
| 
950
 | 
962
 | 
         -- Immediately release any HValueRefs we're not going to add
  | 
| 
951
 | 
963
 | 
         freeHValueRefs interp (map snd to_drop)
  |