summaryrefslogtreecommitdiff
path: root/compiler/main/DriverPipeline.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/main/DriverPipeline.hs')
-rw-r--r--compiler/main/DriverPipeline.hs336
1 files changed, 118 insertions, 218 deletions
diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
index a45507e635..e83f7d66a3 100644
--- a/compiler/main/DriverPipeline.hs
+++ b/compiler/main/DriverPipeline.hs
@@ -64,10 +64,8 @@ import MonadUtils
import Platform
import TcRnTypes
import Hooks
-import MkIface
import Exception
-import Data.IORef ( readIORef )
import System.Directory
import System.FilePath
import System.IO
@@ -133,173 +131,90 @@ compileOne' :: Maybe TcGblEnv
compileOne' m_tc_result mHscMessage
hsc_env0 summary mod_index nmods mb_old_iface maybe_old_linkable
source_modified0
- | HsBootMerge <- ms_hsc_src summary
- = do -- Do a boot merge instead! For now, something very simple
- output_fn <- getOutputFilename next_phase
- Temporary basename dflags next_phase (Just location)
- e <- genericHscMergeRequirement mHscMessage
- hsc_env summary mb_old_iface (mod_index, nmods)
-
- case e of
- -- TODO: dedup
- Left iface ->
- do details <- genModDetails hsc_env iface
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = maybe_old_linkable })
- Right (iface0, mb_old_hash) ->
- case hsc_lang of
- HscInterpreted ->
- do (iface, _no_change) <- mkIfaceDirect hsc_env mb_old_hash iface0
- details <- genModDetails hsc_env iface
- -- Merges don't need to link in any bytecode, unlike
- -- HsSrcFiles.
- let linkable = LM (ms_hs_date summary) this_mod []
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = Just linkable })
-
- HscNothing ->
- do (iface, no_change) <- mkIfaceDirect hsc_env mb_old_hash iface0
- details <- genModDetails hsc_env iface
- when (gopt Opt_WriteInterface dflags) $
- hscWriteIface dflags iface no_change summary
- let linkable = LM (ms_hs_date summary) this_mod []
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = Just linkable })
- _ ->
- do (iface, no_change) <- mkIfaceDirect hsc_env mb_old_hash iface0
- hscWriteIface dflags iface no_change summary
-
- -- #10660: Use the pipeline instead of calling
- -- compileEmptyStub directly, so -dynamic-too gets
- -- handled properly
- let mod_name = ms_mod_name summary
- _ <- runPipeline StopLn hsc_env
- (output_fn,
- Just (HscOut src_flavour
- mod_name HscUpdateBootMerge))
- (Just basename)
- Persistent
- (Just location)
- Nothing
-
- details <- genModDetails hsc_env iface
-
- o_time <- getModificationUTCTime object_filename
- let linkable =
- LM o_time this_mod [DotO object_filename]
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = Just linkable })
-
- | otherwise
= do
debugTraceMsg dflags1 2 (text "compile: input file" <+> text input_fnpp)
- -- What file to generate the output into?
- output_fn <- getOutputFilename next_phase
- Temporary basename dflags next_phase (Just location)
-
- e <- genericHscCompileGetFrontendResult
- always_do_basic_recompilation_check
- m_tc_result mHscMessage
- hsc_env summary source_modified mb_old_iface (mod_index, nmods)
-
- case e of
- Left iface ->
- do details <- genModDetails hsc_env iface
- MASSERT(isJust maybe_old_linkable || isNoLink (ghcLink dflags))
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = maybe_old_linkable })
-
- Right (tc_result, mb_old_hash) ->
- -- run the compiler
- case hsc_lang of
- HscInterpreted ->
- case ms_hsc_src summary of
- HsBootFile ->
- do (iface, _changed, details) <- hscSimpleIface hsc_env tc_result mb_old_hash
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = maybe_old_linkable })
- _ -> do guts0 <- hscDesugar hsc_env summary tc_result
- guts <- hscSimplify hsc_env guts0
- (iface, _changed, details, cgguts) <- hscNormalIface hsc_env guts mb_old_hash
- (hasStub, comp_bc, modBreaks) <- hscInteractive hsc_env cgguts summary
-
- stub_o <- case hasStub of
- Nothing -> return []
- Just stub_c -> do
- stub_o <- compileStub hsc_env stub_c
- return [DotO stub_o]
-
- let hs_unlinked = [BCOs comp_bc modBreaks]
- unlinked_time = ms_hs_date summary
- -- Why do we use the timestamp of the source file here,
- -- rather than the current time? This works better in
- -- the case where the local clock is out of sync
- -- with the filesystem's clock. It's just as accurate:
- -- if the source is modified, then the linkable will
- -- be out of date.
- let linkable = LM unlinked_time this_mod
- (hs_unlinked ++ stub_o)
-
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = Just linkable })
- HscNothing ->
- do (iface, changed, details) <- hscSimpleIface hsc_env tc_result mb_old_hash
- when (gopt Opt_WriteInterface dflags) $
- hscWriteIface dflags iface changed summary
- let linkable = if isHsBoot src_flavour
- then maybe_old_linkable
- else Just (LM (ms_hs_date summary) this_mod [])
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = linkable })
- _ ->
- case ms_hsc_src summary of
- HsBootMerge -> panic "This driver can't handle it"
- HsBootFile ->
- do (iface, changed, details) <- hscSimpleIface hsc_env tc_result mb_old_hash
- hscWriteIface dflags iface changed summary
-
- touchObjectFile dflags object_filename
-
- return (HomeModInfo{
- hm_details = details,
- hm_iface = iface,
- hm_linkable = maybe_old_linkable })
-
- HsSrcFile ->
- do guts0 <- hscDesugar hsc_env summary tc_result
- guts <- hscSimplify hsc_env guts0
- (iface, changed, details, cgguts) <- hscNormalIface hsc_env guts mb_old_hash
- hscWriteIface dflags iface changed summary
-
- -- We're in --make mode: finish the compilation pipeline.
- let mod_name = ms_mod_name summary
- _ <- runPipeline StopLn hsc_env
- (output_fn,
- Just (HscOut src_flavour mod_name (HscRecomp cgguts summary)))
- (Just basename)
- Persistent
- (Just location)
- Nothing
- -- The object filename comes from the ModLocation
- o_time <- getModificationUTCTime object_filename
- let linkable = LM o_time this_mod [DotO object_filename]
-
- return (HomeModInfo{ hm_details = details,
- hm_iface = iface,
- hm_linkable = Just linkable })
+ (status, hmi0) <- hscIncrementalCompile
+ always_do_basic_recompilation_check
+ m_tc_result mHscMessage
+ hsc_env summary source_modified mb_old_iface (mod_index, nmods)
+
+ case (status, hsc_lang) of
+ (HscUpToDate, _) ->
+ ASSERT( isJust maybe_old_linkable || isNoLink (ghcLink dflags) )
+ return hmi0 { hm_linkable = maybe_old_linkable }
+ (HscNotGeneratingCode, HscNothing) ->
+ let mb_linkable = if isHsBoot src_flavour
+ then Nothing
+ -- TODO: Questionable.
+ else Just (LM (ms_hs_date summary) this_mod [])
+ in return hmi0 { hm_linkable = mb_linkable }
+ (HscNotGeneratingCode, _) -> panic "compileOne HscNotGeneratingCode"
+ (_, HscNothing) -> panic "compileOne HscNothing"
+ (HscUpdateBoot, HscInterpreted) -> do
+ return hmi0
+ (HscUpdateBoot, _) -> do
+ touchObjectFile dflags object_filename
+ return hmi0
+ (HscUpdateBootMerge, HscInterpreted) ->
+ let linkable = LM (ms_hs_date summary) this_mod []
+ in return hmi0 { hm_linkable = Just linkable }
+ (HscUpdateBootMerge, _) -> do
+ output_fn <- getOutputFilename next_phase
+ Temporary basename dflags next_phase (Just location)
+
+ -- #10660: Use the pipeline instead of calling
+ -- compileEmptyStub directly, so -dynamic-too gets
+ -- handled properly
+ _ <- runPipeline StopLn hsc_env
+ (output_fn,
+ Just (HscOut src_flavour
+ mod_name HscUpdateBootMerge))
+ (Just basename)
+ Persistent
+ (Just location)
+ Nothing
+ o_time <- getModificationUTCTime object_filename
+ let linkable = LM o_time this_mod [DotO object_filename]
+ return hmi0 { hm_linkable = Just linkable }
+ (HscRecomp cgguts summary, HscInterpreted) -> do
+ (hasStub, comp_bc, modBreaks) <- hscInteractive hsc_env cgguts summary
+
+ stub_o <- case hasStub of
+ Nothing -> return []
+ Just stub_c -> do
+ stub_o <- compileStub hsc_env stub_c
+ return [DotO stub_o]
+
+ let hs_unlinked = [BCOs comp_bc modBreaks]
+ unlinked_time = ms_hs_date summary
+ -- Why do we use the timestamp of the source file here,
+ -- rather than the current time? This works better in
+ -- the case where the local clock is out of sync
+ -- with the filesystem's clock. It's just as accurate:
+ -- if the source is modified, then the linkable will
+ -- be out of date.
+ let linkable = LM unlinked_time (ms_mod summary)
+ (hs_unlinked ++ stub_o)
+ return hmi0 { hm_linkable = Just linkable }
+ (HscRecomp cgguts summary, _) -> do
+ output_fn <- getOutputFilename next_phase
+ Temporary basename dflags next_phase (Just location)
+ -- We're in --make mode: finish the compilation pipeline.
+ _ <- runPipeline StopLn hsc_env
+ (output_fn,
+ Just (HscOut src_flavour mod_name (HscRecomp cgguts summary)))
+ (Just basename)
+ Persistent
+ (Just location)
+ Nothing
+ -- The object filename comes from the ModLocation
+ o_time <- getModificationUTCTime object_filename
+ let linkable = LM o_time this_mod [DotO object_filename]
+ return hmi0 { hm_linkable = Just linkable }
+
where dflags0 = ms_hspp_opts summary
- this_mod = ms_mod summary
- src_flavour = ms_hsc_src summary
location = ms_location summary
input_fn = expectJust "compile:hs" (ml_hs_file location)
input_fnpp = ms_hspp_file summary
@@ -310,6 +225,13 @@ compileOne' m_tc_result mHscMessage
isDynWay = any (== WayDyn) (ways dflags0)
isProfWay = any (== WayProf) (ways dflags0)
+
+ src_flavour = ms_hsc_src summary
+ this_mod = ms_mod summary
+ mod_name = ms_mod_name summary
+ next_phase = hscPostBackendPhase dflags src_flavour hsc_lang
+ object_filename = ml_obj_file location
+
-- #8180 - when using TemplateHaskell, switch on -dynamic-too so
-- the linker can correctly load the object files.
@@ -329,15 +251,12 @@ compileOne' m_tc_result mHscMessage
-- Figure out what lang we're generating
hsc_lang = hscTarget dflags
- -- ... and what the next phase should be
- next_phase = hscPostBackendPhase dflags src_flavour hsc_lang
-- -fforce-recomp should also work with --make
force_recomp = gopt Opt_ForceRecomp dflags
source_modified
| force_recomp = SourceModified
| otherwise = source_modified0
- object_filename = ml_obj_file location
always_do_basic_recompilation_check = case hsc_lang of
HscInterpreted -> True
@@ -478,7 +397,7 @@ link' dflags batch_attempt_linking hpt
return Succeeded
-linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [PackageKey] -> IO Bool
+linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [UnitId] -> IO Bool
linkingNeeded dflags 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
@@ -514,7 +433,7 @@ linkingNeeded dflags staticLink linkables pkg_deps = do
-- Returns 'False' if it was, and we can avoid linking, because the
-- previous binary was linked with "the same options".
-checkLinkInfo :: DynFlags -> [PackageKey] -> FilePath -> IO Bool
+checkLinkInfo :: DynFlags -> [UnitId] -> FilePath -> IO Bool
checkLinkInfo dflags pkg_deps exe_file
| not (platformSupportsSavingLinkOpts (platformOS (targetPlatform dflags)))
-- ToDo: Windows and OS X do not use the ELF binary format, so
@@ -1087,8 +1006,9 @@ runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0
ms_merge_imps = (False, []) }
-- run the compiler!
- result <- liftIO $ hscCompileOneShot hsc_env'
- mod_summary source_unchanged
+ let msg hsc_env _ what _ = oneShotMsg hsc_env what
+ (result, _) <- liftIO $ hscIncrementalCompile True Nothing (Just msg) hsc_env'
+ mod_summary source_unchanged Nothing (1,1)
return (HscOut src_flavour mod_name result,
panic "HscOut doesn't have an input filename")
@@ -1261,7 +1181,7 @@ runPhase (RealPhase cc_phase) input_fn dflags
-- way we do the import depends on whether we're currently compiling
-- the base package or not.
++ (if platformOS platform == OSMinGW32 &&
- thisPackage dflags == basePackageKey
+ thisPackage dflags == baseUnitId
then [ "-DCOMPILING_BASE_PACKAGE" ]
else [])
@@ -1338,14 +1258,7 @@ runPhase (RealPhase (As with_cpp)) input_fn dflags
-- assembler, so we use clang as the assembler instead. (#5636)
let whichAsProg | hscTarget dflags == HscLlvm &&
platformOS (targetPlatform dflags) == OSDarwin
- = do
- -- be careful what options we call clang with
- -- see #5903 and #7617 for bugs caused by this.
- llvmVer <- liftIO $ figureLlvmVersion dflags
- return $ case llvmVer of
- Just n | n >= 30 -> SysTools.runClang
- _ -> SysTools.runAs
-
+ = return SysTools.runClang
| otherwise = return SysTools.runAs
as_prog <- whichAsProg
@@ -1487,18 +1400,15 @@ runPhase (RealPhase SplitAs) _input_fn dflags
runPhase (RealPhase LlvmOpt) input_fn dflags
= do
- ver <- liftIO $ readIORef (llvmVersion dflags)
-
let opt_lvl = max 0 (min 2 $ optLevel 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
-- passes only, so if the user is passing us extra options we assume
-- they know what they are doing and don't get in the way.
optFlag = if null (getOpts dflags opt_lo)
- then map SysTools.Option $ words (llvmOpts ver !! opt_lvl)
+ then map SysTools.Option $ words (llvmOpts !! opt_lvl)
else []
- tbaa | ver < 29 = "" -- no tbaa in 2.8 and earlier
- | gopt Opt_LlvmTBAA dflags = "--enable-tbaa=true"
+ tbaa | gopt Opt_LlvmTBAA dflags = "--enable-tbaa=true"
| otherwise = "--enable-tbaa=false"
@@ -1512,22 +1422,19 @@ runPhase (RealPhase LlvmOpt) input_fn dflags
++ [SysTools.Option tbaa])
return (RealPhase LlvmLlc, output_fn)
- where
+ where
-- we always (unless -optlo specified) run Opt since we rely on it to
-- fix up some pretty big deficiencies in the code we generate
- llvmOpts ver = [ "-mem2reg -globalopt"
- , if ver >= 34 then "-O1 -globalopt" else "-O1"
- -- LLVM 3.4 -O1 doesn't eliminate aliases reliably (bug #8855)
- , "-O2"
- ]
+ llvmOpts = [ "-mem2reg -globalopt"
+ , "-O1 -globalopt"
+ , "-O2"
+ ]
-----------------------------------------------------------------------------
-- LlvmLlc phase
runPhase (RealPhase LlvmLlc) input_fn dflags
= do
- ver <- liftIO $ readIORef (llvmVersion dflags)
-
let opt_lvl = max 0 (min 2 $ optLevel dflags)
-- iOS requires external references to be loaded indirectly from the
-- DATA segment or dyld traps at runtime writing into TEXT: see #7722
@@ -1535,8 +1442,7 @@ runPhase (RealPhase LlvmLlc) input_fn dflags
| gopt Opt_PIC dflags = "pic"
| not (gopt Opt_Static dflags) = "dynamic-no-pic"
| otherwise = "static"
- tbaa | ver < 29 = "" -- no tbaa in 2.8 and earlier
- | gopt Opt_LlvmTBAA dflags = "--enable-tbaa=true"
+ tbaa | gopt Opt_LlvmTBAA dflags = "--enable-tbaa=true"
| otherwise = "--enable-tbaa=false"
-- hidden debugging flag '-dno-llvm-mangler' to skip mangling
@@ -1544,13 +1450,8 @@ runPhase (RealPhase LlvmLlc) input_fn dflags
False -> LlvmMangle
True | gopt Opt_SplitObjs dflags -> Splitter
True -> As False
-
- output_fn <- phaseOutputFilename next_phase
- -- AVX can cause LLVM 3.2 to generate a C-like frame pointer
- -- prelude, see #9391
- when (ver == 32 && isAvxEnabled dflags) $ liftIO $ errorMsg dflags $ text
- "Note: LLVM 3.2 has known problems with AVX instructions (see trac #9391)"
+ output_fn <- phaseOutputFilename next_phase
liftIO $ SysTools.runLlvmLlc dflags
([ SysTools.Option (llvmOpts !! opt_lvl),
@@ -1561,7 +1462,7 @@ runPhase (RealPhase LlvmLlc) input_fn dflags
++ map SysTools.Option fpOpts
++ map SysTools.Option abiOpts
++ map SysTools.Option sseOpts
- ++ map SysTools.Option (avxOpts ver)
+ ++ map SysTools.Option avxOpts
++ map SysTools.Option avx512Opts
++ map SysTools.Option stackAlignOpts)
@@ -1574,7 +1475,7 @@ runPhase (RealPhase LlvmLlc) input_fn dflags
-- On ARMv7 using LLVM, LLVM fails to allocate floating point registers
-- while compiling GHC source code. It's probably due to fact that it
-- does not enable VFP by default. Let's do this manually here
- fpOpts = case platformArch (targetPlatform dflags) of
+ fpOpts = case platformArch (targetPlatform dflags) of
ArchARM ARMv7 ext _ -> if (elem VFPv3 ext)
then ["-mattr=+v7,+vfp3"]
else if (elem VFPv3D16 ext)
@@ -1597,11 +1498,10 @@ runPhase (RealPhase LlvmLlc) input_fn dflags
| isSseEnabled dflags = ["-mattr=+sse"]
| otherwise = []
- avxOpts ver | isAvx512fEnabled dflags = ["-mattr=+avx512f"]
- | isAvx2Enabled dflags = ["-mattr=+avx2"]
- | isAvxEnabled dflags = ["-mattr=+avx"]
- | ver == 32 = ["-mattr=-avx"] -- see #9391
- | otherwise = []
+ avxOpts | isAvx512fEnabled dflags = ["-mattr=+avx512f"]
+ | isAvx2Enabled dflags = ["-mattr=+avx2"]
+ | isAvxEnabled dflags = ["-mattr=+avx"]
+ | otherwise = []
avx512Opts =
[ "-mattr=+avx512cd" | isAvx512cdEnabled dflags ] ++
@@ -1693,7 +1593,7 @@ mkExtraObj dflags extn xs
= do cFile <- newTempName dflags extn
oFile <- newTempName dflags "o"
writeFile cFile xs
- let rtsDetails = getPackageDetails dflags rtsPackageKey
+ let rtsDetails = getPackageDetails dflags rtsUnitId
pic_c_flags = picCCOpts dflags
SysTools.runCc dflags
([Option "-c",
@@ -1748,7 +1648,7 @@ mkExtraObjToLinkIntoBinary dflags = do
-- this was included as inline assembly in the main.c file but this
-- is pretty fragile. gas gets upset trying to calculate relative offsets
-- that span the .note section (notably .text) when debug info is present
-mkNoteObjsToLinkIntoBinary :: DynFlags -> [PackageKey] -> IO [FilePath]
+mkNoteObjsToLinkIntoBinary :: DynFlags -> [UnitId] -> IO [FilePath]
mkNoteObjsToLinkIntoBinary dflags dep_packages = do
link_info <- getLinkInfo dflags dep_packages
@@ -1789,7 +1689,7 @@ mkNoteObjsToLinkIntoBinary dflags dep_packages = do
-- link. We save this information in the binary, and the next time we
-- link, if nothing else has changed, we use the link info stored in
-- the existing binary to decide whether to re-link or not.
-getLinkInfo :: DynFlags -> [PackageKey] -> IO String
+getLinkInfo :: DynFlags -> [UnitId] -> IO String
getLinkInfo dflags dep_packages = do
package_link_opts <- getPackageLinkOpts dflags dep_packages
pkg_frameworks <- if platformUsesFrameworks (targetPlatform dflags)
@@ -1810,13 +1710,13 @@ getLinkInfo dflags dep_packages = do
-----------------------------------------------------------------------------
-- Look for the /* GHC_PACKAGES ... */ comment at the top of a .hc file
-getHCFilePackages :: FilePath -> IO [PackageKey]
+getHCFilePackages :: FilePath -> IO [UnitId]
getHCFilePackages filename =
Exception.bracket (openFile filename ReadMode) hClose $ \h -> do
l <- hGetLine h
case l of
'/':'*':' ':'G':'H':'C':'_':'P':'A':'C':'K':'A':'G':'E':'S':rest ->
- return (map stringToPackageKey (words rest))
+ return (map stringToUnitId (words rest))
_other ->
return []
@@ -1833,10 +1733,10 @@ getHCFilePackages filename =
-- read any interface files), so the user must explicitly specify all
-- the packages.
-linkBinary :: DynFlags -> [FilePath] -> [PackageKey] -> IO ()
+linkBinary :: DynFlags -> [FilePath] -> [UnitId] -> IO ()
linkBinary = linkBinary' False
-linkBinary' :: Bool -> DynFlags -> [FilePath] -> [PackageKey] -> IO ()
+linkBinary' :: Bool -> DynFlags -> [FilePath] -> [UnitId] -> IO ()
linkBinary' staticLink dflags o_files dep_packages = do
let platform = targetPlatform dflags
mySettings = settings dflags
@@ -2080,7 +1980,7 @@ maybeCreateManifest dflags exe_filename
| otherwise = return []
-linkDynLibCheck :: DynFlags -> [String] -> [PackageKey] -> IO ()
+linkDynLibCheck :: DynFlags -> [String] -> [UnitId] -> IO ()
linkDynLibCheck dflags o_files dep_packages
= do
when (haveRtsOptsFlags dflags) $ do
@@ -2090,7 +1990,7 @@ linkDynLibCheck dflags o_files dep_packages
linkDynLib dflags o_files dep_packages
-linkStaticLibCheck :: DynFlags -> [String] -> [PackageKey] -> IO ()
+linkStaticLibCheck :: DynFlags -> [String] -> [UnitId] -> IO ()
linkStaticLibCheck dflags o_files dep_packages
= do
when (platformOS (targetPlatform dflags) `notElem` [OSiOS, OSDarwin]) $
@@ -2275,7 +2175,7 @@ haveRtsOptsFlags dflags =
-- | Find out path to @ghcversion.h@ file
getGhcVersionPathName :: DynFlags -> IO FilePath
getGhcVersionPathName dflags = do
- dirs <- getPackageIncludePath dflags [rtsPackageKey]
+ dirs <- getPackageIncludePath dflags [rtsUnitId]
found <- filterM doesFileExist (map (</> "ghcversion.h") dirs)
case found of