diff --git a/compiler/GHC/Driver/Main.hs b/compiler/GHC/Driver/Main.hs index 7233ffff6122f46aaf426257458166bd94775a66..a514b76198d021c79085e1a4e68014bcddf4edd2 100644 --- a/compiler/GHC/Driver/Main.hs +++ b/compiler/GHC/Driver/Main.hs @@ -148,6 +148,7 @@ import GHC.ByteCode.Types import GHC.Linker.Loader import GHC.Linker.Types +import GHC.Linker.Deps import GHC.Hs import GHC.Hs.Dump @@ -2578,7 +2579,7 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do tidy_expr {- Lint if necessary -} - lintInteractiveExpr (text "hscCompileExpr") hsc_env prepd_expr + lintInteractiveExpr (text "hscCompileCoreExpr") hsc_env prepd_expr let this_loc = ModLocation{ ml_hs_file = Nothing, ml_hi_file = panic "hscCompileCoreExpr':ml_hi_file", ml_obj_file = panic "hscCompileCoreExpr':ml_obj_file", @@ -2592,7 +2593,7 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do -- files for the same module and the JS linker doesn't support this. -- -- Note that we can't use icInteractiveModule because the ic_mod_index value - -- isn't bumped between invocations of hscCompileExpr, so uniqueness isn't + -- isn't bumped between invocations of hscCompileCoreExpr, so uniqueness isn't -- guaranteed. -- -- We reuse the unique we obtained for the binding, but any unique would do. @@ -2611,14 +2612,11 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do let (stg_binds, _stg_deps) = unzip stg_binds_with_deps let interp = hscInterp hsc_env - let tmpfs = hsc_tmpfs hsc_env - let tmp_dir = tmpDir dflags case interp of -- always generate JS code for the JS interpreter (no bytecode!) Interp (ExternalInterp (ExtJS i)) _ -> - jsCodeGen logger tmpfs tmp_dir unit_env (initStgToJSConfig dflags) interp i - this_mod stg_binds binding_id + jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id _ -> do {- Convert to BCOs -} @@ -2637,18 +2635,70 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do -- | Generate JS code for the given bindings and return the HValue for the given id jsCodeGen - :: Logger - -> TmpFs - -> TempDir - -> UnitEnv - -> StgToJSConfig - -> Interp + :: HscEnv + -> SrcSpan -> JSInterp -> Module - -> [CgStgTopBinding] + -> [(CgStgTopBinding,IdSet)] -> Id -> IO (ForeignHValue, [Linkable], PkgsLoaded) -jsCodeGen logger tmpfs tmp_dir unit_env js_config interp i this_mod stg_binds binding_id = do +jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do + let logger = hsc_logger hsc_env + tmpfs = hsc_tmpfs hsc_env + dflags = hsc_dflags hsc_env + interp = hscInterp hsc_env + tmp_dir = tmpDir dflags + unit_env = hsc_unit_env hsc_env + js_config = initStgToJSConfig dflags + + -- We need to load all the dependencies first. + -- + -- We get all the imported names from the Stg bindings and load their modules. + -- + -- (logic adapted from GHC.Linker.Loader.loadDecls for the JS linker) + let + (stg_binds, stg_deps) = unzip stg_binds_with_deps + imported_ids = nonDetEltsUniqSet (unionVarSets stg_deps) + imported_names = map idName imported_ids + + needed_mods :: [Module] + needed_mods = [ nameModule n | n <- imported_names, + isExternalName n, -- Names from other modules + not (isWiredInName n) -- Exclude wired-in names + ] -- (see note below) + -- Exclude wired-in names because we may not have read + -- their interface files, so getLinkDeps will fail + -- All wired-in names are in the base package, which we link + -- by default, so we can safely ignore them here. + + -- Initialise the linker (if it's not been done already) + initLoaderState interp hsc_env + + -- Take lock for the actual work. + (dep_linkables, dep_units) <- modifyLoaderState interp $ \pls -> do + let link_opts = initLinkDepsOpts hsc_env + + -- Find what packages and linkables are required + deps <- getLinkDeps link_opts interp pls srcspan needed_mods + -- We update the LinkerState even if the JS interpreter maintains its linker + -- state independently to load new objects here. + let (objs, _bcos) = partition isObjectLinkable + (concatMap partitionLinkable (ldNeededLinkables deps)) + + let (objs_loaded', _new_objs) = rmDupLinkables (objs_loaded pls) objs + + -- FIXME: we should make the JS linker load new_objs here, instead of + -- on-demand. + + -- FIXME: we don't report needed units because we would have to find a way + -- to build a meaningful LoadedPkgInfo (see the mess in + -- GHC.Linker.Loader.{loadPackage,loadPackages'}). Detecting what to load + -- and actually loading (using the native interpreter) are intermingled, so + -- we can't directly reuse this code. + let pls' = pls { objs_loaded = objs_loaded' } + pure (pls', (ldAllLinkables deps, emptyUDFM {- ldNeededUnits deps -}) ) + + let foreign_stubs = NoStubs spt_entries = mempty cost_centre_info = mempty @@ -2671,12 +2721,7 @@ jsCodeGen logger tmpfs tmp_dir unit_env js_config interp i this_mod stg_binds bi binding_fref <- withJSInterp i $ \inst -> mkForeignRef href (freeReallyRemoteRef inst href) - -- FIXME (#23013): the JS linker doesn't use the LoaderState. - -- The state is only maintained in the interpreter instance (jsLinkState field) for now. - let linkables = mempty - let loaded_pkgs = emptyUDFM - - return (castForeignRef binding_fref, linkables, loaded_pkgs) + return (castForeignRef binding_fref, dep_linkables, dep_units) {- ********************************************************************** diff --git a/compiler/GHC/Linker/Loader.hs b/compiler/GHC/Linker/Loader.hs index aaea2936fbf385d1e3597b5b8cadf43e89f5dea4..fe19df150b9771d88b9566390ab2c861531fb02c 100644 --- a/compiler/GHC/Linker/Loader.hs +++ b/compiler/GHC/Linker/Loader.hs @@ -29,6 +29,11 @@ module GHC.Linker.Loader , withExtendedLoadedEnv , extendLoadedEnv , deleteFromLoadedEnv + -- * Internals + , rmDupLinkables + , modifyLoaderState + , initLinkDepsOpts + , partitionLinkable ) where @@ -282,15 +287,22 @@ reallyInitLoaderState interp hsc_env = do -- Initialise the linker state let pls0 = emptyLoaderState - -- (a) initialise the C dynamic linker - initObjLinker interp + case platformArch (targetPlatform (hsc_dflags hsc_env)) of + -- FIXME: we don't initialize anything with the JS interpreter. + -- Perhaps we should load preload packages. We'll load them on demand + -- anyway. + ArchJavaScript -> return pls0 + _ -> do + -- (a) initialise the C dynamic linker + initObjLinker interp - -- (b) Load packages from the command-line (Note [preload packages]) - pls <- unitEnv_foldWithKey (\k u env -> k >>= \pls' -> loadPackages' interp (hscSetActiveUnitId u hsc_env) (preloadUnits (homeUnitEnv_units env)) pls') (return pls0) (hsc_HUG hsc_env) - -- steps (c), (d) and (e) - loadCmdLineLibs' interp hsc_env pls + -- (b) Load packages from the command-line (Note [preload packages]) + pls <- unitEnv_foldWithKey (\k u env -> k >>= \pls' -> loadPackages' interp (hscSetActiveUnitId u hsc_env) (preloadUnits (homeUnitEnv_units env)) pls') (return pls0) (hsc_HUG hsc_env) + + -- steps (c), (d) and (e) + loadCmdLineLibs' interp hsc_env pls loadCmdLineLibs :: Interp -> HscEnv -> IO () diff --git a/testsuite/tests/driver/recomp009/all.T b/testsuite/tests/driver/recomp009/all.T index 83a811ca68d551f738453f095e312f37001bf8eb..33c36f7ea3d8ba7dd13871bdb5013383015a8a5d 100644 --- a/testsuite/tests/driver/recomp009/all.T +++ b/testsuite/tests/driver/recomp009/all.T @@ -1,3 +1,3 @@ # Test for #481, a recompilation bug with Template Haskell -test('recomp009', [req_th, js_broken(23013), extra_files(['Main.hs', 'Sub1.hs', 'Sub2.hs'])], makefile_test, []) +test('recomp009', [req_th, extra_files(['Main.hs', 'Sub1.hs', 'Sub2.hs'])], makefile_test, []) diff --git a/testsuite/tests/driver/recompTH/all.T b/testsuite/tests/driver/recompTH/all.T index 238f7aa2749248ab8187ad2f5868b7fa72d64a5d..8d75ed0308ffaeb513e34a0ec052ca98d717420c 100644 --- a/testsuite/tests/driver/recompTH/all.T +++ b/testsuite/tests/driver/recompTH/all.T @@ -1,4 +1,4 @@ -test('recompTH', [req_th, js_broken(23013), extra_files(['A.hs', 'B1.hs', 'B2.hs' ]), +test('recompTH', [req_th, extra_files(['A.hs', 'B1.hs', 'B2.hs' ]), when(fast(), skip) , normalise_slashes], makefile_test, []) diff --git a/testsuite/tests/driver/th-new-test/all.T b/testsuite/tests/driver/th-new-test/all.T index a5072178b4be450677c99af63ebe4794e532be18..54dd7852beb639b3587a7882be1ca1509ae4890f 100644 --- a/testsuite/tests/driver/th-new-test/all.T +++ b/testsuite/tests/driver/th-new-test/all.T @@ -1,4 +1,4 @@ -test('th-new-test', [req_th, js_broken(23013), extra_files(['A.hs', 'B.hs', 'C.hs', 'D.hs', 'B1.hs', 'D1.hs', 'Main.hs']), +test('th-new-test', [req_th, extra_files(['A.hs', 'B.hs', 'C.hs', 'D.hs', 'B1.hs', 'D1.hs', 'Main.hs']), when(fast(), skip) , normalise_slashes], makefile_test, [])