summaryrefslogtreecommitdiff
path: root/compiler/GHC/Driver
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-11-12 10:36:58 +0100
committerSylvain Henry <sylvain@haskus.fr>2020-12-14 19:45:13 +0100
commitd0e8c10d587e4b9984526d0dfcfcb258b75733b8 (patch)
treee0993719d76f87a0f4f8eccef089526217bf5bb4 /compiler/GHC/Driver
parent92377c27e1a48d0d3776f65c7074dfeb122b46db (diff)
downloadhaskell-d0e8c10d587e4b9984526d0dfcfcb258b75733b8.tar.gz
Move Unit related fields from DynFlags to HscEnv
The unit database cache, the home unit and the unit state were stored in DynFlags while they ought to be stored in the compiler session state (HscEnv). This patch fixes this. It introduces a new UnitEnv type that should be used in the future to handle separate unit environments (especially host vs target units). Related to #17957 Bump haddock submodule
Diffstat (limited to 'compiler/GHC/Driver')
-rw-r--r--compiler/GHC/Driver/Backpack.hs170
-rw-r--r--compiler/GHC/Driver/CodeOutput.hs11
-rw-r--r--compiler/GHC/Driver/Env.hs33
-rw-r--r--compiler/GHC/Driver/Hooks.hs3
-rw-r--r--compiler/GHC/Driver/Main.hs49
-rw-r--r--compiler/GHC/Driver/Make.hs31
-rw-r--r--compiler/GHC/Driver/MakeFile.hs4
-rw-r--r--compiler/GHC/Driver/Pipeline.hs367
-rw-r--r--compiler/GHC/Driver/Pipeline/Monad.hs6
-rw-r--r--compiler/GHC/Driver/Ppr.hs11
-rw-r--r--compiler/GHC/Driver/Session.hs48
-rw-r--r--compiler/GHC/Driver/Session.hs-boot2
12 files changed, 382 insertions, 353 deletions
diff --git a/compiler/GHC/Driver/Backpack.hs b/compiler/GHC/Driver/Backpack.hs
index d38ba98622..b86ef6281b 100644
--- a/compiler/GHC/Driver/Backpack.hs
+++ b/compiler/GHC/Driver/Backpack.hs
@@ -56,6 +56,7 @@ import GHC.Utils.Panic
import GHC.Utils.Error
import GHC.Unit
+import GHC.Unit.Env
import GHC.Unit.External
import GHC.Unit.State
import GHC.Unit.Finder
@@ -69,6 +70,7 @@ import qualified GHC.LanguageExtensions as LangExt
import GHC.Data.Maybe
import GHC.Data.StringBuffer
import GHC.Data.FastString
+import qualified GHC.Data.EnumSet as EnumSet
import qualified GHC.Data.ShortText as ST
import Data.List ( partition )
@@ -103,8 +105,8 @@ doBackpack [src_filename] = do
POk _ pkgname_bkp -> do
-- OK, so we have an LHsUnit PackageName, but we want an
-- LHsUnit HsComponentId. So let's rename it.
- let pkgstate = unitState dflags
- let bkp = renameHsUnits pkgstate (bkpPackageNameMap pkgname_bkp) pkgname_bkp
+ hsc_env <- getSession
+ let bkp = renameHsUnits (hsc_units hsc_env) (bkpPackageNameMap pkgname_bkp) pkgname_bkp
initBkpM src_filename bkp $
forM_ (zip [1..] bkp) $ \(i, lunit) -> do
let comp_name = unLoc (hsunitName (unLoc lunit))
@@ -170,61 +172,67 @@ withBkpSession cid insts deps session_type do_this = do
-- Special case when package is definite
, not (null insts) = sub_comp (key_base p) </> uid_str
| otherwise = sub_comp (key_base p)
- withTempSession (overHscDynFlags (\dflags ->
- -- If we're type-checking an indefinite package, we want to
- -- turn on interface writing. However, if the user also
- -- explicitly passed in `-fno-code`, we DON'T want to write
- -- interfaces unless the user also asked for `-fwrite-interface`.
- -- See Note [-fno-code mode]
- (case session_type of
- -- Make sure to write interfaces when we are type-checking
- -- indefinite packages.
- TcSession | backend dflags /= NoBackend
- -> flip gopt_set Opt_WriteInterface
- | otherwise -> id
- CompSession -> id
- ExeSession -> id) $
- dflags {
- backend = case session_type of
- TcSession -> NoBackend
- _ -> backend dflags,
- homeUnitInstantiations_ = insts,
- -- if we don't have any instantiation, don't
- -- fill `homeUnitInstanceOfId` as it makes no
- -- sense (we're not instantiating anything)
- homeUnitInstanceOf_ = if null insts then Nothing else Just (indefUnit cid),
- homeUnitId_ =
- case session_type of
+
+ mk_temp_env hsc_env = hsc_env
+ { hsc_dflags = mk_temp_dflags (hsc_units hsc_env) (hsc_dflags hsc_env)
+ }
+ mk_temp_dflags unit_state dflags = dflags
+ { backend = case session_type of
+ TcSession -> NoBackend
+ _ -> backend dflags
+ , homeUnitInstantiations_ = insts
+ -- if we don't have any instantiation, don't
+ -- fill `homeUnitInstanceOfId` as it makes no
+ -- sense (we're not instantiating anything)
+ , homeUnitInstanceOf_ = if null insts then Nothing else Just (indefUnit cid)
+ , homeUnitId_ = case session_type of
TcSession -> newUnitId cid Nothing
-- No hash passed if no instances
_ | null insts -> newUnitId cid Nothing
- | otherwise -> newUnitId cid (Just (mkInstantiatedUnitHash cid insts)),
- -- Setup all of the output directories according to our hierarchy
- objectDir = Just (outdir objectDir),
- hiDir = Just (outdir hiDir),
- stubDir = Just (outdir stubDir),
- -- Unset output-file for non exe builds
- outputFile_ = if session_type == ExeSession
- then outputFile_ dflags
- else Nothing,
- dynOutputFile_ = if session_type == ExeSession
- then dynOutputFile_ dflags
- else Nothing,
- -- Clear the import path so we don't accidentally grab anything
- importPaths = [],
- -- Synthesized the flags
- packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->
- let state = unitState dflags
- uid = unwireUnit state (improveUnit state $ renameHoleUnit state (listToUFM insts) uid0)
- in ExposePackage
- (showSDoc dflags
- (text "-unit-id" <+> ppr uid <+> ppr rn))
- (UnitIdArg uid) rn) deps
- } )) $ do
- dflags <- getSessionDynFlags
- -- pprTrace "flags" (ppr insts <> ppr deps) $ return ()
- setSessionDynFlags dflags -- calls initUnits
- do_this
+ | otherwise -> newUnitId cid (Just (mkInstantiatedUnitHash cid insts))
+
+
+ -- If we're type-checking an indefinite package, we want to
+ -- turn on interface writing. However, if the user also
+ -- explicitly passed in `-fno-code`, we DON'T want to write
+ -- interfaces unless the user also asked for `-fwrite-interface`.
+ -- See Note [-fno-code mode]
+ , generalFlags = case session_type of
+ -- Make sure to write interfaces when we are type-checking
+ -- indefinite packages.
+ TcSession
+ | backend dflags /= NoBackend
+ -> EnumSet.insert Opt_WriteInterface (generalFlags dflags)
+ _ -> generalFlags dflags
+
+ -- Setup all of the output directories according to our hierarchy
+ , objectDir = Just (outdir objectDir)
+ , hiDir = Just (outdir hiDir)
+ , stubDir = Just (outdir stubDir)
+ -- Unset output-file for non exe builds
+ , outputFile_ = case session_type of
+ ExeSession -> outputFile_ dflags
+ _ -> Nothing
+ , dynOutputFile_ = case session_type of
+ ExeSession -> dynOutputFile_ dflags
+ _ -> Nothing
+ -- Clear the import path so we don't accidentally grab anything
+ , importPaths = []
+ -- Synthesize the flags
+ , packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->
+ let uid = unwireUnit unit_state
+ $ improveUnit unit_state
+ $ renameHoleUnit unit_state (listToUFM insts) uid0
+ in ExposePackage
+ (showSDoc dflags
+ (text "-unit-id" <+> ppr uid <+> ppr rn))
+ (UnitIdArg uid) rn) deps
+ }
+ withTempSession mk_temp_env $ do
+ dflags <- getSessionDynFlags
+ -- pprTrace "flags" (ppr insts <> ppr deps) $ return ()
+ setSessionDynFlags dflags -- calls initUnits
+ do_this
withBkpExeSession :: [(Unit, ModRenaming)] -> BkpM a -> BkpM a
withBkpExeSession deps do_this =
@@ -278,11 +286,11 @@ buildUnit session cid insts lunit = do
-- any object files.
let deps_w_rns = hsunitDeps (session == TcSession) (unLoc lunit)
raw_deps = map fst deps_w_rns
- dflags <- getDynFlags
+ hsc_env <- getSession
-- The compilation dependencies are just the appropriately filled
-- in unit IDs which must be compiled before we can compile.
let hsubst = listToUFM insts
- deps0 = map (renameHoleUnit (unitState dflags) hsubst) raw_deps
+ deps0 = map (renameHoleUnit (hsc_units hsc_env) hsubst) raw_deps
-- Build dependencies OR make sure they make sense. BUT NOTE,
-- we can only check the ones that are fully filled; the rest
@@ -293,9 +301,8 @@ buildUnit session cid insts lunit = do
TcSession -> return ()
_ -> compileInclude (length deps0) (i, dep)
- dflags <- getDynFlags
-- IMPROVE IT
- let deps = map (improveUnit (unitState dflags)) deps0
+ let deps = map (improveUnit (hsc_units hsc_env)) deps0
mb_old_eps <- case session of
TcSession -> fmap Just getEpsGhc
@@ -324,7 +331,7 @@ buildUnit session cid insts lunit = do
$ home_mod_infos
getOfiles (LM _ _ us) = map nameOfObject (filter isObject us)
obj_files = concatMap getOfiles linkables
- state = unitState (hsc_dflags hsc_env)
+ state = hsc_units hsc_env
let compat_fs = unitIdFS (indefUnit cid)
compat_pn = PackageName compat_fs
@@ -380,7 +387,7 @@ buildUnit session cid insts lunit = do
}
- addPackage conf
+ addUnit conf
case mb_old_eps of
Just old_eps -> updateEpsGhc_ (const old_eps)
_ -> return ()
@@ -400,22 +407,33 @@ compileExe lunit = do
when (failed ok) (liftIO $ exitWith (ExitFailure 1))
-- | Register a new virtual unit database containing a single unit
-addPackage :: GhcMonad m => UnitInfo -> m ()
-addPackage pkg = do
- dflags <- GHC.getSessionDynFlags
- case unitDatabases dflags of
- Nothing -> panic "addPackage: called too early"
- Just dbs -> do
+addUnit :: GhcMonad m => UnitInfo -> m ()
+addUnit u = do
+ hsc_env <- getSession
+ newdbs <- case hsc_unit_dbs hsc_env of
+ Nothing -> panic "addUnit: called too early"
+ Just dbs ->
let newdb = UnitDatabase
- { unitDatabasePath = "(in memory " ++ showSDoc dflags (ppr (unitId pkg)) ++ ")"
- , unitDatabaseUnits = [pkg]
+ { unitDatabasePath = "(in memory " ++ showSDoc (hsc_dflags hsc_env) (ppr (unitId u)) ++ ")"
+ , unitDatabaseUnits = [u]
}
- GHC.setSessionDynFlags (dflags { unitDatabases = Just (dbs ++ [newdb]) })
+ in return (dbs ++ [newdb]) -- added at the end because ordering matters
+ (dbs,unit_state,home_unit) <- liftIO $ initUnits (hsc_dflags hsc_env) (Just newdbs)
+ let unit_env = UnitEnv
+ { ue_platform = targetPlatform (hsc_dflags hsc_env)
+ , ue_namever = ghcNameVersion (hsc_dflags hsc_env)
+ , ue_home_unit = home_unit
+ , ue_units = unit_state
+ }
+ setSession $ hsc_env
+ { hsc_unit_dbs = Just dbs
+ , hsc_unit_env = unit_env
+ }
compileInclude :: Int -> (Int, Unit) -> BkpM ()
compileInclude n (i, uid) = do
hsc_env <- getSession
- let pkgs = unitState (hsc_dflags hsc_env)
+ let pkgs = hsc_units hsc_env
msgInclude (i, n) uid
-- Check if we've compiled it already
case uid of
@@ -469,10 +487,6 @@ getBkpEnv = getEnv
getBkpLevel :: BkpM Int
getBkpLevel = bkp_level `fmap` getBkpEnv
--- | Apply a function on 'DynFlags' on an 'HscEnv'
-overHscDynFlags :: (DynFlags -> DynFlags) -> HscEnv -> HscEnv
-overHscDynFlags f hsc_env = hsc_env { hsc_dflags = f (hsc_dflags hsc_env) }
-
-- | Run a 'BkpM' computation, with the nesting level bumped one.
innerBkpM :: BkpM a -> BkpM a
innerBkpM do_this =
@@ -522,7 +536,7 @@ mkBackpackMsg = do
level <- getBkpLevel
return $ \hsc_env mod_index recomp mod_summary ->
let dflags = hsc_dflags hsc_env
- state = unitState dflags
+ state = hsc_units hsc_env
showMsg msg reason =
backpackProgressMsg level dflags $ pprWithUnitState state $
showModuleIndex mod_index <>
@@ -557,8 +571,9 @@ msgTopPackage (i,n) (HsComponentId (PackageName fs_pn) _) = do
msgUnitId :: Unit -> BkpM ()
msgUnitId pk = do
dflags <- getDynFlags
+ hsc_env <- getSession
level <- getBkpLevel
- let state = unitState dflags
+ let state = hsc_units hsc_env
liftIO . backpackProgressMsg level dflags
$ pprWithUnitState state
$ text "Instantiating "
@@ -568,8 +583,9 @@ msgUnitId pk = do
msgInclude :: (Int,Int) -> Unit -> BkpM ()
msgInclude (i,n) uid = do
dflags <- getDynFlags
+ hsc_env <- getSession
level <- getBkpLevel
- let state = unitState dflags
+ let state = hsc_units hsc_env
liftIO . backpackProgressMsg level dflags
$ pprWithUnitState state
$ showModuleIndex (i, n) <> text "Including "
diff --git a/compiler/GHC/Driver/CodeOutput.hs b/compiler/GHC/Driver/CodeOutput.hs
index 2bb30656dd..b251794f1a 100644
--- a/compiler/GHC/Driver/CodeOutput.hs
+++ b/compiler/GHC/Driver/CodeOutput.hs
@@ -64,6 +64,7 @@ import System.IO
-}
codeOutput :: DynFlags
+ -> UnitState
-> Module
-> FilePath
-> ModLocation
@@ -77,7 +78,7 @@ codeOutput :: DynFlags
[(ForeignSrcLang, FilePath)]{-foreign_fps-},
a)
-codeOutput dflags this_mod filenm location foreign_stubs foreign_fps pkg_deps
+codeOutput dflags unit_state this_mod filenm location foreign_stubs foreign_fps pkg_deps
cmm_stream
=
do {
@@ -104,7 +105,7 @@ codeOutput dflags this_mod filenm location foreign_stubs foreign_fps pkg_deps
; return cmm
}
- ; stubs_exist <- outputForeignStubs dflags this_mod location foreign_stubs
+ ; stubs_exist <- outputForeignStubs dflags unit_state this_mod location foreign_stubs
; a <- case backend dflags of
NCG -> outputAsm dflags this_mod location filenm
linted_cmm_stream
@@ -190,10 +191,10 @@ outputLlvm dflags filenm cmm_stream =
************************************************************************
-}
-outputForeignStubs :: DynFlags -> Module -> ModLocation -> ForeignStubs
+outputForeignStubs :: DynFlags -> UnitState -> Module -> ModLocation -> ForeignStubs
-> IO (Bool, -- Header file created
Maybe FilePath) -- C file created
-outputForeignStubs dflags mod location stubs
+outputForeignStubs dflags unit_state mod location stubs
= do
let stub_h = mkStubPaths dflags (moduleName mod) location
stub_c <- newTempName dflags TFL_CurrentModule "c"
@@ -220,7 +221,7 @@ outputForeignStubs dflags mod location stubs
-- we need the #includes from the rts package for the stub files
let rts_includes =
- let rts_pkg = unsafeLookupUnitId (unitState dflags) rtsUnitId in
+ let rts_pkg = unsafeLookupUnitId unit_state rtsUnitId in
concatMap mk_include (unitIncludes rts_pkg)
mk_include i = "#include \"" ++ ST.unpack i ++ "\"\n"
diff --git a/compiler/GHC/Driver/Env.hs b/compiler/GHC/Driver/Env.hs
index 6bf83c576e..596ea936ca 100644
--- a/compiler/GHC/Driver/Env.hs
+++ b/compiler/GHC/Driver/Env.hs
@@ -4,6 +4,8 @@
module GHC.Driver.Env
( Hsc(..)
, HscEnv (..)
+ , hsc_home_unit
+ , hsc_units
, runHsc
, mkInteractiveHscEnv
, runInteractiveHsc
@@ -17,6 +19,7 @@ module GHC.Driver.Env
, prepareAnnotations
, lookupType
, lookupIfaceByModule
+ , mainModIs
)
where
@@ -38,6 +41,7 @@ import GHC.Unit.Module.ModIface
import GHC.Unit.Module.ModDetails
import GHC.Unit.Module.Deps
import GHC.Unit.Home.ModInfo
+import GHC.Unit.Env
import GHC.Unit.External
import GHC.Unit.Finder.Types
@@ -179,9 +183,6 @@ data HscEnv
, hsc_loader :: Loader
-- ^ Loader (dynamic linker)
- , hsc_home_unit :: !HomeUnit
- -- ^ Home-unit
-
, hsc_plugins :: ![LoadedPlugin]
-- ^ plugins dynamically loaded after processing arguments. What
-- will be loaded here is directed by DynFlags.pluginModNames.
@@ -197,8 +198,31 @@ data HscEnv
--
-- To add dynamically loaded plugins through the GHC API see
-- 'addPluginModuleName' instead.
+
+ , hsc_unit_dbs :: !(Maybe [UnitDatabase UnitId])
+ -- ^ Stack of unit databases for the target platform.
+ --
+ -- This field is populated with the result of `initUnits`.
+ --
+ -- 'Nothing' means the databases have never been read from disk.
+ --
+ -- Usually we don't reload the databases from disk if they are
+ -- cached, even if the database flags changed!
+
+ , hsc_unit_env :: UnitEnv
+ -- ^ Unit environment (unit state, home unit, etc.).
+ --
+ -- Initialized from the databases cached in 'hsc_unit_dbs' and
+ -- from the DynFlags.
}
+
+hsc_home_unit :: HscEnv -> HomeUnit
+hsc_home_unit = ue_home_unit . hsc_unit_env
+
+hsc_units :: HscEnv -> UnitState
+hsc_units = ue_units . hsc_unit_env
+
{-
Note [Target code interpreter]
@@ -392,3 +416,6 @@ lookupIfaceByModule hpt pit mod
-- We could eliminate (b) if we wanted, by making GHC.Prim belong to a package
-- of its own, but it doesn't seem worth the bother.
+mainModIs :: HscEnv -> Module
+mainModIs hsc_env = mkHomeModule (hsc_home_unit hsc_env) (mainModuleNameIs (hsc_dflags hsc_env))
+
diff --git a/compiler/GHC/Driver/Hooks.hs b/compiler/GHC/Driver/Hooks.hs
index 25e6530eef..432297b735 100644
--- a/compiler/GHC/Driver/Hooks.hs
+++ b/compiler/GHC/Driver/Hooks.hs
@@ -136,8 +136,7 @@ data Hooks = Hooks
, hscCompileCoreExprHook ::
Maybe (HscEnv -> SrcSpan -> CoreExpr -> IO ForeignHValue)
, ghcPrimIfaceHook :: Maybe ModIface
- , runPhaseHook :: Maybe (PhasePlus -> FilePath -> DynFlags
- -> CompPipeline (PhasePlus, FilePath))
+ , runPhaseHook :: Maybe (PhasePlus -> FilePath -> CompPipeline (PhasePlus, FilePath))
, runMetaHook :: Maybe (MetaHook TcM)
, linkHook :: Maybe (GhcLink -> DynFlags -> Bool
-> HomePackageTable -> IO SuccessFlag)
diff --git a/compiler/GHC/Driver/Main.hs b/compiler/GHC/Driver/Main.hs
index cd37ac4f3a..8685462e7d 100644
--- a/compiler/GHC/Driver/Main.hs
+++ b/compiler/GHC/Driver/Main.hs
@@ -235,12 +235,16 @@ import Data.Bifunctor (first, bimap)
newHscEnv :: DynFlags -> IO HscEnv
newHscEnv dflags = do
- let home_unit = mkHomeUnitFromFlags dflags
- eps_var <- newIORef (initExternalPackageState home_unit)
+ -- we don't store the unit databases and the unit state to still
+ -- allow `setSessionDynFlags` to be used to set unit db flags.
+ eps_var <- newIORef (initExternalPackageState (homeUnitId_ dflags))
us <- mkSplitUniqSupply 'r'
nc_var <- newIORef (initNameCache us knownKeyNames)
fc_var <- newIORef emptyInstalledModuleEnv
emptyLoader <- uninitializedLoader
+ -- FIXME: it's sad that we have so many "unitialized" fields filled with
+ -- empty stuff or lazy panics. We should have two kinds of HscEnv
+ -- (initialized or not) instead and less fields that are mutable over time.
return HscEnv { hsc_dflags = dflags
, hsc_targets = []
, hsc_mod_graph = emptyMG
@@ -252,9 +256,10 @@ newHscEnv dflags = do
, hsc_type_env_var = Nothing
, hsc_interp = Nothing
, hsc_loader = emptyLoader
- , hsc_home_unit = home_unit
+ , hsc_unit_env = panic "hsc_unit_env not initialized"
, hsc_plugins = []
, hsc_static_plugins = []
+ , hsc_unit_dbs = Nothing
}
-- -----------------------------------------------------------------------------
@@ -1258,6 +1263,7 @@ hscCheckSafe' m l = do
where
isModSafe :: HomeUnit -> Module -> SrcSpan -> Hsc (Bool, Set UnitId)
isModSafe home_unit m l = do
+ hsc_env <- getHscEnv
dflags <- getDynFlags
iface <- lookup' m
case iface of
@@ -1273,7 +1279,7 @@ hscCheckSafe' m l = do
-- check module is trusted
safeM = trust `elem` [Sf_Safe, Sf_SafeInferred, Sf_Trustworthy]
-- check package is trusted
- safeP = packageTrusted dflags home_unit trust trust_own_pkg m
+ safeP = packageTrusted dflags (hsc_units hsc_env) home_unit trust trust_own_pkg m
-- pkg trust reqs
pkgRs = S.fromList . map fst $ filter snd $ dep_pkgs $ mi_deps iface'
-- warn if Safe module imports Safe-Inferred module.
@@ -1293,7 +1299,7 @@ hscCheckSafe' m l = do
return (trust == Sf_Trustworthy, pkgRs)
where
- state = unitState dflags
+ state = hsc_units hsc_env
inferredImportWarn = unitBag
$ makeIntoWarning (Reason Opt_WarnInferredSafeImports)
$ mkWarnMsg dflags l (pkgQual state)
@@ -1318,17 +1324,17 @@ hscCheckSafe' m l = do
-- modules are trusted without requiring that their package is trusted. For
-- trustworthy modules, modules in the home package are trusted but
-- otherwise we check the package trust flag.
- packageTrusted :: DynFlags -> HomeUnit -> SafeHaskellMode -> Bool -> Module -> Bool
- packageTrusted _ _ Sf_None _ _ = False -- shouldn't hit these cases
- packageTrusted _ _ Sf_Ignore _ _ = False -- shouldn't hit these cases
- packageTrusted _ _ Sf_Unsafe _ _ = False -- prefer for completeness.
- packageTrusted dflags _ _ _ _
- | not (packageTrustOn dflags) = True
- packageTrusted _ _ Sf_Safe False _ = True
- packageTrusted _ _ Sf_SafeInferred False _ = True
- packageTrusted dflags home_unit _ _ m
- | isHomeModule home_unit m = True
- | otherwise = unitIsTrusted $ unsafeLookupUnit (unitState dflags) (moduleUnit m)
+ packageTrusted :: DynFlags -> UnitState -> HomeUnit -> SafeHaskellMode -> Bool -> Module -> Bool
+ packageTrusted dflags unit_state home_unit safe_mode trust_own_pkg mod =
+ case safe_mode of
+ Sf_None -> False -- shouldn't hit these cases
+ Sf_Ignore -> False -- shouldn't hit these cases
+ Sf_Unsafe -> False -- prefer for completeness.
+ _ | not (packageTrustOn dflags) -> True
+ Sf_Safe | not trust_own_pkg -> True
+ Sf_SafeInferred | not trust_own_pkg -> True
+ _ | isHomeModule home_unit mod -> True
+ _ -> unitIsTrusted $ unsafeLookupUnit unit_state (moduleUnit m)
lookup' :: Module -> Hsc (Maybe ModIface)
lookup' m = do
@@ -1349,8 +1355,9 @@ hscCheckSafe' m l = do
checkPkgTrust :: Set UnitId -> Hsc ()
checkPkgTrust pkgs = do
dflags <- getDynFlags
+ hsc_env <- getHscEnv
let errors = S.foldr go [] pkgs
- state = unitState dflags
+ state = hsc_units hsc_env
go pkg acc
| unitIsTrusted $ unsafeLookupUnitId state pkg
= acc
@@ -1542,7 +1549,7 @@ hscGenHardCode hsc_env cgguts location output_filename = do
(output_filename, (_stub_h_exists, stub_c_exists), foreign_fps, cg_infos)
<- {-# SCC "codeOutput" #-}
- codeOutput dflags this_mod output_filename location
+ codeOutput dflags (hsc_units hsc_env) this_mod output_filename location
foreign_stubs foreign_files dependencies rawcmms1
return (output_filename, stub_c_exists, foreign_fps, cg_infos)
@@ -1575,7 +1582,7 @@ hscInteractive hsc_env cgguts location = do
comp_bc <- byteCodeGen hsc_env this_mod prepd_binds data_tycons mod_breaks
------------------ Create f-x-dynamic C-side stuff -----
(_istub_h_exists, istub_c_exists)
- <- outputForeignStubs dflags this_mod location foreign_stubs
+ <- outputForeignStubs dflags (hsc_units hsc_env) this_mod location foreign_stubs
return (istub_c_exists, comp_bc, spt_entries)
------------------------------
@@ -1588,7 +1595,7 @@ hscCompileCmmFile hsc_env filename output_filename = runHsc hsc_env $ do
cmm <- ioMsgMaybe
$ do
(warns,errs,cmm) <- withTiming dflags (text "ParseCmm"<+>brackets (text filename)) (\_ -> ())
- $ parseCmmFile dflags filename
+ $ parseCmmFile dflags home_unit filename
return ((fmap pprWarning warns, fmap pprError errs), cmm)
liftIO $ do
dumpIfSet_dyn dflags Opt_D_dump_cmm_verbose_by_proc "Parsed Cmm" FormatCMM (pdoc platform cmm)
@@ -1611,7 +1618,7 @@ hscCompileCmmFile hsc_env filename output_filename = runHsc hsc_env $ do
FormatCMM (pdoc platform cmmgroup)
rawCmms <- lookupHook (\x -> cmmToRawCmmHook x)
(\dflgs _ -> cmmToRawCmm dflgs) dflags dflags Nothing (Stream.yield cmmgroup)
- _ <- codeOutput dflags cmm_mod output_filename no_loc NoStubs [] []
+ _ <- codeOutput dflags (hsc_units hsc_env) cmm_mod output_filename no_loc NoStubs [] []
rawCmms
return ()
where
diff --git a/compiler/GHC/Driver/Make.hs b/compiler/GHC/Driver/Make.hs
index 06f5014684..62eeb01e44 100644
--- a/compiler/GHC/Driver/Make.hs
+++ b/compiler/GHC/Driver/Make.hs
@@ -55,6 +55,7 @@ import GHC.Driver.Main
import GHC.Parser.Header
import GHC.Parser.Errors.Ppr
+import GHC.Iface.Load ( cannotFindModule )
import GHC.IfaceToCore ( typecheckIface )
import GHC.Data.Bag ( unitBag, listToBag, unionManyBags, isEmptyBag )
@@ -329,7 +330,7 @@ warnUnusedPackages = do
eps <- liftIO $ hscEPS hsc_env
let dflags = hsc_dflags hsc_env
- state = unitState dflags
+ state = hsc_units hsc_env
pit = eps_PIT eps
let loadedPackages
@@ -569,12 +570,13 @@ load' how_much mHscMessage mod_graph = do
let ofile = outputFile dflags
let no_hs_main = gopt Opt_NoHsMain dflags
let
- main_mod = mainModIs dflags
+ main_mod = mainModIs hsc_env
a_root_is_Main = mgElemModule mod_graph main_mod
do_linking = a_root_is_Main || no_hs_main || ghcLink dflags == LinkDynLib || ghcLink dflags == LinkStaticLib
-- link everything together
- linkresult <- liftIO $ link (ghcLink dflags) dflags do_linking (hsc_HPT hsc_env1)
+ unit_env <- hsc_unit_env <$> getSession
+ linkresult <- liftIO $ link (ghcLink dflags) dflags unit_env do_linking (hsc_HPT hsc_env1)
if ghcLink dflags == LinkBinary && isJust ofile && not do_linking
then do
@@ -632,7 +634,8 @@ load' how_much mHscMessage mod_graph = do
ASSERT( just_linkables ) do
-- Link everything together
- linkresult <- liftIO $ link (ghcLink dflags) dflags False hpt5
+ unit_env <- hsc_unit_env <$> getSession
+ linkresult <- liftIO $ link (ghcLink dflags) dflags unit_env False hpt5
modifySession $ \hsc_env -> hsc_env{ hsc_HPT = hpt5 }
loadFinish Failed linkresult
@@ -691,7 +694,7 @@ guessOutputFile = modifySession $ \env ->
!mod_graph = hsc_mod_graph env
mainModuleSrcPath :: Maybe String
mainModuleSrcPath = do
- ms <- mgLookupModule mod_graph (mainModIs dflags)
+ ms <- mgLookupModule mod_graph (mainModIs env)
ml_hs_file (ms_location ms)
name = fmap dropExtension mainModuleSrcPath
@@ -998,7 +1001,7 @@ parUpsweep n_jobs mHscMessage old_hpt stable_mods cleanup sccs = do
hsc_env <- getSession
let dflags = hsc_dflags hsc_env
- when (not (null (instantiatedUnitsToCheck dflags))) $
+ when (not (null (instantiatedUnitsToCheck (hsc_units hsc_env)))) $
throwGhcException (ProgramError "Backpack typechecking not supported with -j")
-- The bits of shared state we'll be using:
@@ -1413,9 +1416,9 @@ upsweep
-- 3. A list of modules which succeeded loading.
upsweep mHscMessage old_hpt stable_mods cleanup sccs = do
- dflags <- getSessionDynFlags
+ hsc_env <- getSession
(res, done) <- upsweep' old_hpt emptyMG sccs 1 (length sccs)
- (instantiatedUnitsToCheck dflags) done_holes
+ (instantiatedUnitsToCheck (hsc_units hsc_env)) done_holes
return (res, reverse $ mgModSummaries done)
where
done_holes = emptyUniqSet
@@ -1562,9 +1565,9 @@ upsweep mHscMessage old_hpt stable_mods cleanup sccs = do
--
-- Use explicit (instantiated) units as roots and also return their
-- instantiations that are themselves instantiations and so on recursively.
-instantiatedUnitsToCheck :: DynFlags -> [Unit]
-instantiatedUnitsToCheck dflags =
- nubSort $ concatMap goUnit (explicitUnits (unitState dflags))
+instantiatedUnitsToCheck :: UnitState -> [Unit]
+instantiatedUnitsToCheck unit_state =
+ nubSort $ concatMap goUnit (explicitUnits unit_state)
where
goUnit HoleUnit = []
goUnit (RealUnit _) = []
@@ -2740,10 +2743,10 @@ withDeferredDiagnostics f = do
(\_ -> setLogAction (log_action dflags) >> printDeferredDiagnostics)
(\_ -> f)
-noModError :: DynFlags -> SrcSpan -> ModuleName -> FindResult -> ErrMsg
+noModError :: HscEnv -> SrcSpan -> ModuleName -> FindResult -> ErrMsg
-- ToDo: we don't have a proper line number for this error
-noModError dflags loc wanted_mod err
- = mkPlainErrMsg dflags loc $ cannotFindModule dflags wanted_mod err
+noModError hsc_env loc wanted_mod err
+ = mkPlainErrMsg (hsc_dflags hsc_env) loc $ cannotFindModule hsc_env wanted_mod err
noHsFileErr :: DynFlags -> SrcSpan -> String -> ErrorMessages
noHsFileErr dflags loc path
diff --git a/compiler/GHC/Driver/MakeFile.hs b/compiler/GHC/Driver/MakeFile.hs
index c8c4c07d0d..86262c5ab4 100644
--- a/compiler/GHC/Driver/MakeFile.hs
+++ b/compiler/GHC/Driver/MakeFile.hs
@@ -33,6 +33,8 @@ import Data.List
import GHC.Data.FastString
import GHC.SysTools.FileCleanup
+import GHC.Iface.Load (cannotFindModule)
+
import GHC.Unit.Module
import GHC.Unit.Module.ModSummary
import GHC.Unit.Module.Graph
@@ -279,7 +281,7 @@ findDependency hsc_env srcloc pkg imp is_boot include_pkg_deps
fail ->
let dflags = hsc_dflags hsc_env
in throwOneError $ mkPlainErrMsg dflags srcloc $
- cannotFindModule dflags imp fail
+ cannotFindModule hsc_env imp fail
}
-----------------------------
diff --git a/compiler/GHC/Driver/Pipeline.hs b/compiler/GHC/Driver/Pipeline.hs
index a2dc71d957..1a3e256710 100644
--- a/compiler/GHC/Driver/Pipeline.hs
+++ b/compiler/GHC/Driver/Pipeline.hs
@@ -65,8 +65,6 @@ import GHC.SysTools.FileCleanup
import GHC.Linker.ExtraObj
import GHC.Linker.Dynamic
-import GHC.Linker.MacOS
-import GHC.Linker.Unit
import GHC.Linker.Static
import GHC.Linker.Types
@@ -96,6 +94,7 @@ import GHC.Types.SourceFile
import GHC.Types.SourceError
import GHC.Unit
+import GHC.Unit.Env
import GHC.Unit.State
import GHC.Unit.Finder
import GHC.Unit.Module.ModSummary
@@ -479,10 +478,11 @@ compileEmptyStub dflags hsc_env basename location mod_name = do
-- by shortening the library names, or start putting libraries into the same
-- folders, such that one runpath would be sufficient for multiple/all
-- libraries.
-link :: GhcLink -- interactive or batch
- -> DynFlags -- dynamic flags
- -> Bool -- attempt linking in batch mode?
- -> HomePackageTable -- what to link
+link :: GhcLink -- ^ interactive or batch
+ -> DynFlags -- ^ dynamic flags
+ -> UnitEnv -- ^ unit environment
+ -> Bool -- ^ attempt linking in batch mode?
+ -> HomePackageTable -- ^ what to link
-> IO SuccessFlag
-- For the moment, in the batch linker, we don't bother to tell doLink
@@ -492,7 +492,7 @@ link :: GhcLink -- interactive or batch
-- exports main, i.e., we have good reason to believe that linking
-- will succeed.
-link ghcLink dflags
+link ghcLink dflags unit_env
= lookupHook linkHook l dflags ghcLink dflags
where
l LinkInMemory _ _ _
@@ -505,24 +505,25 @@ link ghcLink dflags
= return Succeeded
l LinkBinary dflags batch_attempt_linking hpt
- = link' dflags batch_attempt_linking hpt
+ = link' dflags unit_env batch_attempt_linking hpt
l LinkStaticLib dflags batch_attempt_linking hpt
- = link' dflags batch_attempt_linking hpt
+ = link' dflags unit_env batch_attempt_linking hpt
l LinkDynLib dflags batch_attempt_linking hpt
- = link' dflags batch_attempt_linking hpt
+ = link' dflags unit_env batch_attempt_linking hpt
panicBadLink :: GhcLink -> a
panicBadLink other = panic ("link: GHC not built to link this way: " ++
show other)
-link' :: DynFlags -- dynamic flags
- -> Bool -- attempt linking in batch mode?
- -> HomePackageTable -- what to link
+link' :: DynFlags -- ^ dynamic flags
+ -> UnitEnv -- ^ unit environment
+ -> Bool -- ^ attempt linking in batch mode?
+ -> HomePackageTable -- ^ what to link
-> IO SuccessFlag
-link' dflags batch_attempt_linking hpt
+link' dflags unit_env batch_attempt_linking hpt
| batch_attempt_linking
= do
let
@@ -551,7 +552,7 @@ link' dflags batch_attempt_linking hpt
platform = targetPlatform dflags
exe_file = exeFileName platform staticLink (outputFile dflags)
- linking_needed <- linkingNeeded dflags staticLink linkables pkg_deps
+ linking_needed <- linkingNeeded dflags unit_env staticLink linkables pkg_deps
if not (gopt Opt_ForceRecomp dflags) && not linking_needed
then do debugTraceMsg dflags 2 (text exe_file <+> text "is up to date, linking not required.")
@@ -566,7 +567,7 @@ link' dflags batch_attempt_linking hpt
LinkStaticLib -> linkStaticLib
LinkDynLib -> linkDynLibCheck
other -> panicBadLink other
- link dflags obj_files pkg_deps
+ link dflags unit_env obj_files pkg_deps
debugTraceMsg dflags 3 (text "link: done")
@@ -579,13 +580,14 @@ link' dflags batch_attempt_linking hpt
return Succeeded
-linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [UnitId] -> IO Bool
-linkingNeeded dflags staticLink linkables pkg_deps = do
+linkingNeeded :: DynFlags -> UnitEnv -> Bool -> [Linkable] -> [UnitId] -> IO Bool
+linkingNeeded dflags unit_env staticLink linkables pkg_deps = do
-- if the modification time on the executable is later than the
-- modification times on all of the objects and libraries, then omit
-- linking (unless the -fforce-recomp flag was given).
- let platform = targetPlatform dflags
- exe_file = exeFileName platform staticLink (outputFile dflags)
+ let platform = ue_platform unit_env
+ unit_state = ue_units unit_env
+ exe_file = exeFileName platform staticLink (outputFile dflags)
e_exe_time <- tryIO $ getModificationUTCTime exe_file
case e_exe_time of
Left _ -> return True
@@ -601,10 +603,9 @@ linkingNeeded dflags staticLink linkables pkg_deps = do
-- next, check libraries. XXX this only checks Haskell libraries,
-- not extra_libraries or -l things from the command line.
- let unit_state = unitState dflags
- let pkg_hslibs = [ (collectLibraryPaths (ways dflags) [c], lib)
+ let pkg_hslibs = [ (collectLibraryDirs (ways dflags) [c], lib)
| Just c <- map (lookupUnitId unit_state) pkg_deps,
- lib <- packageHsLibs dflags c ]
+ lib <- unitHsLibs (ghcNameVersion dflags) (ways dflags) c ]
pkg_libfiles <- mapM (uncurry (findHSLib platform (ways dflags))) pkg_hslibs
if any isNothing pkg_libfiles then return True else do
@@ -613,7 +614,7 @@ linkingNeeded dflags staticLink linkables pkg_deps = do
let (lib_errs,lib_times) = partitionEithers e_lib_times
if not (null lib_errs) || any (t <) lib_times
then return True
- else checkLinkInfo dflags pkg_deps exe_file
+ else checkLinkInfo dflags unit_env pkg_deps exe_file
findHSLib :: Platform -> Ways -> [String] -> String -> IO (Maybe FilePath)
findHSLib platform ws dirs lib = do
@@ -631,7 +632,7 @@ findHSLib platform ws dirs lib = do
oneShot :: HscEnv -> Phase -> [(String, Maybe Phase)] -> IO ()
oneShot hsc_env stop_phase srcs = do
o_files <- mapM (compileFile hsc_env stop_phase) srcs
- doLink (hsc_dflags hsc_env) stop_phase o_files
+ doLink hsc_env stop_phase o_files
compileFile :: HscEnv -> Phase -> (FilePath, Maybe Phase) -> IO FilePath
compileFile hsc_env stop_phase (src, mb_phase) = do
@@ -665,17 +666,20 @@ compileFile hsc_env stop_phase (src, mb_phase) = do
return out_file
-doLink :: DynFlags -> Phase -> [FilePath] -> IO ()
-doLink dflags stop_phase o_files
+doLink :: HscEnv -> Phase -> [FilePath] -> IO ()
+doLink hsc_env stop_phase o_files
| not (isStopLn stop_phase)
= return () -- We stopped before the linking phase
| otherwise
- = case ghcLink dflags of
+ = let
+ dflags = hsc_dflags hsc_env
+ unit_env = hsc_unit_env hsc_env
+ in case ghcLink dflags of
NoLink -> return ()
- LinkBinary -> linkBinary dflags o_files []
- LinkStaticLib -> linkStaticLib dflags o_files []
- LinkDynLib -> linkDynLibCheck dflags o_files []
+ LinkBinary -> linkBinary dflags unit_env o_files []
+ LinkStaticLib -> linkStaticLib dflags unit_env o_files []
+ LinkDynLib -> linkDynLibCheck dflags unit_env o_files []
other -> panicBadLink other
@@ -804,7 +808,18 @@ runPipeline stop_phase hsc_env0 (input_fn, mb_input_buf, mb_phase)
$ setDynamicNow
$ dflags
hsc_env' <- newHscEnv dflags'
- _ <- runPipeline' start_phase hsc_env' env input_fn'
+ (dbs,unit_state,home_unit) <- initUnits dflags' Nothing
+ let unit_env = UnitEnv
+ { ue_platform = targetPlatform dflags'
+ , ue_namever = ghcNameVersion dflags'
+ , ue_home_unit = home_unit
+ , ue_units = unit_state
+ }
+ let hsc_env'' = hsc_env'
+ { hsc_unit_env = unit_env
+ , hsc_unit_dbs = Just dbs
+ }
+ _ <- runPipeline' start_phase hsc_env'' env input_fn'
maybe_loc foreign_os
return ()
return r
@@ -874,7 +889,7 @@ pipeLoop phase input_fn = do
case phase of
HscOut {} -> do
let noDynToo = do
- (next_phase, output_fn) <- runHookedPhase phase input_fn dflags
+ (next_phase, output_fn) <- runHookedPhase phase input_fn
pipeLoop next_phase output_fn
let dynToo = do
-- if Opt_BuildDynamicToo is set and if the platform
@@ -883,7 +898,7 @@ pipeLoop phase input_fn = do
-- the non-dynamic ones.
let dflags' = setDynamicNow dflags -- set "dynamicNow"
setDynFlags dflags'
- (next_phase, output_fn) <- runHookedPhase phase input_fn dflags'
+ (next_phase, output_fn) <- runHookedPhase phase input_fn
_ <- pipeLoop next_phase output_fn
-- TODO: we probably shouldn't ignore the result of
-- the dynamic compilation
@@ -902,13 +917,13 @@ pipeLoop phase input_fn = do
-- we set DynamicNow but we unset Opt_BuildDynamicToo so
-- it's weird.
_ -> do
- (next_phase, output_fn) <- runHookedPhase phase input_fn dflags
+ (next_phase, output_fn) <- runHookedPhase phase input_fn
pipeLoop next_phase output_fn
-runHookedPhase :: PhasePlus -> FilePath -> DynFlags
- -> CompPipeline (PhasePlus, FilePath)
-runHookedPhase pp input dflags =
- lookupHook runPhaseHook runPhase dflags pp input dflags
+runHookedPhase :: PhasePlus -> FilePath -> CompPipeline (PhasePlus, FilePath)
+runHookedPhase pp input = do
+ dflags <- hsc_dflags <$> getPipeSession
+ lookupHook runPhaseHook runPhase dflags pp input
-- -----------------------------------------------------------------------------
-- In each phase, we need to know into what filename to generate the
@@ -1052,7 +1067,6 @@ llvmOptions dflags =
--
runPhase :: PhasePlus -- ^ Run this phase
-> FilePath -- ^ name of the input file
- -> DynFlags -- ^ for convenience, we pass the current dflags in
-> CompPipeline (PhasePlus, -- next phase to run
FilePath) -- output filename
@@ -1064,23 +1078,8 @@ runPhase :: PhasePlus -- ^ Run this phase
-------------------------------------------------------------------------------
-- Unlit phase
-runPhase (RealPhase (Unlit sf)) input_fn dflags
- = do
- output_fn <- phaseOutputFilename (Cpp sf)
-
- let flags = [ -- The -h option passes the file name for unlit to
- -- put in a #line directive
- GHC.SysTools.Option "-h"
- -- See Note [Don't normalise input filenames].
- , GHC.SysTools.Option $ escape input_fn
- , GHC.SysTools.FileOption "" input_fn
- , GHC.SysTools.FileOption "" output_fn
- ]
-
- liftIO $ GHC.SysTools.runUnlit dflags flags
-
- return (RealPhase (Cpp sf), output_fn)
- where
+runPhase (RealPhase (Unlit sf)) input_fn = do
+ let
-- escape the characters \, ", and ', but don't try to escape
-- Unicode or anything else (so we don't use Util.charToC
-- here). If we get this wrong, then in
@@ -1094,12 +1093,29 @@ runPhase (RealPhase (Unlit sf)) input_fn dflags
escape (c:cs) = c : escape cs
escape [] = []
+ output_fn <- phaseOutputFilename (Cpp sf)
+
+ let flags = [ -- The -h option passes the file name for unlit to
+ -- put in a #line directive
+ GHC.SysTools.Option "-h"
+ -- See Note [Don't normalise input filenames].
+ , GHC.SysTools.Option $ escape input_fn
+ , GHC.SysTools.FileOption "" input_fn
+ , GHC.SysTools.FileOption "" output_fn
+ ]
+
+ dflags <- hsc_dflags <$> getPipeSession
+ liftIO $ GHC.SysTools.runUnlit dflags flags
+
+ return (RealPhase (Cpp sf), output_fn)
+
-------------------------------------------------------------------------------
-- Cpp phase : (a) gets OPTIONS out of file
-- (b) runs cpp if necessary
-runPhase (RealPhase (Cpp sf)) input_fn dflags0
+runPhase (RealPhase (Cpp sf)) input_fn
= do
+ dflags0 <- getDynFlags
src_opts <- liftIO $ getOptionsFromFile dflags0 input_fn
(dflags1, unhandled_flags, warns)
<- liftIO $ parseDynamicFilePragma dflags0 src_opts
@@ -1116,7 +1132,9 @@ runPhase (RealPhase (Cpp sf)) input_fn dflags0
return (RealPhase (HsPp sf), input_fn)
else do
output_fn <- phaseOutputFilename (HsPp sf)
- liftIO $ doCpp dflags1 True{-raw-}
+ hsc_env <- getPipeSession
+ liftIO $ doCpp (hsc_dflags hsc_env) (hsc_unit_env hsc_env)
+ True{-raw-}
input_fn output_fn
-- re-read the pragmas now that we've preprocessed the file
-- See #2464,#3457
@@ -1135,8 +1153,9 @@ runPhase (RealPhase (Cpp sf)) input_fn dflags0
-------------------------------------------------------------------------------
-- HsPp phase
-runPhase (RealPhase (HsPp sf)) input_fn dflags
- = if not (gopt Opt_Pp dflags) then
+runPhase (RealPhase (HsPp sf)) input_fn = do
+ dflags <- getDynFlags
+ if not (gopt Opt_Pp dflags) then
-- no need to preprocess, just pass input file along
-- to the next phase of the pipeline.
return (RealPhase (Hsc sf), input_fn)
@@ -1166,8 +1185,9 @@ runPhase (RealPhase (HsPp sf)) input_fn dflags
-- Compilation of a single module, in "legacy" mode (_not_ under
-- the direction of the compilation manager).
-runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0
+runPhase (RealPhase (Hsc src_flavour)) input_fn
= do -- normal Hsc mode, not mkdependHS
+ dflags0 <- getDynFlags
PipeEnv{ stop_phase=stop,
src_basename=basename,
@@ -1270,7 +1290,8 @@ runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0
return (HscOut src_flavour mod_name result,
panic "HscOut doesn't have an input filename")
-runPhase (HscOut src_flavour mod_name result) _ dflags = do
+runPhase (HscOut src_flavour mod_name result) _ = do
+ dflags <- getDynFlags
location <- getLocation src_flavour mod_name
setModLocation location
@@ -1335,14 +1356,18 @@ runPhase (HscOut src_flavour mod_name result) _ dflags = do
-----------------------------------------------------------------------------
-- Cmm phase
-runPhase (RealPhase CmmCpp) input_fn dflags
- = do output_fn <- phaseOutputFilename Cmm
- liftIO $ doCpp dflags False{-not raw-}
+runPhase (RealPhase CmmCpp) input_fn = do
+ hsc_env <- getPipeSession
+ output_fn <- phaseOutputFilename Cmm
+ liftIO $ doCpp (hsc_dflags hsc_env) (hsc_unit_env hsc_env)
+ False{-not raw-}
input_fn output_fn
return (RealPhase Cmm, output_fn)
-runPhase (RealPhase Cmm) input_fn dflags
- = do let next_phase = hscPostBackendPhase HsSrcFile (backend dflags)
+runPhase (RealPhase Cmm) input_fn = do
+ hsc_env <- getPipeSession
+ let dflags = hsc_dflags hsc_env
+ let next_phase = hscPostBackendPhase HsSrcFile (backend dflags)
output_fn <- phaseOutputFilename next_phase
PipeState{hsc_env} <- getPipeState
liftIO $ hscCompileCmmFile hsc_env input_fn output_fn
@@ -1351,12 +1376,15 @@ runPhase (RealPhase Cmm) input_fn dflags
-----------------------------------------------------------------------------
-- Cc phase
-runPhase (RealPhase cc_phase) input_fn dflags
+runPhase (RealPhase cc_phase) input_fn
| any (cc_phase `eqPhase`) [Cc, Ccxx, HCc, Cobjc, Cobjcxx]
= do
- let platform = targetPlatform dflags
- hcc = cc_phase `eqPhase` HCc
- home_unit = mkHomeUnitFromFlags dflags
+ hsc_env <- getPipeSession
+ let dflags = hsc_dflags hsc_env
+ let unit_env = hsc_unit_env hsc_env
+ let home_unit = hsc_home_unit hsc_env
+ let platform = ue_platform unit_env
+ let hcc = cc_phase `eqPhase` HCc
let cmdline_include_paths = includePaths dflags
@@ -1366,11 +1394,8 @@ runPhase (RealPhase cc_phase) input_fn dflags
-- add package include paths even if we're just compiling .c
-- files; this is the Value Add(TM) that using ghc instead of
-- gcc gives you :)
- pkg_include_dirs <- liftIO $ getUnitIncludePath
- (initSDocContext dflags defaultUserStyle)
- (unitState dflags)
- home_unit
- pkgs
+ ps <- liftIO $ mayThrowUnitErr (preloadUnitsInfo' unit_env pkgs)
+ let pkg_include_dirs = collectIncludeDirs ps
let include_paths_global = foldr (\ x xs -> ("-I" ++ x) : xs) []
(includePathsGlobal cmdline_include_paths ++ pkg_include_dirs)
let include_paths_quote = foldr (\ x xs -> ("-iquote" ++ x) : xs) []
@@ -1395,26 +1420,17 @@ runPhase (RealPhase cc_phase) input_fn dflags
-- cc-options are not passed when compiling .hc files. Our
-- hc code doesn't not #include any header files anyway, so these
-- options aren't necessary.
- pkg_extra_cc_opts <- liftIO $
- if hcc
- then return []
- else getUnitExtraCcOpts
- (initSDocContext dflags defaultUserStyle)
- (unitState dflags)
- home_unit
- pkgs
-
- framework_paths <-
- if platformUsesFrameworks platform
- then do pkgFrameworkPaths <- liftIO $ getUnitFrameworkPath
- (initSDocContext dflags defaultUserStyle)
- (unitState dflags)
- home_unit
- pkgs
- let cmdlineFrameworkPaths = frameworkPaths dflags
- return $ map ("-F"++)
- (cmdlineFrameworkPaths ++ pkgFrameworkPaths)
- else return []
+ let pkg_extra_cc_opts
+ | hcc = []
+ | otherwise = collectExtraCcOpts ps
+
+ let framework_paths
+ | platformUsesFrameworks platform
+ = let pkgFrameworkPaths = collectFrameworksDirs ps
+ cmdlineFrameworkPaths = frameworkPaths dflags
+ in map ("-F"++) (cmdlineFrameworkPaths ++ pkgFrameworkPaths)
+ | otherwise
+ = []
let cc_opt | optLevel dflags >= 2 = [ "-O2" ]
| optLevel dflags >= 1 = [ "-O" ]
@@ -1441,7 +1457,7 @@ runPhase (RealPhase cc_phase) input_fn dflags
-- very weakly typed, being derived from C--.
["-fno-strict-aliasing"]
- ghcVersionH <- liftIO $ getGhcVersionPathName dflags
+ ghcVersionH <- liftIO $ getGhcVersionPathName dflags unit_env
liftIO $ GHC.SysTools.runCc (phaseForeignLanguage cc_phase) dflags (
[ GHC.SysTools.FileOption "" input_fn
@@ -1496,14 +1512,20 @@ runPhase (RealPhase cc_phase) input_fn dflags
-- As, SpitAs phase : Assembler
-- This is for calling the assembler on a regular assembly file
-runPhase (RealPhase (As with_cpp)) input_fn dflags
+runPhase (RealPhase (As with_cpp)) input_fn
= do
+ hsc_env <- getPipeSession
+ let dflags = hsc_dflags hsc_env
+ let unit_env = hsc_unit_env hsc_env
+ let platform = ue_platform unit_env
+
-- LLVM from version 3.0 onwards doesn't support the OS X system
-- assembler, so we use clang as the assembler instead. (#5636)
- let as_prog | backend dflags == LLVM &&
- platformOS (targetPlatform dflags) == OSDarwin
+ let as_prog | backend dflags == LLVM
+ , platformOS platform == OSDarwin
= GHC.SysTools.runClang
- | otherwise = GHC.SysTools.runAs
+ | otherwise
+ = GHC.SysTools.runAs
let cmdline_include_paths = includePaths dflags
let pic_c_flags = picCCOpts dflags
@@ -1565,20 +1587,9 @@ runPhase (RealPhase (As with_cpp)) input_fn dflags
-----------------------------------------------------------------------------
-- LlvmOpt phase
-runPhase (RealPhase LlvmOpt) input_fn dflags
- = do
- output_fn <- phaseOutputFilename LlvmLlc
-
- liftIO $ GHC.SysTools.runLlvmOpt dflags
- ( optFlag
- ++ defaultOptions ++
- [ GHC.SysTools.FileOption "" input_fn
- , GHC.SysTools.Option "-o"
- , GHC.SysTools.FileOption "" output_fn]
- )
-
- return (RealPhase LlvmLlc, output_fn)
- where
+runPhase (RealPhase LlvmOpt) input_fn = do
+ hsc_env <- getPipeSession
+ let dflags = hsc_dflags hsc_env
-- we always (unless -optlo specified) run Opt since we rely on it to
-- fix up some pretty big deficiencies in the code we generate
optIdx = max 0 $ min 2 $ optLevel dflags -- ensure we're in [0,2]
@@ -1587,6 +1598,8 @@ runPhase (RealPhase LlvmOpt) input_fn dflags
Nothing -> panic ("runPhase LlvmOpt: llvm-passes file "
++ "is missing passes for level "
++ show optIdx)
+ defaultOptions = map GHC.SysTools.Option . concat . fmap words . fst
+ $ unzip (llvmOptions dflags)
-- don't specify anything if user has specified commands. We do this
-- for opt but not llc since opt is very specifically for optimisation
@@ -1596,31 +1609,23 @@ runPhase (RealPhase LlvmOpt) input_fn dflags
then map GHC.SysTools.Option $ words llvmOpts
else []
- defaultOptions = map GHC.SysTools.Option . concat . fmap words . fst
- $ unzip (llvmOptions dflags)
+ output_fn <- phaseOutputFilename LlvmLlc
------------------------------------------------------------------------------
--- LlvmLlc phase
+ liftIO $ GHC.SysTools.runLlvmOpt dflags
+ ( optFlag
+ ++ defaultOptions ++
+ [ GHC.SysTools.FileOption "" input_fn
+ , GHC.SysTools.Option "-o"
+ , GHC.SysTools.FileOption "" output_fn]
+ )
-runPhase (RealPhase LlvmLlc) input_fn dflags
- = do
- next_phase <- if -- hidden debugging flag '-dno-llvm-mangler' to skip mangling
- | gopt Opt_NoLlvmMangler dflags -> return (As False)
- | otherwise -> return LlvmMangle
+ return (RealPhase LlvmLlc, output_fn)
- output_fn <- phaseOutputFilename next_phase
- liftIO $ GHC.SysTools.runLlvmLlc dflags
- ( optFlag
- ++ defaultOptions
- ++ [ GHC.SysTools.FileOption "" input_fn
- , GHC.SysTools.Option "-o"
- , GHC.SysTools.FileOption "" output_fn
- ]
- )
+-----------------------------------------------------------------------------
+-- LlvmLlc phase
- return (RealPhase next_phase, output_fn)
- where
+runPhase (RealPhase LlvmLlc) input_fn = do
-- Note [Clamping of llc optimizations]
--
-- See #13724
@@ -1660,45 +1665,64 @@ runPhase (RealPhase LlvmLlc) input_fn dflags
--
-- Observed at least with -mtriple=arm-unknown-linux-gnueabihf -enable-tbaa
--
- llvmOpts = case optLevel dflags of
- 0 -> "-O1" -- required to get the non-naive reg allocator. Passing -regalloc=greedy is not sufficient.
- 1 -> "-O1"
- _ -> "-O2"
+ dflags <- hsc_dflags <$> getPipeSession
+ let
+ llvmOpts = case optLevel dflags of
+ 0 -> "-O1" -- required to get the non-naive reg allocator. Passing -regalloc=greedy is not sufficient.
+ 1 -> "-O1"
+ _ -> "-O2"
+
+ defaultOptions = map GHC.SysTools.Option . concatMap words . snd
+ $ unzip (llvmOptions dflags)
+ optFlag = if null (getOpts dflags opt_lc)
+ then map GHC.SysTools.Option $ words llvmOpts
+ else []
- optFlag = if null (getOpts dflags opt_lc)
- then map GHC.SysTools.Option $ words llvmOpts
- else []
+ next_phase <- if -- hidden debugging flag '-dno-llvm-mangler' to skip mangling
+ | gopt Opt_NoLlvmMangler dflags -> return (As False)
+ | otherwise -> return LlvmMangle
+
+ output_fn <- phaseOutputFilename next_phase
+
+ liftIO $ GHC.SysTools.runLlvmLlc dflags
+ ( optFlag
+ ++ defaultOptions
+ ++ [ GHC.SysTools.FileOption "" input_fn
+ , GHC.SysTools.Option "-o"
+ , GHC.SysTools.FileOption "" output_fn
+ ]
+ )
+
+ return (RealPhase next_phase, output_fn)
- defaultOptions = map GHC.SysTools.Option . concatMap words . snd
- $ unzip (llvmOptions dflags)
-----------------------------------------------------------------------------
-- LlvmMangle phase
-runPhase (RealPhase LlvmMangle) input_fn dflags
- = do
+runPhase (RealPhase LlvmMangle) input_fn = do
let next_phase = As False
output_fn <- phaseOutputFilename next_phase
+ dflags <- hsc_dflags <$> getPipeSession
liftIO $ llvmFixupAsm dflags input_fn output_fn
return (RealPhase next_phase, output_fn)
-----------------------------------------------------------------------------
-- merge in stub objects
-runPhase (RealPhase MergeForeign) input_fn dflags
- = do
+runPhase (RealPhase MergeForeign) input_fn = do
PipeState{foreign_os} <- getPipeState
output_fn <- phaseOutputFilename StopLn
liftIO $ createDirectoryIfMissing True (takeDirectory output_fn)
if null foreign_os
then panic "runPhase(MergeForeign): no foreign objects"
else do
+ dflags <- hsc_dflags <$> getPipeSession
liftIO $ joinObjectFiles dflags (input_fn : foreign_os) output_fn
return (RealPhase StopLn, output_fn)
-- warning suppression
-runPhase (RealPhase other) _input_fn _dflags =
+runPhase (RealPhase other) _input_fn =
panic ("runPhase: don't know how to run phase " ++ show other)
maybeMergeForeign :: CompPipeline Phase
@@ -1769,30 +1793,29 @@ getHCFilePackages filename =
return []
-linkDynLibCheck :: DynFlags -> [String] -> [UnitId] -> IO ()
-linkDynLibCheck dflags o_files dep_units = do
+linkDynLibCheck :: DynFlags -> UnitEnv -> [String] -> [UnitId] -> IO ()
+linkDynLibCheck dflags unit_env o_files dep_units = do
when (haveRtsOptsFlags dflags) $
putLogMsg dflags NoReason SevInfo noSrcSpan
$ withPprStyle defaultUserStyle
(text "Warning: -rtsopts and -with-rtsopts have no effect with -shared." $$
text " Call hs_init_ghc() from your main() function to set these options.")
- linkDynLib dflags o_files dep_units
+ linkDynLib dflags unit_env o_files dep_units
-- -----------------------------------------------------------------------------
-- Running CPP
-doCpp :: DynFlags -> Bool -> FilePath -> FilePath -> IO ()
-doCpp dflags raw input_fn output_fn = do
+-- | Run CPP
+--
+-- UnitState is needed to compute MIN_VERSION macros
+doCpp :: DynFlags -> UnitEnv -> Bool -> FilePath -> FilePath -> IO ()
+doCpp dflags unit_env raw input_fn output_fn = do
let hscpp_opts = picPOpts dflags
let cmdline_include_paths = includePaths dflags
- let home_unit = mkHomeUnitFromFlags dflags
-
- pkg_include_dirs <- getUnitIncludePath
- (initSDocContext dflags defaultUserStyle)
- (unitState dflags)
- home_unit
- []
+ let unit_state = ue_units unit_env
+ pkg_include_dirs <- mayThrowUnitErr
+ (collectIncludeDirs <$> preloadUnitsInfo unit_env)
let include_paths_global = foldr (\ x xs -> ("-I" ++ x) : xs) []
(includePathsGlobal cmdline_include_paths ++ pkg_include_dirs)
let include_paths_quote = foldr (\ x xs -> ("-iquote" ++ x) : xs) []
@@ -1837,13 +1860,12 @@ doCpp dflags raw input_fn output_fn = do
let th_defs = [ "-D__GLASGOW_HASKELL_TH__" ]
-- Default CPP defines in Haskell source
- ghcVersionH <- getGhcVersionPathName dflags
+ ghcVersionH <- getGhcVersionPathName dflags unit_env
let hsSourceCppOpts = [ "-include", ghcVersionH ]
-- MIN_VERSION macros
- let state = unitState dflags
- uids = explicitUnits state
- pkgs = catMaybes (map (lookupUnit state) uids)
+ let uids = explicitUnits unit_state
+ pkgs = catMaybes (map (lookupUnit unit_state) uids)
mb_macro_include <-
if not (null pkgs) && gopt Opt_VersionMacros dflags
then do macro_stub <- newTempName dflags TFL_CurrentModule "h"
@@ -2053,16 +2075,13 @@ touchObjectFile dflags path = do
GHC.SysTools.touch dflags "Touching object file" path
-- | Find out path to @ghcversion.h@ file
-getGhcVersionPathName :: DynFlags -> IO FilePath
-getGhcVersionPathName dflags = do
+getGhcVersionPathName :: DynFlags -> UnitEnv -> IO FilePath
+getGhcVersionPathName dflags unit_env = do
candidates <- case ghcVersionFile dflags of
Just path -> return [path]
- Nothing -> (map (</> "ghcversion.h")) <$>
- (getUnitIncludePath
- (initSDocContext dflags defaultUserStyle)
- (unitState dflags)
- (mkHomeUnitFromFlags dflags)
- [rtsUnitId])
+ Nothing -> do
+ ps <- mayThrowUnitErr (preloadUnitsInfo' unit_env [rtsUnitId])
+ return ((</> "ghcversion.h") <$> collectIncludeDirs ps)
found <- filterM doesFileExist candidates
case found of
diff --git a/compiler/GHC/Driver/Pipeline/Monad.hs b/compiler/GHC/Driver/Pipeline/Monad.hs
index 03ee6e14f6..88f19d8c2c 100644
--- a/compiler/GHC/Driver/Pipeline/Monad.hs
+++ b/compiler/GHC/Driver/Pipeline/Monad.hs
@@ -6,7 +6,8 @@ module GHC.Driver.Pipeline.Monad (
CompPipeline(..), evalP
, PhasePlus(..)
, PipeEnv(..), PipeState(..), PipelineOutput(..)
- , getPipeEnv, getPipeState, setDynFlags, setModLocation, setForeignOs, setIface
+ , getPipeEnv, getPipeState, getPipeSession
+ , setDynFlags, setModLocation, setForeignOs, setIface
, pipeStateDynFlags, pipeStateModIface, setPlugins
) where
@@ -111,6 +112,9 @@ getPipeEnv = P $ \env state -> return (state, env)
getPipeState :: CompPipeline PipeState
getPipeState = P $ \_env state -> return (state, state)
+getPipeSession :: CompPipeline HscEnv
+getPipeSession = P $ \_env state -> return (state, hsc_env state)
+
instance HasDynFlags CompPipeline where
getDynFlags = P $ \_env state -> return (state, hsc_dflags (hsc_env state))
diff --git a/compiler/GHC/Driver/Ppr.hs b/compiler/GHC/Driver/Ppr.hs
index 2ea371f223..9d430f0466 100644
--- a/compiler/GHC/Driver/Ppr.hs
+++ b/compiler/GHC/Driver/Ppr.hs
@@ -24,6 +24,7 @@ where
import GHC.Prelude
import {-# SOURCE #-} GHC.Driver.Session
+import {-# SOURCE #-} GHC.Unit.State
import GHC.Utils.Exception
import GHC.Utils.Misc
@@ -31,7 +32,6 @@ import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.GlobalVars
import GHC.Utils.Ppr ( Mode(..) )
-import {-# SOURCE #-} GHC.Unit.State
import System.IO ( Handle )
import Control.Monad.IO.Class
@@ -47,12 +47,11 @@ showPprUnsafe :: Outputable a => a -> String
showPprUnsafe a = renderWithContext defaultSDocContext (ppr a)
-- | Allows caller to specify the PrintUnqualified to use
-showSDocForUser :: DynFlags -> PrintUnqualified -> SDoc -> String
-showSDocForUser dflags unqual doc = renderWithContext (initSDocContext dflags sty) doc'
+showSDocForUser :: DynFlags -> UnitState -> PrintUnqualified -> SDoc -> String
+showSDocForUser dflags unit_state unqual doc = renderWithContext (initSDocContext dflags sty) doc'
where
- sty = mkUserStyle unqual AllTheWay
- unit_state = unitState dflags
- doc' = pprWithUnitState unit_state doc
+ sty = mkUserStyle unqual AllTheWay
+ doc' = pprWithUnitState unit_state doc
showSDocDump :: SDocContext -> SDoc -> String
showSDocDump ctx d = renderWithContext ctx (withPprStyle defaultDumpStyle d)
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 024ac97c05..a1075f1cdb 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -39,7 +39,7 @@ module GHC.Driver.Session (
DynamicTooState(..), dynamicTooState, setDynamicNow, setDynamicTooFailed,
dynamicOutputFile,
sccProfilingEnabled,
- DynFlags(..), mainModIs,
+ DynFlags(..),
outputFile, hiSuf, objectSuf, ways,
FlagSpec(..),
HasDynFlags(..), ContainsDynFlags(..),
@@ -63,8 +63,6 @@ module GHC.Driver.Session (
targetProfile,
- mkHomeUnitFromFlags,
-
-- ** Log output
putLogMsg,
@@ -231,13 +229,11 @@ import GHC.Platform
import GHC.Platform.Ways
import GHC.Platform.Profile
import GHC.UniqueSubdir (uniqueSubdir)
-import GHC.Unit.Home
import GHC.Unit.Types
import GHC.Unit.Parser
import GHC.Unit.Module
import GHC.Builtin.Names ( mAIN_NAME )
import {-# SOURCE #-} GHC.Driver.Hooks
-import {-# SOURCE #-} GHC.Unit.State (UnitState, emptyUnitState, UnitDatabase)
import GHC.Driver.Phases ( Phase(..), phaseInputExt )
import GHC.Driver.Flags
import GHC.Driver.Backend
@@ -594,21 +590,6 @@ data DynFlags = DynFlags {
packageEnv :: Maybe FilePath,
-- ^ Filepath to the package environment file (if overriding default)
- unitDatabases :: Maybe [UnitDatabase UnitId],
- -- ^ Stack of unit databases for the target platform.
- --
- -- This field is populated by `initUnits`.
- --
- -- 'Nothing' means the databases have never been read from disk. If
- -- `initUnits` is called again, it doesn't reload the databases from
- -- disk.
-
- unitState :: UnitState,
- -- ^ Consolidated unit database built by 'initUnits' from the unit
- -- databases in 'unitDatabases' and flags ('-ignore-package', etc.).
- --
- -- It also contains mapping from module names to actual Modules.
-
-- Temporary files
-- These have to be IORefs, because the defaultCleanupHandler needs to
-- know what to clean when an exception happens
@@ -1232,8 +1213,6 @@ defaultDynFlags mySettings llvmConfig =
ignorePackageFlags = [],
trustFlags = [],
packageEnv = Nothing,
- unitDatabases = Nothing,
- unitState = emptyUnitState,
targetWays_ = defaultWays mySettings,
splitInfo = Nothing,
@@ -1666,9 +1645,6 @@ lang_set dflags lang =
extensionFlags = flattenExtensionFlags lang (extensions dflags)
}
-mainModIs :: DynFlags -> Module
-mainModIs dflags = mkHomeModule (mkHomeUnitFromFlags dflags) (mainModuleNameIs dflags)
-
-- | Set the Haskell language standard to use
setLanguage :: Language -> DynP ()
setLanguage l = upd (`lang_set` Just l)
@@ -1815,28 +1791,6 @@ setOutputHi f d = d { outputHi = f}
setJsonLogAction :: DynFlags -> DynFlags
setJsonLogAction d = d { log_action = jsonLogAction }
--- | Get home unit
-mkHomeUnitFromFlags :: DynFlags -> HomeUnit
-mkHomeUnitFromFlags dflags =
- let !hu_id = homeUnitId_ dflags
- !hu_instanceof = homeUnitInstanceOf_ dflags
- !hu_instantiations = homeUnitInstantiations_ dflags
- in case (hu_instanceof, hu_instantiations) of
- (Nothing,[]) -> DefiniteHomeUnit hu_id Nothing
- (Nothing, _) -> throwGhcException $ CmdLineError ("Use of -instantiated-with requires -this-component-id")
- (Just _, []) -> throwGhcException $ CmdLineError ("Use of -this-component-id requires -instantiated-with")
- (Just u, is)
- -- detect fully indefinite units: all their instantiations are hole
- -- modules and the home unit id is the same as the instantiating unit
- -- id (see Note [About units] in GHC.Unit)
- | all (isHoleModule . snd) is && u == hu_id
- -> IndefiniteHomeUnit u is
- -- otherwise it must be that we (fully) instantiate an indefinite unit
- -- to make it definite.
- -- TODO: error when the unit is partially instantiated??
- | otherwise
- -> DefiniteHomeUnit hu_id (Just (u, is))
-
parseUnitInsts :: String -> Instantiations
parseUnitInsts str = case filter ((=="").snd) (readP_to_S parse str) of
[(r, "")] -> r
diff --git a/compiler/GHC/Driver/Session.hs-boot b/compiler/GHC/Driver/Session.hs-boot
index 2550782d37..d2125e4b9d 100644
--- a/compiler/GHC/Driver/Session.hs-boot
+++ b/compiler/GHC/Driver/Session.hs-boot
@@ -3,12 +3,10 @@ module GHC.Driver.Session where
import GHC.Prelude
import GHC.Platform
import {-# SOURCE #-} GHC.Utils.Outputable
-import {-# SOURCE #-} GHC.Unit.State
data DynFlags
targetPlatform :: DynFlags -> Platform
-unitState :: DynFlags -> UnitState
hasPprDebug :: DynFlags -> Bool
hasNoDebugOutput :: DynFlags -> Bool
initSDocContext :: DynFlags -> PprStyle -> SDocContext