Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
0fb37893
by Matthew Pickering at 2025-06-23T13:55:10-04:00
-
3bf6720e
by soulomoon at 2025-06-23T13:55:52-04:00
-
bcd90cf5
by Ben Gamari at 2025-06-23T17:31:13-04:00
-
4e2069ea
by Ben Gamari at 2025-06-23T17:31:13-04:00
-
344d08fe
by Ben Gamari at 2025-06-23T17:31:13-04:00
-
8fdbee83
by Rodrigo Mesquita at 2025-06-23T17:31:13-04:00
-
0a4d4abf
by Rodrigo Mesquita at 2025-06-23T17:31:13-04:00
-
e34b734d
by Ben Gamari at 2025-06-23T17:31:14-04:00
-
f09c2519
by Ben Gamari at 2025-06-23T17:31:14-04:00
29 changed files:
- compiler/GHC.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Home/PackageTable.hs
- distrib/configure.ac.in
- ghc/GHCi/UI.hs
- hadrian/cfg/default.host.target.in
- hadrian/cfg/default.target.in
- hadrian/cfg/system.config.in
- hadrian/src/Builder.hs
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Settings/Builders/RunTest.hs
- m4/fp_settings.m4
- m4/ghc_toolchain.m4
- m4/prep_target_file.m4
- rts/linker/LoadArchive.c
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Target.hs
Changes:
| ... | ... | @@ -859,6 +859,7 @@ setProgramDynFlags_ invalidate_needed dflags = do |
| 859 | 859 | , ue_namever = ghcNameVersion dflags1
|
| 860 | 860 | , ue_home_unit_graph = home_unit_graph
|
| 861 | 861 | , ue_current_unit = ue_currentUnit old_unit_env
|
| 862 | + , ue_module_graph = ue_module_graph old_unit_env
|
|
| 862 | 863 | , ue_eps = ue_eps old_unit_env
|
| 863 | 864 | }
|
| 864 | 865 | modifySession $ \h -> hscSetFlags dflags1 h{ hsc_unit_env = unit_env }
|
| ... | ... | @@ -916,6 +917,7 @@ setProgramHUG_ invalidate_needed new_hug0 = do |
| 916 | 917 | , ue_home_unit_graph = home_unit_graph
|
| 917 | 918 | , ue_current_unit = ue_currentUnit unit_env0
|
| 918 | 919 | , ue_eps = ue_eps unit_env0
|
| 920 | + , ue_module_graph = ue_module_graph unit_env0
|
|
| 919 | 921 | }
|
| 920 | 922 | modifySession $ \h ->
|
| 921 | 923 | -- hscSetFlags takes care of updating the logger as well.
|
| ... | ... | @@ -996,7 +998,7 @@ setProgramHUG_ invalidate_needed new_hug0 = do |
| 996 | 998 | --
|
| 997 | 999 | invalidateModSummaryCache :: GhcMonad m => m ()
|
| 998 | 1000 | invalidateModSummaryCache =
|
| 999 | - modifySession $ \h -> h { hsc_mod_graph = mapMG inval (hsc_mod_graph h) }
|
|
| 1001 | + modifySession $ \hsc_env -> setModuleGraph (mapMG inval (hsc_mod_graph hsc_env)) hsc_env
|
|
| 1000 | 1002 | where
|
| 1001 | 1003 | inval ms = ms { ms_hs_hash = fingerprint0 }
|
| 1002 | 1004 |
| ... | ... | @@ -97,10 +97,11 @@ core2core hsc_env guts@(ModGuts { mg_module = mod |
| 97 | 97 | where
|
| 98 | 98 | dflags = hsc_dflags hsc_env
|
| 99 | 99 | logger = hsc_logger hsc_env
|
| 100 | + unit_env = hsc_unit_env hsc_env
|
|
| 100 | 101 | extra_vars = interactiveInScope (hsc_IC hsc_env)
|
| 101 | 102 | home_pkg_rules = hugRulesBelow hsc_env (moduleUnitId mod)
|
| 102 | 103 | (GWIB { gwib_mod = moduleName mod, gwib_isBoot = NotBoot })
|
| 103 | - name_ppr_ctx = mkNamePprCtx ptc (hsc_unit_env hsc_env) rdr_env
|
|
| 104 | + name_ppr_ctx = mkNamePprCtx ptc unit_env rdr_env
|
|
| 104 | 105 | ptc = initPromotionTickContext dflags
|
| 105 | 106 | -- mod: get the module out of the current HscEnv so we can retrieve it from the monad.
|
| 106 | 107 | -- This is very convienent for the users of the monad (e.g. plugins do not have to
|
| ... | ... | @@ -457,6 +457,7 @@ addUnit u = do |
| 457 | 457 | (homeUnitId home_unit)
|
| 458 | 458 | (HUG.mkHomeUnitEnv unit_state (Just dbs) dflags (ue_hpt old_unit_env) (Just home_unit))
|
| 459 | 459 | , ue_eps = ue_eps old_unit_env
|
| 460 | + , ue_module_graph = ue_module_graph old_unit_env
|
|
| 460 | 461 | }
|
| 461 | 462 | setSession $ hscSetFlags dflags $ hsc_env { hsc_unit_env = unit_env }
|
| 462 | 463 |
| ... | ... | @@ -2,6 +2,8 @@ |
| 2 | 2 | module GHC.Driver.Env
|
| 3 | 3 | ( Hsc(..)
|
| 4 | 4 | , HscEnv (..)
|
| 5 | + , hsc_mod_graph
|
|
| 6 | + , setModuleGraph
|
|
| 5 | 7 | , hscUpdateFlags
|
| 6 | 8 | , hscSetFlags
|
| 7 | 9 | , hsc_home_unit
|
| ... | ... | @@ -130,6 +132,9 @@ hsc_HUE = ue_currentHomeUnitEnv . hsc_unit_env |
| 130 | 132 | hsc_HUG :: HscEnv -> HomeUnitGraph
|
| 131 | 133 | hsc_HUG = ue_home_unit_graph . hsc_unit_env
|
| 132 | 134 | |
| 135 | +hsc_mod_graph :: HscEnv -> ModuleGraph
|
|
| 136 | +hsc_mod_graph = ue_module_graph . hsc_unit_env
|
|
| 137 | + |
|
| 133 | 138 | hsc_all_home_unit_ids :: HscEnv -> Set.Set UnitId
|
| 134 | 139 | hsc_all_home_unit_ids = HUG.allUnits . hsc_HUG
|
| 135 | 140 | |
| ... | ... | @@ -139,6 +144,9 @@ hscInsertHPT hmi hsc_env = UnitEnv.insertHpt hmi (hsc_unit_env hsc_env) |
| 139 | 144 | hscUpdateHUG :: (HomeUnitGraph -> HomeUnitGraph) -> HscEnv -> HscEnv
|
| 140 | 145 | hscUpdateHUG f hsc_env = hsc_env { hsc_unit_env = updateHug f (hsc_unit_env hsc_env) }
|
| 141 | 146 | |
| 147 | +setModuleGraph :: ModuleGraph -> HscEnv -> HscEnv
|
|
| 148 | +setModuleGraph mod_graph hsc_env = hsc_env { hsc_unit_env = (hsc_unit_env hsc_env) { ue_module_graph = mod_graph } }
|
|
| 149 | + |
|
| 142 | 150 | {-
|
| 143 | 151 | |
| 144 | 152 | Note [Target code interpreter]
|
| ... | ... | @@ -220,15 +228,15 @@ hscEPS hsc_env = readIORef (euc_eps (ue_eps (hsc_unit_env hsc_env))) |
| 220 | 228 | -- | Find all rules in modules that are in the transitive closure of the given
|
| 221 | 229 | -- module.
|
| 222 | 230 | hugRulesBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO RuleBase
|
| 223 | -hugRulesBelow hsc uid mn = foldr (flip extendRuleBaseList) emptyRuleBase <$>
|
|
| 224 | - hugSomeThingsBelowUs (md_rules . hm_details) False hsc uid mn
|
|
| 231 | +hugRulesBelow hsc_env uid mn = foldr (flip extendRuleBaseList) emptyRuleBase <$>
|
|
| 232 | + hugSomeThingsBelowUs (md_rules . hm_details) False hsc_env uid mn
|
|
| 225 | 233 | |
| 226 | 234 | -- | Get annotations from all modules "below" this one (in the dependency
|
| 227 | 235 | -- sense) within the home units. If the module is @Nothing@, returns /all/
|
| 228 | 236 | -- annotations in the home units.
|
| 229 | 237 | hugAnnsBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO AnnEnv
|
| 230 | -hugAnnsBelow hsc uid mn = foldr (flip extendAnnEnvList) emptyAnnEnv <$>
|
|
| 231 | - hugSomeThingsBelowUs (md_anns . hm_details) False hsc uid mn
|
|
| 238 | +hugAnnsBelow hsc_env uid mn = foldr (flip extendAnnEnvList) emptyAnnEnv <$>
|
|
| 239 | + hugSomeThingsBelowUs (md_anns . hm_details) False hsc_env uid mn
|
|
| 232 | 240 | |
| 233 | 241 | -- | Find all COMPLETE pragmas in modules that are in the transitive closure of the
|
| 234 | 242 | -- given module.
|
| ... | ... | @@ -237,7 +245,7 @@ hugCompleteSigsBelow hsc uid mn = foldr (++) [] <$> |
| 237 | 245 | hugSomeThingsBelowUs (md_complete_matches . hm_details) False hsc uid mn
|
| 238 | 246 | |
| 239 | 247 | -- | Find instances visible from the given set of imports
|
| 240 | -hugInstancesBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO (InstEnv, [FamInst])
|
|
| 248 | +hugInstancesBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO (InstEnv, [(Module, FamInstEnv)])
|
|
| 241 | 249 | hugInstancesBelow hsc_env uid mnwib = do
|
| 242 | 250 | let mn = gwib_mod mnwib
|
| 243 | 251 | (insts, famInsts) <-
|
| ... | ... | @@ -247,7 +255,7 @@ hugInstancesBelow hsc_env uid mnwib = do |
| 247 | 255 | -- Don't include instances for the current module
|
| 248 | 256 | in if moduleName (mi_module (hm_iface mod_info)) == mn
|
| 249 | 257 | then []
|
| 250 | - else [(md_insts details, md_fam_insts details)])
|
|
| 258 | + else [(md_insts details, [(mi_module $ hm_iface mod_info, extendFamInstEnvList emptyFamInstEnv $ md_fam_insts details)])])
|
|
| 251 | 259 | True -- Include -hi-boot
|
| 252 | 260 | hsc_env
|
| 253 | 261 | uid
|
| ... | ... | @@ -260,7 +268,8 @@ hugInstancesBelow hsc_env uid mnwib = do |
| 260 | 268 | hugSomeThingsBelowUs :: (HomeModInfo -> [a]) -> Bool -> HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO [[a]]
|
| 261 | 269 | -- An explicit check to see if we are in one-shot mode to avoid poking the ModuleGraph thunk
|
| 262 | 270 | -- These things are currently stored in the EPS for home packages. (See #25795 for
|
| 263 | --- progress in removing these kind of checks)
|
|
| 271 | +-- progress in removing these kind of checks; and making these functions of
|
|
| 272 | +-- `UnitEnv` rather than `HscEnv`)
|
|
| 264 | 273 | -- See Note [Downsweep and the ModuleGraph]
|
| 265 | 274 | hugSomeThingsBelowUs _ _ hsc_env _ _ | isOneShot (ghcMode (hsc_dflags hsc_env)) = return []
|
| 266 | 275 | hugSomeThingsBelowUs extract include_hi_boot hsc_env uid mn
|
| ... | ... | @@ -18,7 +18,6 @@ import GHC.Types.Name.Cache |
| 18 | 18 | import GHC.Types.Target
|
| 19 | 19 | import GHC.Types.TypeEnv
|
| 20 | 20 | import GHC.Unit.Finder.Types
|
| 21 | -import GHC.Unit.Module.Graph
|
|
| 22 | 21 | import GHC.Unit.Env
|
| 23 | 22 | import GHC.Utils.Logger
|
| 24 | 23 | import GHC.Utils.TmpFs
|
| ... | ... | @@ -65,10 +64,6 @@ data HscEnv |
| 65 | 64 | hsc_targets :: [Target],
|
| 66 | 65 | -- ^ The targets (or roots) of the current session
|
| 67 | 66 | |
| 68 | - hsc_mod_graph :: ModuleGraph,
|
|
| 69 | - -- ^ The module graph of the current session
|
|
| 70 | - -- See Note [Downsweep and the ModuleGraph] for when this is constructed.
|
|
| 71 | - |
|
| 72 | 67 | hsc_IC :: InteractiveContext,
|
| 73 | 68 | -- ^ The context for evaluating interactive statements
|
| 74 | 69 | |
| ... | ... | @@ -113,3 +108,4 @@ data HscEnv |
| 113 | 108 | , hsc_llvm_config :: !LlvmConfigCache
|
| 114 | 109 | -- ^ LLVM configuration cache.
|
| 115 | 110 | }
|
| 111 | + |
| ... | ... | @@ -332,7 +332,6 @@ newHscEnvWithHUG top_dir top_dynflags cur_unit home_unit_graph = do |
| 332 | 332 | return HscEnv { hsc_dflags = top_dynflags
|
| 333 | 333 | , hsc_logger = setLogFlags logger (initLogFlags top_dynflags)
|
| 334 | 334 | , hsc_targets = []
|
| 335 | - , hsc_mod_graph = emptyMG
|
|
| 336 | 335 | , hsc_IC = emptyInteractiveContext dflags
|
| 337 | 336 | , hsc_NC = nc_var
|
| 338 | 337 | , hsc_FC = fc_var
|
| ... | ... | @@ -190,12 +190,12 @@ depanalE diag_wrapper msg excluded_mods allow_dup_roots = do |
| 190 | 190 | |
| 191 | 191 | all_errs <- liftIO $ HUG.unitEnv_foldWithKey one_unit_messages (return emptyMessages) (hsc_HUG hsc_env)
|
| 192 | 192 | logDiagnostics (GhcDriverMessage <$> all_errs)
|
| 193 | - setSession hsc_env { hsc_mod_graph = mod_graph }
|
|
| 193 | + setSession (setModuleGraph mod_graph hsc_env)
|
|
| 194 | 194 | pure (emptyMessages, mod_graph)
|
| 195 | 195 | else do
|
| 196 | 196 | -- We don't have a complete module dependency graph,
|
| 197 | 197 | -- The graph may be disconnected and is unusable.
|
| 198 | - setSession hsc_env { hsc_mod_graph = emptyMG }
|
|
| 198 | + setSession (setModuleGraph emptyMG hsc_env)
|
|
| 199 | 199 | pure (errs, emptyMG)
|
| 200 | 200 | |
| 201 | 201 | |
| ... | ... | @@ -616,7 +616,7 @@ load' mhmi_cache how_much diag_wrapper mHscMessage mod_graph = do |
| 616 | 616 | -- for any client who might interact with GHC via load'.
|
| 617 | 617 | -- See Note [Timing of plugin initialization]
|
| 618 | 618 | initializeSessionPlugins
|
| 619 | - modifySession $ \hsc_env -> hsc_env { hsc_mod_graph = mod_graph }
|
|
| 619 | + modifySession (setModuleGraph mod_graph)
|
|
| 620 | 620 | guessOutputFile
|
| 621 | 621 | hsc_env <- getSession
|
| 622 | 622 |
| ... | ... | @@ -768,8 +768,9 @@ runHscPhase pipe_env hsc_env0 input_fn src_flavour = do |
| 768 | 768 | -- files. See GHC.Tc.Utils.TcGblEnv.tcg_type_env_var.
|
| 769 | 769 | -- See also Note [hsc_type_env_var hack]
|
| 770 | 770 | type_env_var <- newIORef emptyNameEnv
|
| 771 | - let hsc_env' = hsc_env { hsc_type_env_vars = knotVarsFromModuleEnv (mkModuleEnv [(mod, type_env_var)])
|
|
| 772 | - , hsc_mod_graph = mg }
|
|
| 771 | + let hsc_env' =
|
|
| 772 | + setModuleGraph mg
|
|
| 773 | + hsc_env { hsc_type_env_vars = knotVarsFromModuleEnv (mkModuleEnv [(mod, type_env_var)]) }
|
|
| 773 | 774 | |
| 774 | 775 | |
| 775 | 776 |
| ... | ... | @@ -671,7 +671,7 @@ dontLeakTheHUG thing_inside = do |
| 671 | 671 | -- oneshot mode does not support backpack
|
| 672 | 672 | -- and we want to avoid prodding the hsc_mod_graph thunk
|
| 673 | 673 | | isOneShot (ghcMode (hsc_dflags hsc_env)) = False
|
| 674 | - | mgHasHoles (hsc_mod_graph hsc_env) = True
|
|
| 674 | + | mgHasHoles (ue_module_graph old_unit_env) = True
|
|
| 675 | 675 | | otherwise = False
|
| 676 | 676 | pruneHomeUnitEnv hme = do
|
| 677 | 677 | -- NB: These are empty HPTs because Iface/Load first consults the HPT
|
| ... | ... | @@ -683,19 +683,19 @@ dontLeakTheHUG thing_inside = do |
| 683 | 683 | | otherwise
|
| 684 | 684 | = do
|
| 685 | 685 | hug' <- traverse pruneHomeUnitEnv (ue_home_unit_graph old_unit_env)
|
| 686 | + let !new_mod_graph = emptyMG { mg_mss = panic "cleanTopEnv: mg_mss"
|
|
| 687 | + , mg_graph = panic "cleanTopEnv: mg_graph"
|
|
| 688 | + , mg_has_holes = keepFor20509 }
|
|
| 686 | 689 | return old_unit_env
|
| 687 | 690 | { ue_home_unit_graph = hug'
|
| 691 | + , ue_module_graph = new_mod_graph
|
|
| 688 | 692 | }
|
| 689 | 693 | in do
|
| 690 | 694 | !unit_env <- unit_env_io
|
| 691 | 695 | -- mg_has_holes will be checked again, but nothing else about the module graph
|
| 692 | - let !new_mod_graph = emptyMG { mg_mss = panic "cleanTopEnv: mg_mss"
|
|
| 693 | - , mg_graph = panic "cleanTopEnv: mg_graph"
|
|
| 694 | - , mg_has_holes = keepFor20509 }
|
|
| 695 | 696 | pure $
|
| 696 | 697 | hsc_env
|
| 697 | 698 | { hsc_targets = panic "cleanTopEnv: hsc_targets"
|
| 698 | - , hsc_mod_graph = new_mod_graph
|
|
| 699 | 699 | , hsc_IC = panic "cleanTopEnv: hsc_IC"
|
| 700 | 700 | , hsc_type_env_vars = case maybe_type_vars of
|
| 701 | 701 | Just vars -> vars
|
| ... | ... | @@ -286,8 +286,8 @@ why we still do redundant checks. |
| 286 | 286 | -- We don't need to check the current module, this is done in
|
| 287 | 287 | -- tcExtendLocalFamInstEnv.
|
| 288 | 288 | -- See Note [The type family instance consistency story].
|
| 289 | -checkFamInstConsistency :: [Module] -> TcM ()
|
|
| 290 | -checkFamInstConsistency directlyImpMods
|
|
| 289 | +checkFamInstConsistency :: ModuleEnv FamInstEnv -> [Module] -> TcM ()
|
|
| 290 | +checkFamInstConsistency hpt_fam_insts directlyImpMods
|
|
| 291 | 291 | = do { (eps, hug) <- getEpsAndHug
|
| 292 | 292 | ; traceTc "checkFamInstConsistency" (ppr directlyImpMods)
|
| 293 | 293 | ; let { -- Fetch the iface of a given module. Must succeed as
|
| ... | ... | @@ -317,7 +317,6 @@ checkFamInstConsistency directlyImpMods |
| 317 | 317 | -- See Note [Order of type family consistency checks]
|
| 318 | 318 | }
|
| 319 | 319 | |
| 320 | - ; hpt_fam_insts <- liftIO $ HUG.allFamInstances hug
|
|
| 321 | 320 | ; debug_consistent_set <- mapM (\x -> (\y -> (x, length y)) <$> modConsistent x) directlyImpMods
|
| 322 | 321 | ; traceTc "init_consistent_set" (ppr debug_consistent_set)
|
| 323 | 322 | ; let init_consistent_set = map fst (reverse (sortOn snd debug_consistent_set))
|
| ... | ... | @@ -120,7 +120,7 @@ import GHC.Core.TyCo.Ppr( debugPprType ) |
| 120 | 120 | import GHC.Core.TyCo.Tidy( tidyTopType )
|
| 121 | 121 | import GHC.Core.FamInstEnv
|
| 122 | 122 | ( FamInst, pprFamInst, famInstsRepTyCons, orphNamesOfFamInst
|
| 123 | - , famInstEnvElts, extendFamInstEnvList, normaliseType )
|
|
| 123 | + , famInstEnvElts, extendFamInstEnvList, normaliseType, emptyFamInstEnv, unionFamInstEnv )
|
|
| 124 | 124 | |
| 125 | 125 | import GHC.Parser.Header ( mkPrelImports )
|
| 126 | 126 | |
| ... | ... | @@ -467,8 +467,8 @@ tcRnImports hsc_env import_decls |
| 467 | 467 | = do { (rn_imports, imp_user_spec, rdr_env, imports) <- rnImports import_decls
|
| 468 | 468 | -- Get the default declarations for the classes imported by this module
|
| 469 | 469 | -- and group them by class.
|
| 470 | - ; tc_defaults <-(NE.groupBy ((==) `on` cd_class) . (concatMap defaultList))
|
|
| 471 | - <$> tcGetClsDefaults (M.keys $ imp_mods imports)
|
|
| 470 | + ; tc_defaults <- NE.groupBy ((==) `on` cd_class) . (concatMap defaultList)
|
|
| 471 | + <$> tcGetClsDefaults (M.keys $ imp_mods imports)
|
|
| 472 | 472 | ; this_mod <- getModule
|
| 473 | 473 | ; gbl_env <- getGblEnv
|
| 474 | 474 | ; let unitId = homeUnitId $ hsc_home_unit hsc_env
|
| ... | ... | @@ -480,8 +480,10 @@ tcRnImports hsc_env import_decls |
| 480 | 480 | -- filtering also ensures that we don't see instances from
|
| 481 | 481 | -- modules batch (@--make@) compiled before this one, but
|
| 482 | 482 | -- which are not below this one.
|
| 483 | - ; (home_insts, home_fam_insts) <- liftIO $
|
|
| 483 | + ; (home_insts, home_mod_fam_inst_env) <- liftIO $
|
|
| 484 | 484 | hugInstancesBelow hsc_env unitId mnwib
|
| 485 | + ; let home_fam_inst_env = foldl' unionFamInstEnv emptyFamInstEnv $ snd <$> home_mod_fam_inst_env
|
|
| 486 | + ; let hpt_fam_insts = mkModuleEnv home_mod_fam_inst_env
|
|
| 485 | 487 | |
| 486 | 488 | -- We use 'unsafeInterleaveIO' to avoid redundant memory allocations
|
| 487 | 489 | -- See Note [Lazily loading COMPLETE pragmas] from GHC.HsToCore.Monad
|
| ... | ... | @@ -507,8 +509,7 @@ tcRnImports hsc_env import_decls |
| 507 | 509 | tcg_rn_imports = rn_imports,
|
| 508 | 510 | tcg_default = foldMap subsume tc_defaults,
|
| 509 | 511 | tcg_inst_env = tcg_inst_env gbl `unionInstEnv` home_insts,
|
| 510 | - tcg_fam_inst_env = extendFamInstEnvList (tcg_fam_inst_env gbl)
|
|
| 511 | - home_fam_insts
|
|
| 512 | + tcg_fam_inst_env = unionFamInstEnv (tcg_fam_inst_env gbl) home_fam_inst_env
|
|
| 512 | 513 | }) $ do {
|
| 513 | 514 | |
| 514 | 515 | ; traceRn "rn1" (ppr (imp_direct_dep_mods imports))
|
| ... | ... | @@ -538,7 +539,7 @@ tcRnImports hsc_env import_decls |
| 538 | 539 | $ imports }
|
| 539 | 540 | ; logger <- getLogger
|
| 540 | 541 | ; withTiming logger (text "ConsistencyCheck"<+>brackets (ppr this_mod)) (const ())
|
| 541 | - $ checkFamInstConsistency dir_imp_mods
|
|
| 542 | + $ checkFamInstConsistency hpt_fam_insts dir_imp_mods
|
|
| 542 | 543 | ; traceRn "rn1: } checking family instance consistency" empty
|
| 543 | 544 | |
| 544 | 545 | ; gbl_env <- getGblEnv
|
| ... | ... | @@ -2109,7 +2110,7 @@ for the unit portion of the graph, if it's not already been performed. |
| 2109 | 2110 | withInteractiveModuleNode :: HscEnv -> TcM a -> TcM a
|
| 2110 | 2111 | withInteractiveModuleNode hsc_env thing_inside = do
|
| 2111 | 2112 | mg <- liftIO $ downsweepInteractiveImports hsc_env (hsc_IC hsc_env)
|
| 2112 | - updTopEnv (\env -> env { hsc_mod_graph = mg }) thing_inside
|
|
| 2113 | + updTopEnv (setModuleGraph mg) thing_inside
|
|
| 2113 | 2114 | |
| 2114 | 2115 | |
| 2115 | 2116 | runTcInteractive :: HscEnv -> TcRn a -> IO (Messages TcRnMessage, Maybe a)
|
| ... | ... | @@ -23,21 +23,22 @@ |
| 23 | 23 | -- ┌▽────────────┐ │ │
|
| 24 | 24 | -- │HomeUnitGraph│ │ │
|
| 25 | 25 | -- └┬────────────┘ │ │
|
| 26 | --- ┌▽─────────────────▽┐ │
|
|
| 27 | --- │UnitEnv │ │
|
|
| 28 | --- └┬──────────────────┘ │
|
|
| 29 | --- ┌▽───────────────────────────────────────▽┐
|
|
| 30 | --- │HscEnv │
|
|
| 31 | --- └─────────────────────────────────────────┘
|
|
| 26 | +-- ┌▽─────────────────▽─────────────────────▽┐
|
|
| 27 | +-- │UnitEnv │
|
|
| 28 | +-- └┬─────────────-──────────────────────────┘
|
|
| 29 | +-- │
|
|
| 30 | +-- │
|
|
| 31 | +-- ┌▽──────────────────────────────────────▽┐
|
|
| 32 | +-- │HscEnv │
|
|
| 33 | +-- └────────────────────────────────────────┘
|
|
| 32 | 34 | -- @
|
| 33 | 35 | --
|
| 34 | --- The 'UnitEnv' references both the 'HomeUnitGraph' (with all the home unit
|
|
| 35 | --- modules) and the 'ExternalPackageState' (information about all
|
|
| 36 | --- non-home/external units). The 'HscEnv' references this 'UnitEnv' and the
|
|
| 37 | --- 'ModuleGraph' (which describes the relationship between the modules being
|
|
| 38 | --- compiled). The 'HomeUnitGraph' has one 'HomePackageTable' for every unit.
|
|
| 39 | ---
|
|
| 40 | --- TODO: Arguably, the 'ModuleGraph' should be part of 'UnitEnv' rather than being in the 'HscEnv'.
|
|
| 36 | +-- The 'UnitEnv' references the 'HomeUnitGraph' (with all the home unit
|
|
| 37 | +-- modules), the 'ExternalPackageState' (information about all
|
|
| 38 | +-- non-home/external units), and the 'ModuleGraph' (which describes the
|
|
| 39 | +-- relationship between the modules being compiled).
|
|
| 40 | +-- The 'HscEnv' references this 'UnitEnv'.
|
|
| 41 | +-- The 'HomeUnitGraph' has one 'HomePackageTable' for every unit.
|
|
| 41 | 42 | module GHC.Unit.Env
|
| 42 | 43 | ( UnitEnv (..)
|
| 43 | 44 | , initUnitEnv
|
| ... | ... | @@ -119,6 +120,7 @@ import GHC.Unit.Home.ModInfo |
| 119 | 120 | import GHC.Unit.Home.PackageTable
|
| 120 | 121 | import GHC.Unit.Home.Graph (HomeUnitGraph, HomeUnitEnv)
|
| 121 | 122 | import qualified GHC.Unit.Home.Graph as HUG
|
| 123 | +import GHC.Unit.Module.Graph
|
|
| 122 | 124 | |
| 123 | 125 | import GHC.Platform
|
| 124 | 126 | import GHC.Settings
|
| ... | ... | @@ -163,6 +165,10 @@ data UnitEnv = UnitEnv |
| 163 | 165 | |
| 164 | 166 | , ue_current_unit :: UnitId
|
| 165 | 167 | |
| 168 | + , ue_module_graph :: ModuleGraph
|
|
| 169 | + -- ^ The module graph of the current session
|
|
| 170 | + -- See Note [Downsweep and the ModuleGraph] for when this is constructed.
|
|
| 171 | + |
|
| 166 | 172 | , ue_home_unit_graph :: !HomeUnitGraph
|
| 167 | 173 | -- See Note [Multiple Home Units]
|
| 168 | 174 | |
| ... | ... | @@ -182,6 +188,7 @@ initUnitEnv cur_unit hug namever platform = do |
| 182 | 188 | return $ UnitEnv
|
| 183 | 189 | { ue_eps = eps
|
| 184 | 190 | , ue_home_unit_graph = hug
|
| 191 | + , ue_module_graph = emptyMG
|
|
| 185 | 192 | , ue_current_unit = cur_unit
|
| 186 | 193 | , ue_platform = platform
|
| 187 | 194 | , ue_namever = namever
|
| ... | ... | @@ -43,7 +43,6 @@ module GHC.Unit.Home.Graph |
| 43 | 43 | |
| 44 | 44 | -- * Very important queries
|
| 45 | 45 | , allInstances
|
| 46 | - , allFamInstances
|
|
| 47 | 46 | , allAnns
|
| 48 | 47 | , allCompleteSigs
|
| 49 | 48 | |
| ... | ... | @@ -110,10 +109,6 @@ allInstances hug = foldr go (pure (emptyInstEnv, [])) hug where |
| 110 | 109 | go hue = liftA2 (\(a,b) (a',b') -> (a `unionInstEnv` a', b ++ b'))
|
| 111 | 110 | (hptAllInstances (homeUnitEnv_hpt hue))
|
| 112 | 111 | |
| 113 | -allFamInstances :: HomeUnitGraph -> IO (ModuleEnv FamInstEnv)
|
|
| 114 | -allFamInstances hug = foldr go (pure emptyModuleEnv) hug where
|
|
| 115 | - go hue = liftA2 plusModuleEnv (hptAllFamInstances (homeUnitEnv_hpt hue))
|
|
| 116 | - |
|
| 117 | 112 | allAnns :: HomeUnitGraph -> IO AnnEnv
|
| 118 | 113 | allAnns hug = foldr go (pure emptyAnnEnv) hug where
|
| 119 | 114 | go hue = liftA2 plusAnnEnv (hptAllAnnotations (homeUnitEnv_hpt hue))
|
| ... | ... | @@ -41,7 +41,6 @@ module GHC.Unit.Home.PackageTable |
| 41 | 41 | -- * Queries about home modules
|
| 42 | 42 | , hptCompleteSigs
|
| 43 | 43 | , hptAllInstances
|
| 44 | - , hptAllFamInstances
|
|
| 45 | 44 | , hptAllAnnotations
|
| 46 | 45 | |
| 47 | 46 | -- ** More Traversal-based queries
|
| ... | ... | @@ -208,14 +207,6 @@ hptAllInstances hpt = do |
| 208 | 207 | let (insts, famInsts) = unzip hits
|
| 209 | 208 | return (foldl' unionInstEnv emptyInstEnv insts, concat famInsts)
|
| 210 | 209 | |
| 211 | --- | Find all the family instance declarations from the HPT
|
|
| 212 | -hptAllFamInstances :: HomePackageTable -> IO (ModuleEnv FamInstEnv)
|
|
| 213 | -hptAllFamInstances = fmap mkModuleEnv . concatHpt (\hmi -> [(hmiModule hmi, hmiFamInstEnv hmi)])
|
|
| 214 | - where
|
|
| 215 | - hmiModule = mi_module . hm_iface
|
|
| 216 | - hmiFamInstEnv = extendFamInstEnvList emptyFamInstEnv
|
|
| 217 | - . md_fam_insts . hm_details
|
|
| 218 | - |
|
| 219 | 210 | -- | All annotations from the HPT
|
| 220 | 211 | hptAllAnnotations :: HomePackageTable -> IO AnnEnv
|
| 221 | 212 | hptAllAnnotations = fmap mkAnnEnv . concatHpt (md_anns . hm_details)
|
| ... | ... | @@ -216,7 +216,7 @@ AC_SUBST([LlvmAsCmd]) |
| 216 | 216 | |
| 217 | 217 | dnl We know that `clang` supports `--target` and it is necessary to pass it
|
| 218 | 218 | dnl lest we see #25793.
|
| 219 | -if test -z "$LlvmAsFlags" ; then
|
|
| 219 | +if test -z "$LlvmAsFlags" && ! test -z "$LlvmTarget"; then
|
|
| 220 | 220 | LlvmAsFlags="--target=$LlvmTarget"
|
| 221 | 221 | fi
|
| 222 | 222 | AC_SUBST([LlvmAsFlags])
|
| ... | ... | @@ -4680,7 +4680,7 @@ clearHPTs = do |
| 4680 | 4680 | let pruneHomeUnitEnv hme = liftIO $ do
|
| 4681 | 4681 | emptyHpt <- emptyHomePackageTable
|
| 4682 | 4682 | pure hme{ homeUnitEnv_hpt = emptyHpt }
|
| 4683 | - discardMG hsc = hsc { hsc_mod_graph = GHC.emptyMG }
|
|
| 4683 | + discardMG hsc = setModuleGraph GHC.emptyMG hsc
|
|
| 4684 | 4684 | modifySessionM $ \hsc_env -> do
|
| 4685 | 4685 | hug' <- traverse pruneHomeUnitEnv $ hsc_HUG hsc_env
|
| 4686 | 4686 | pure $ discardMG $ discardIC $ hscUpdateHUG (const hug') hsc_env
|
| ... | ... | @@ -38,5 +38,10 @@ Target |
| 38 | 38 | , tgtRanlib = Nothing
|
| 39 | 39 | , tgtNm = Nm {nmProgram = Program {prgPath = "", prgFlags = []}}
|
| 40 | 40 | , tgtMergeObjs = Just (MergeObjs {mergeObjsProgram = Program {prgPath = "@LD_STAGE0@", prgFlags = ["-r"]}, mergeObjsSupportsResponseFiles = False})
|
| 41 | +, tgtLlc = Nothing
|
|
| 42 | +, tgtOpt = Nothing
|
|
| 43 | +, tgtLlvmAs = Nothing
|
|
| 41 | 44 | , tgtWindres = Nothing
|
| 45 | +, tgtOtool = Nothing
|
|
| 46 | +, tgtInstallNameTool = Nothing
|
|
| 42 | 47 | } |
| ... | ... | @@ -38,5 +38,10 @@ Target |
| 38 | 38 | , tgtRanlib = Just (Ranlib {ranlibProgram = Program {prgPath = "@RanlibCmd@", prgFlags = []}})
|
| 39 | 39 | , tgtNm = Nm {nmProgram = Program {prgPath = "@NmCmd@", prgFlags = []}}
|
| 40 | 40 | , tgtMergeObjs = @MergeObjsCmdMaybe@
|
| 41 | +, tgtLlc = @LlcCmdMaybeProg@
|
|
| 42 | +, tgtOpt = @OptCmdMaybeProg@
|
|
| 43 | +, tgtLlvmAs = @LlvmAsCmdMaybeProg@
|
|
| 41 | 44 | , tgtWindres = @WindresCmdMaybeProg@
|
| 45 | +, tgtOtool = @OtoolCmdMaybeProg@
|
|
| 46 | +, tgtInstallNameTool = @InstallNameToolCmdMaybeProg@
|
|
| 42 | 47 | } |
| ... | ... | @@ -79,13 +79,6 @@ project-git-commit-id = @ProjectGitCommitId@ |
| 79 | 79 | # generated by configure, to generated being by the build system. Many of these
|
| 80 | 80 | # might become redundant.
|
| 81 | 81 | # See Note [tooldir: How GHC finds mingw on Windows]
|
| 82 | - |
|
| 83 | -settings-otool-command = @SettingsOtoolCommand@
|
|
| 84 | -settings-install_name_tool-command = @SettingsInstallNameToolCommand@
|
|
| 85 | -settings-llc-command = @SettingsLlcCommand@
|
|
| 86 | -settings-opt-command = @SettingsOptCommand@
|
|
| 87 | -settings-llvm-as-command = @SettingsLlvmAsCommand@
|
|
| 88 | -settings-llvm-as-flags = @SettingsLlvmAsFlags@
|
|
| 89 | 82 | settings-use-distro-mingw = @SettingsUseDistroMINGW@
|
| 90 | 83 | |
| 91 | 84 | target-has-libm = @TargetHasLibm@
|
| ... | ... | @@ -34,7 +34,6 @@ import Base |
| 34 | 34 | import Context
|
| 35 | 35 | import Oracles.Flag
|
| 36 | 36 | import Oracles.Setting (setting, Setting(..))
|
| 37 | -import Oracles.Setting (settingsFileSetting, ToolchainSetting(..))
|
|
| 38 | 37 | import Packages
|
| 39 | 38 | |
| 40 | 39 | import GHC.IO.Encoding (getFileSystemEncoding)
|
| ... | ... | @@ -240,7 +239,7 @@ instance H.Builder Builder where |
| 240 | 239 | Ghc _ st -> do
|
| 241 | 240 | root <- buildRoot
|
| 242 | 241 | unlitPath <- builderPath Unlit
|
| 243 | - distro_mingw <- settingsFileSetting ToolchainSetting_DistroMinGW
|
|
| 242 | + distro_mingw <- lookupSystemConfig "settings-use-distro-mingw"
|
|
| 244 | 243 | libffi_adjustors <- useLibffiForAdjustors
|
| 245 | 244 | use_system_ffi <- flag UseSystemFfi
|
| 246 | 245 |
| ... | ... | @@ -2,7 +2,6 @@ module Oracles.Setting ( |
| 2 | 2 | configFile,
|
| 3 | 3 | -- * Settings
|
| 4 | 4 | Setting (..), setting, getSetting,
|
| 5 | - ToolchainSetting (..), settingsFileSetting,
|
|
| 6 | 5 | |
| 7 | 6 | -- * Helpers
|
| 8 | 7 | ghcCanonVersion, cmdLineLengthLimit, targetSupportsRPaths, topDirectory,
|
| ... | ... | @@ -75,25 +74,6 @@ data Setting = CursesIncludeDir |
| 75 | 74 | | BourneShell
|
| 76 | 75 | | EmsdkVersion
|
| 77 | 76 | |
| 78 | --- TODO compute solely in Hadrian, removing these variables' definitions
|
|
| 79 | --- from aclocal.m4 whenever they can be calculated from other variables
|
|
| 80 | --- already fed into Hadrian.
|
|
| 81 | - |
|
| 82 | --- | All 'ToolchainSetting's are computed by the ghc-toolchain utility for configuring toolchains.
|
|
| 83 | --- This used to be defined by 'FP_SETTINGS' in aclocal.m4.
|
|
| 84 | ---
|
|
| 85 | --- TODO: We should be able to drop this completely, after moving all the toolchain settings to ghc-toolchain
|
|
| 86 | --- Move to ghc-toolchain and to the Target files generated by configure and ghc-toolchain
|
|
| 87 | --- * First we will get rid of DistroMinGW when we fix the windows build
|
|
| 88 | -data ToolchainSetting
|
|
| 89 | - = ToolchainSetting_OtoolCommand
|
|
| 90 | - | ToolchainSetting_InstallNameToolCommand
|
|
| 91 | - | ToolchainSetting_LlcCommand
|
|
| 92 | - | ToolchainSetting_OptCommand
|
|
| 93 | - | ToolchainSetting_LlvmAsCommand
|
|
| 94 | - | ToolchainSetting_LlvmAsFlags
|
|
| 95 | - | ToolchainSetting_DistroMinGW
|
|
| 96 | - |
|
| 97 | 77 | -- | Look up the value of a 'Setting' in @cfg/system.config@, tracking the
|
| 98 | 78 | -- result.
|
| 99 | 79 | setting :: Setting -> Action String
|
| ... | ... | @@ -134,20 +114,6 @@ setting key = lookupSystemConfig $ case key of |
| 134 | 114 | BourneShell -> "bourne-shell"
|
| 135 | 115 | EmsdkVersion -> "emsdk-version"
|
| 136 | 116 | |
| 137 | --- | Look up the value of a 'SettingList' in @cfg/system.config@, tracking the
|
|
| 138 | --- result.
|
|
| 139 | --- See Note [tooldir: How GHC finds mingw on Windows]
|
|
| 140 | --- ROMES:TODO: This should be queryTargetTargetConfig
|
|
| 141 | -settingsFileSetting :: ToolchainSetting -> Action String
|
|
| 142 | -settingsFileSetting key = lookupSystemConfig $ case key of
|
|
| 143 | - ToolchainSetting_OtoolCommand -> "settings-otool-command"
|
|
| 144 | - ToolchainSetting_InstallNameToolCommand -> "settings-install_name_tool-command"
|
|
| 145 | - ToolchainSetting_LlcCommand -> "settings-llc-command"
|
|
| 146 | - ToolchainSetting_OptCommand -> "settings-opt-command"
|
|
| 147 | - ToolchainSetting_LlvmAsCommand -> "settings-llvm-as-command"
|
|
| 148 | - ToolchainSetting_LlvmAsFlags -> "settings-llvm-as-flags"
|
|
| 149 | - ToolchainSetting_DistroMinGW -> "settings-use-distro-mingw" -- ROMES:TODO: This option doesn't seem to be in ghc-toolchain yet. It corresponds to EnableDistroToolchain
|
|
| 150 | - |
|
| 151 | 117 | -- | An expression that looks up the value of a 'Setting' in @cfg/system.config@,
|
| 152 | 118 | -- tracking the result.
|
| 153 | 119 | getSetting :: Setting -> Expr c b String
|
| ... | ... | @@ -424,7 +424,7 @@ bindistRules = do |
| 424 | 424 | , interpolateSetting "LlvmMinVersion" LlvmMinVersion
|
| 425 | 425 | , interpolateVar "LlvmTarget" $ getTarget tgtLlvmTarget
|
| 426 | 426 | , interpolateSetting "ProjectVersion" ProjectVersion
|
| 427 | - , interpolateVar "SettingsUseDistroMINGW" $ settingsFileSetting ToolchainSetting_DistroMinGW
|
|
| 427 | + , interpolateVar "SettingsUseDistroMINGW" $ lookupSystemConfig "settings-use-distro-mingw"
|
|
| 428 | 428 | , interpolateVar "TablesNextToCode" $ yesNo <$> getTarget tgtTablesNextToCode
|
| 429 | 429 | , interpolateVar "TargetHasLibm" $ lookupSystemConfig "target-has-libm"
|
| 430 | 430 | , interpolateVar "TargetPlatform" $ getTarget targetPlatformTriple
|
| ... | ... | @@ -508,9 +508,9 @@ generateSettings settingsFile = do |
| 508 | 508 | , ("ar flags", queryTarget arFlags)
|
| 509 | 509 | , ("ar supports at file", queryTarget arSupportsAtFile')
|
| 510 | 510 | , ("ar supports -L", queryTarget arSupportsDashL')
|
| 511 | - , ("ranlib command", queryTarget ranlibPath)
|
|
| 512 | - , ("otool command", expr $ settingsFileSetting ToolchainSetting_OtoolCommand)
|
|
| 513 | - , ("install_name_tool command", expr $ settingsFileSetting ToolchainSetting_InstallNameToolCommand)
|
|
| 511 | + , ("ranlib command", queryTarget ranlibPath)
|
|
| 512 | + , ("otool command", queryTarget otoolPath)
|
|
| 513 | + , ("install_name_tool command", queryTarget installNameToolPath)
|
|
| 514 | 514 | , ("windres command", queryTarget (maybe "/bin/false" prgPath . tgtWindres)) -- TODO: /bin/false is not available on many distributions by default, but we keep it as it were before the ghc-toolchain patch. Fix-me.
|
| 515 | 515 | , ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit })))
|
| 516 | 516 | , ("cross compiling", expr $ yesNo <$> flag CrossCompiling)
|
| ... | ... | @@ -525,11 +525,11 @@ generateSettings settingsFile = do |
| 525 | 525 | , ("target has libm", expr $ lookupSystemConfig "target-has-libm")
|
| 526 | 526 | , ("Unregisterised", queryTarget (yesNo . tgtUnregisterised))
|
| 527 | 527 | , ("LLVM target", queryTarget tgtLlvmTarget)
|
| 528 | - , ("LLVM llc command", expr $ settingsFileSetting ToolchainSetting_LlcCommand)
|
|
| 529 | - , ("LLVM opt command", expr $ settingsFileSetting ToolchainSetting_OptCommand)
|
|
| 530 | - , ("LLVM llvm-as command", expr $ settingsFileSetting ToolchainSetting_LlvmAsCommand)
|
|
| 531 | - , ("LLVM llvm-as flags", expr $ settingsFileSetting ToolchainSetting_LlvmAsFlags)
|
|
| 532 | - , ("Use inplace MinGW toolchain", expr $ settingsFileSetting ToolchainSetting_DistroMinGW)
|
|
| 528 | + , ("LLVM llc command", queryTarget llcPath)
|
|
| 529 | + , ("LLVM opt command", queryTarget optPath)
|
|
| 530 | + , ("LLVM llvm-as command", queryTarget llvmAsPath)
|
|
| 531 | + , ("LLVM llvm-as flags", queryTarget llvmAsFlags)
|
|
| 532 | + , ("Use inplace MinGW toolchain", expr $ lookupSystemConfig "settings-use-distro-mingw")
|
|
| 533 | 533 | |
| 534 | 534 | , ("target RTS linker only supports shared libraries", expr $ yesNo <$> targetRTSLinkerOnlySupportsSharedLibs)
|
| 535 | 535 | , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter (predStage stage))
|
| ... | ... | @@ -571,10 +571,16 @@ generateSettings settingsFile = do |
| 571 | 571 | linkSupportsFilelist = yesNo . ccLinkSupportsFilelist . tgtCCompilerLink
|
| 572 | 572 | linkSupportsCompactUnwind = yesNo . ccLinkSupportsCompactUnwind . tgtCCompilerLink
|
| 573 | 573 | linkIsGnu = yesNo . ccLinkIsGnu . tgtCCompilerLink
|
| 574 | + llcPath = maybe "" prgPath . tgtLlc
|
|
| 575 | + optPath = maybe "" prgPath . tgtOpt
|
|
| 576 | + llvmAsPath = maybe "" prgPath . tgtLlvmAs
|
|
| 577 | + llvmAsFlags = escapeArgs . maybe [] prgFlags . tgtLlvmAs
|
|
| 574 | 578 | arPath = prgPath . arMkArchive . tgtAr
|
| 575 | 579 | arFlags = escapeArgs . prgFlags . arMkArchive . tgtAr
|
| 576 | 580 | arSupportsAtFile' = yesNo . arSupportsAtFile . tgtAr
|
| 577 | 581 | arSupportsDashL' = yesNo . arSupportsDashL . tgtAr
|
| 582 | + otoolPath = maybe "" prgPath . tgtOtool
|
|
| 583 | + installNameToolPath = maybe "" prgPath . tgtInstallNameTool
|
|
| 578 | 584 | ranlibPath = maybe "" (prgPath . ranlibProgram) . tgtRanlib
|
| 579 | 585 | mergeObjsSupportsResponseFiles' = maybe "NO" (yesNo . mergeObjsSupportsResponseFiles) . tgtMergeObjs
|
| 580 | 586 |
| ... | ... | @@ -127,9 +127,9 @@ inTreeCompilerArgs stg = do |
| 127 | 127 | platform <- queryTargetTarget targetPlatformTriple
|
| 128 | 128 | wordsize <- show @Int . (*8) <$> queryTargetTarget (wordSize2Bytes . tgtWordSize)
|
| 129 | 129 | |
| 130 | - llc_cmd <- settingsFileSetting ToolchainSetting_LlcCommand
|
|
| 131 | - llvm_as_cmd <- settingsFileSetting ToolchainSetting_LlvmAsCommand
|
|
| 132 | - have_llvm <- liftIO (all isJust <$> mapM findExecutable [llc_cmd, llvm_as_cmd])
|
|
| 130 | + llc_cmd <- queryTargetTarget tgtLlc
|
|
| 131 | + llvm_as_cmd <- queryTargetTarget tgtLlvmAs
|
|
| 132 | + let have_llvm = all isJust [llc_cmd, llvm_as_cmd]
|
|
| 133 | 133 | |
| 134 | 134 | top <- topDirectory
|
| 135 | 135 |
| ... | ... | @@ -136,14 +136,7 @@ AC_DEFUN([FP_SETTINGS], |
| 136 | 136 | fi
|
| 137 | 137 | |
| 138 | 138 | # Mac-only tools
|
| 139 | - if test -z "$OtoolCmd"; then
|
|
| 140 | - OtoolCmd="otool"
|
|
| 141 | - fi
|
|
| 142 | 139 | SettingsOtoolCommand="$OtoolCmd"
|
| 143 | - |
|
| 144 | - if test -z "$InstallNameToolCmd"; then
|
|
| 145 | - InstallNameToolCmd="install_name_tool"
|
|
| 146 | - fi
|
|
| 147 | 140 | SettingsInstallNameToolCommand="$InstallNameToolCmd"
|
| 148 | 141 | |
| 149 | 142 | SettingsCCompilerSupportsNoPie="$CONF_GCC_SUPPORTS_NO_PIE"
|
| ... | ... | @@ -107,6 +107,9 @@ AC_DEFUN([FIND_GHC_TOOLCHAIN], |
| 107 | 107 | echo "--merge-objs=$MergeObjsCmd" >> acargs
|
| 108 | 108 | echo "--readelf=$READELF" >> acargs
|
| 109 | 109 | echo "--windres=$WindresCmd" >> acargs
|
| 110 | + echo "--llc=$LlcCmd" >> acargs
|
|
| 111 | + echo "--opt=$OptCmd" >> acargs
|
|
| 112 | + echo "--llvm-as=$LlvmAsCmd" >> acargs
|
|
| 110 | 113 | |
| 111 | 114 | if test -n "$USER_LD"; then
|
| 112 | 115 | echo "--ld=$USER_LD" >> acargs
|
| ... | ... | @@ -10,6 +10,38 @@ |
| 10 | 10 | # This toolchain will additionally be used to validate the one generated by
|
| 11 | 11 | # ghc-toolchain. See Note [ghc-toolchain consistency checking].
|
| 12 | 12 | |
| 13 | +# PREP_LIST
|
|
| 14 | +# ============
|
|
| 15 | +#
|
|
| 16 | +# Issue a substitution with ["list","of","args"] of [$1List] when $1 is a
|
|
| 17 | +# space-separated list of args
|
|
| 18 | +# i.e.
|
|
| 19 | +# "arg1 arg2 arg3"
|
|
| 20 | +# ==>
|
|
| 21 | +# ["arg1","arg2","arg3"]
|
|
| 22 | +#
|
|
| 23 | +# $1 = list variable to substitute
|
|
| 24 | +dnl In autoconf, '@<:@' stands for '[', and '@:>@' for ']'.
|
|
| 25 | +AC_DEFUN([PREP_LIST],[
|
|
| 26 | + # shell array
|
|
| 27 | + set -- $$1
|
|
| 28 | + $1List="@<:@"
|
|
| 29 | + if test "[$]#" -eq 0; then
|
|
| 30 | + # no arguments
|
|
| 31 | + true
|
|
| 32 | + else
|
|
| 33 | + $1List="${$1List}\"[$]1\""
|
|
| 34 | + shift # drop first elem
|
|
| 35 | + for arg in "[$]@"
|
|
| 36 | + do
|
|
| 37 | + $1List="${$1List},\"$arg\""
|
|
| 38 | + done
|
|
| 39 | + fi
|
|
| 40 | + $1List="${$1List}@:>@"
|
|
| 41 | + |
|
| 42 | + AC_SUBST([$1List])
|
|
| 43 | +])
|
|
| 44 | + |
|
| 13 | 45 | # PREP_MAYBE_SIMPLE_PROGRAM
|
| 14 | 46 | # =========================
|
| 15 | 47 | #
|
| ... | ... | @@ -27,6 +59,25 @@ AC_DEFUN([PREP_MAYBE_SIMPLE_PROGRAM],[ |
| 27 | 59 | AC_SUBST([$1MaybeProg])
|
| 28 | 60 | ])
|
| 29 | 61 | |
| 62 | +# PREP_MAYBE_PROGRAM
|
|
| 63 | +# =========================
|
|
| 64 | +#
|
|
| 65 | +# Introduce a substitution [$1MaybeProg] with
|
|
| 66 | +# * Nothing, if $$1 is empty
|
|
| 67 | +# * Just (Program {prgPath = "$$1", prgFlags = [elements of $$2]}), otherwise
|
|
| 68 | +#
|
|
| 69 | +# $1 = optional program path
|
|
| 70 | +# $2 = program arguments
|
|
| 71 | +AC_DEFUN([PREP_MAYBE_PROGRAM],[
|
|
| 72 | + if test -z "$$1"; then
|
|
| 73 | + $1MaybeProg=Nothing
|
|
| 74 | + else
|
|
| 75 | + PREP_LIST([$2])
|
|
| 76 | + $1MaybeProg="Just (Program {prgPath = \"$$1\", prgFlags = $$2List})"
|
|
| 77 | + fi
|
|
| 78 | + AC_SUBST([$1MaybeProg])
|
|
| 79 | +])
|
|
| 80 | + |
|
| 30 | 81 | # PREP_MAYBE_STRING
|
| 31 | 82 | # =========================
|
| 32 | 83 | #
|
| ... | ... | @@ -86,38 +137,6 @@ AC_DEFUN([PREP_NOT_BOOLEAN],[ |
| 86 | 137 | AC_SUBST([Not$1Bool])
|
| 87 | 138 | ])
|
| 88 | 139 | |
| 89 | -# PREP_LIST
|
|
| 90 | -# ============
|
|
| 91 | -#
|
|
| 92 | -# Issue a substitution with ["list","of","args"] of [$1List] when $1 is a
|
|
| 93 | -# space-separated list of args
|
|
| 94 | -# i.e.
|
|
| 95 | -# "arg1 arg2 arg3"
|
|
| 96 | -# ==>
|
|
| 97 | -# ["arg1","arg2","arg3"]
|
|
| 98 | -#
|
|
| 99 | -# $1 = list variable to substitute
|
|
| 100 | -dnl In autoconf, '@<:@' stands for '[', and '@:>@' for ']'.
|
|
| 101 | -AC_DEFUN([PREP_LIST],[
|
|
| 102 | - # shell array
|
|
| 103 | - set -- $$1
|
|
| 104 | - $1List="@<:@"
|
|
| 105 | - if test "[$]#" -eq 0; then
|
|
| 106 | - # no arguments
|
|
| 107 | - true
|
|
| 108 | - else
|
|
| 109 | - $1List="${$1List}\"[$]1\""
|
|
| 110 | - shift # drop first elem
|
|
| 111 | - for arg in "[$]@"
|
|
| 112 | - do
|
|
| 113 | - $1List="${$1List},\"$arg\""
|
|
| 114 | - done
|
|
| 115 | - fi
|
|
| 116 | - $1List="${$1List}@:>@"
|
|
| 117 | - |
|
| 118 | - AC_SUBST([$1List])
|
|
| 119 | -])
|
|
| 120 | - |
|
| 121 | 140 | # Eventually: PREP_BUILD_TARGET_FILE, PREP_HOST_TARGET_FILE, PREP_TARGET_TARGET_FILE
|
| 122 | 141 | # Prepares required substitutions to generate the target file
|
| 123 | 142 | AC_DEFUN([PREP_TARGET_FILE],[
|
| ... | ... | @@ -148,7 +167,12 @@ AC_DEFUN([PREP_TARGET_FILE],[ |
| 148 | 167 | PREP_LIST([JavaScriptCPPArgs])
|
| 149 | 168 | PREP_LIST([CmmCPPArgs])
|
| 150 | 169 | PREP_LIST([CmmCPPArgs_STAGE0])
|
| 170 | + PREP_MAYBE_SIMPLE_PROGRAM([LlcCmd])
|
|
| 171 | + PREP_MAYBE_SIMPLE_PROGRAM([OptCmd])
|
|
| 172 | + PREP_MAYBE_PROGRAM([LlvmAsCmd], [LlvmAsFlags])
|
|
| 151 | 173 | PREP_MAYBE_SIMPLE_PROGRAM([WindresCmd])
|
| 174 | + PREP_MAYBE_SIMPLE_PROGRAM([OtoolCmd])
|
|
| 175 | + PREP_MAYBE_SIMPLE_PROGRAM([InstallNameToolCmd])
|
|
| 152 | 176 | PREP_MAYBE_STRING([TargetVendor_CPP])
|
| 153 | 177 | PREP_MAYBE_STRING([HostVendor_CPP])
|
| 154 | 178 | PREP_LIST([CONF_CPP_OPTS_STAGE2])
|
| ... | ... | @@ -33,6 +33,7 @@ |
| 33 | 33 | |
| 34 | 34 | #define DEBUG_LOG(...) IF_DEBUG(linker, debugBelch("loadArchive: " __VA_ARGS__))
|
| 35 | 35 | |
| 36 | + |
|
| 36 | 37 | #if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
|
| 37 | 38 | /* Read 4 bytes and convert to host byte order */
|
| 38 | 39 | static uint32_t read4Bytes(const char buf[static 4])
|
| ... | ... | @@ -40,7 +41,7 @@ static uint32_t read4Bytes(const char buf[static 4]) |
| 40 | 41 | return ntohl(*(uint32_t*)buf);
|
| 41 | 42 | }
|
| 42 | 43 | |
| 43 | -static StgBool loadFatArchive(char tmp[static 20], FILE* f, pathchar* path)
|
|
| 44 | +static bool loadFatArchive(char input[static 20], FILE* f, pathchar* path)
|
|
| 44 | 45 | {
|
| 45 | 46 | uint32_t nfat_arch, nfat_offset, cputype, cpusubtype;
|
| 46 | 47 | #if defined(i386_HOST_ARCH)
|
| ... | ... | @@ -58,8 +59,9 @@ static StgBool loadFatArchive(char tmp[static 20], FILE* f, pathchar* path) |
| 58 | 59 | #error Unknown Darwin architecture
|
| 59 | 60 | #endif
|
| 60 | 61 | |
| 61 | - nfat_arch = read4Bytes(tmp + 4);
|
|
| 62 | + nfat_arch = read4Bytes(input + 4);
|
|
| 62 | 63 | DEBUG_LOG("found a fat archive containing %d architectures\n", nfat_arch);
|
| 64 | + char tmp[20];
|
|
| 63 | 65 | nfat_offset = 0;
|
| 64 | 66 | for (uint32_t i = 0; i < nfat_arch; i++) {
|
| 65 | 67 | /* search for the right arch */
|
| ... | ... | @@ -90,6 +92,7 @@ static StgBool loadFatArchive(char tmp[static 20], FILE* f, pathchar* path) |
| 90 | 92 | }
|
| 91 | 93 | |
| 92 | 94 | /* Read the header */
|
| 95 | + char tmp[20];
|
|
| 93 | 96 | n = fread(tmp, 1, 8, f);
|
| 94 | 97 | if (n != 8) {
|
| 95 | 98 | errorBelch("Failed reading header from `%" PATH_FMT "'", path);
|
| ... | ... | @@ -107,10 +110,51 @@ static StgBool loadFatArchive(char tmp[static 20], FILE* f, pathchar* path) |
| 107 | 110 | }
|
| 108 | 111 | #endif
|
| 109 | 112 | |
| 110 | -static StgBool readThinArchiveMember(int n, int memberSize, pathchar* path,
|
|
| 113 | +enum ObjectFileFormat {
|
|
| 114 | + NotObject,
|
|
| 115 | + COFFAmd64,
|
|
| 116 | + COFFI386,
|
|
| 117 | + COFFAArch64,
|
|
| 118 | + ELF,
|
|
| 119 | + MachO32,
|
|
| 120 | + MachO64,
|
|
| 121 | +};
|
|
| 122 | + |
|
| 123 | +static enum ObjectFileFormat identifyObjectFile_(char* buf, size_t sz)
|
|
| 124 | +{
|
|
| 125 | + if (sz > 2 && ((uint16_t*)buf)[0] == 0x8664) {
|
|
| 126 | + return COFFAmd64;
|
|
| 127 | + }
|
|
| 128 | + if (sz > 2 && ((uint16_t*)buf)[0] == 0x014c) {
|
|
| 129 | + return COFFI386;
|
|
| 130 | + }
|
|
| 131 | + if (sz > 2 && ((uint16_t*)buf)[0] == 0xaa64) {
|
|
| 132 | + return COFFAArch64;
|
|
| 133 | + }
|
|
| 134 | + if (sz > 4 && memcmp(buf, "\x7f" "ELF", 4) == 0) {
|
|
| 135 | + return ELF;
|
|
| 136 | + }
|
|
| 137 | + if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedface) {
|
|
| 138 | + return MachO32;
|
|
| 139 | + }
|
|
| 140 | + if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedfacf) {
|
|
| 141 | + return MachO64;
|
|
| 142 | + }
|
|
| 143 | + return NotObject;
|
|
| 144 | +}
|
|
| 145 | + |
|
| 146 | +static enum ObjectFileFormat identifyObjectFile(FILE *f)
|
|
| 147 | +{
|
|
| 148 | + char buf[32];
|
|
| 149 | + ssize_t sz = fread(buf, 1, 32, f);
|
|
| 150 | + CHECK(fseek(f, -sz, SEEK_CUR) == 0);
|
|
| 151 | + return identifyObjectFile_(buf, sz);
|
|
| 152 | +}
|
|
| 153 | + |
|
| 154 | +static bool readThinArchiveMember(int n, int memberSize, pathchar* path,
|
|
| 111 | 155 | char* fileName, char* image)
|
| 112 | 156 | {
|
| 113 | - StgBool has_succeeded = false;
|
|
| 157 | + bool has_succeeded = false;
|
|
| 114 | 158 | FILE* member = NULL;
|
| 115 | 159 | pathchar *pathCopy, *dirName, *memberPath, *objFileName;
|
| 116 | 160 | memberPath = NULL;
|
| ... | ... | @@ -148,10 +192,9 @@ inner_fail: |
| 148 | 192 | return has_succeeded;
|
| 149 | 193 | }
|
| 150 | 194 | |
| 151 | -static StgBool checkFatArchive(char magic[static 20], FILE* f, pathchar* path)
|
|
| 195 | +static bool checkFatArchive(char magic[static 4], FILE* f, pathchar* path)
|
|
| 152 | 196 | {
|
| 153 | - StgBool success;
|
|
| 154 | - success = false;
|
|
| 197 | + bool success = false;
|
|
| 155 | 198 | #if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
|
| 156 | 199 | /* Not a standard archive, look for a fat archive magic number: */
|
| 157 | 200 | if (read4Bytes(magic) == FAT_MAGIC)
|
| ... | ... | @@ -175,7 +218,7 @@ static StgBool checkFatArchive(char magic[static 20], FILE* f, pathchar* path) |
| 175 | 218 | * be reallocated on return; the old value is now _invalid_.
|
| 176 | 219 | * @param gnuFileIndexSize The size of the index.
|
| 177 | 220 | */
|
| 178 | -static StgBool
|
|
| 221 | +static bool
|
|
| 179 | 222 | lookupGNUArchiveIndex(int gnuFileIndexSize, char **fileName_,
|
| 180 | 223 | char* gnuFileIndex, pathchar* path, size_t* thisFileNameSize,
|
| 181 | 224 | size_t* fileNameSize)
|
| ... | ... | @@ -241,47 +284,21 @@ lookupGNUArchiveIndex(int gnuFileIndexSize, char **fileName_, |
| 241 | 284 | return true;
|
| 242 | 285 | }
|
| 243 | 286 | |
| 244 | -HsInt loadArchive_ (pathchar *path)
|
|
| 245 | -{
|
|
| 246 | - char *image = NULL;
|
|
| 247 | - HsInt retcode = 0;
|
|
| 248 | - int memberSize;
|
|
| 249 | - int memberIdx = 0;
|
|
| 250 | - FILE *f = NULL;
|
|
| 251 | - int n;
|
|
| 252 | - size_t thisFileNameSize = (size_t)-1; /* shut up bogus GCC warning */
|
|
| 253 | - char *fileName;
|
|
| 254 | - size_t fileNameSize;
|
|
| 255 | - int isObject, isGnuIndex, isThin, isImportLib;
|
|
| 256 | - char tmp[20];
|
|
| 257 | - char *gnuFileIndex;
|
|
| 258 | - int gnuFileIndexSize;
|
|
| 259 | - int misalignment = 0;
|
|
| 260 | - |
|
| 261 | - DEBUG_LOG("start\n");
|
|
| 262 | - DEBUG_LOG("Loading archive `%" PATH_FMT "'\n", path);
|
|
| 287 | +enum ArchiveFormat {
|
|
| 288 | + StandardArchive,
|
|
| 289 | + ThinArchive,
|
|
| 290 | + FatArchive,
|
|
| 291 | +};
|
|
| 263 | 292 | |
| 264 | - /* Check that we haven't already loaded this archive.
|
|
| 265 | - Ignore requests to load multiple times */
|
|
| 266 | - if (isAlreadyLoaded(path)) {
|
|
| 267 | - IF_DEBUG(linker,
|
|
| 268 | - debugBelch("ignoring repeated load of %" PATH_FMT "\n", path));
|
|
| 269 | - return 1; /* success */
|
|
| 293 | +static bool identifyArchiveFormat(FILE *f, pathchar *path, enum ArchiveFormat *out)
|
|
| 294 | +{
|
|
| 295 | + char tmp[8];
|
|
| 296 | + size_t n = fread(tmp, 1, 8, f);
|
|
| 297 | + if (n != 8) {
|
|
| 298 | + errorBelch("loadArchive: Failed reading header from `%" PATH_FMT "'", path); \
|
|
| 299 | + return false;
|
|
| 270 | 300 | }
|
| 271 | 301 | |
| 272 | - gnuFileIndex = NULL;
|
|
| 273 | - gnuFileIndexSize = 0;
|
|
| 274 | - |
|
| 275 | - fileNameSize = 32;
|
|
| 276 | - fileName = stgMallocBytes(fileNameSize, "loadArchive(fileName)");
|
|
| 277 | - |
|
| 278 | - isThin = 0;
|
|
| 279 | - isImportLib = 0;
|
|
| 280 | - |
|
| 281 | - f = pathopen(path, WSTR("rb"));
|
|
| 282 | - if (!f)
|
|
| 283 | - FAIL("loadObj: can't read `%" PATH_FMT "'", path);
|
|
| 284 | - |
|
| 285 | 302 | /* Check if this is an archive by looking for the magic "!<arch>\n"
|
| 286 | 303 | * string. Usually, if this fails, we belch an error and return. On
|
| 287 | 304 | * Darwin however, we may have a fat archive, which contains archives for
|
| ... | ... | @@ -300,12 +317,10 @@ HsInt loadArchive_ (pathchar *path) |
| 300 | 317 | * its magic "!<arch>\n" string and continue processing just as if
|
| 301 | 318 | * we had a single architecture archive.
|
| 302 | 319 | */
|
| 303 | - |
|
| 304 | - n = fread ( tmp, 1, 8, f );
|
|
| 305 | - if (n != 8) {
|
|
| 306 | - FAIL("Failed reading header from `%" PATH_FMT "'", path);
|
|
| 320 | + if (strncmp(tmp, "!<arch>\n", 8) == 0) {
|
|
| 321 | + *out = StandardArchive;
|
|
| 322 | + return true;
|
|
| 307 | 323 | }
|
| 308 | - if (strncmp(tmp, "!<arch>\n", 8) == 0) {}
|
|
| 309 | 324 | /* Check if this is a thin archive by looking for the magic string "!<thin>\n"
|
| 310 | 325 | *
|
| 311 | 326 | * ar thin libraries have the exact same format as normal archives except they
|
| ... | ... | @@ -322,16 +337,59 @@ HsInt loadArchive_ (pathchar *path) |
| 322 | 337 | *
|
| 323 | 338 | */
|
| 324 | 339 | else if (strncmp(tmp, "!<thin>\n", 8) == 0) {
|
| 325 | - isThin = 1;
|
|
| 340 | + *out = ThinArchive;
|
|
| 341 | + return true;
|
|
| 326 | 342 | }
|
| 327 | 343 | else {
|
| 328 | - StgBool success = checkFatArchive(tmp, f, path);
|
|
| 329 | - if (!success)
|
|
| 330 | - goto fail;
|
|
| 344 | + bool success = checkFatArchive(tmp, f, path);
|
|
| 345 | + if (!success) {
|
|
| 346 | + return false;
|
|
| 347 | + }
|
|
| 348 | + *out = FatArchive;
|
|
| 349 | + return true;
|
|
| 331 | 350 | }
|
| 351 | +}
|
|
| 352 | + |
|
| 353 | +HsInt loadArchive_ (pathchar *path)
|
|
| 354 | +{
|
|
| 355 | + char *image = NULL;
|
|
| 356 | + HsInt retcode = 0;
|
|
| 357 | + int memberIdx = 0;
|
|
| 358 | + FILE *f = NULL;
|
|
| 359 | + size_t thisFileNameSize = (size_t) -1; /* shut up bogus GCC warning */
|
|
| 360 | + int misalignment = 0;
|
|
| 361 | + |
|
| 362 | + DEBUG_LOG("start\n");
|
|
| 363 | + DEBUG_LOG("Loading archive `%" PATH_FMT "'\n", path);
|
|
| 364 | + |
|
| 365 | + /* Check that we haven't already loaded this archive.
|
|
| 366 | + Ignore requests to load multiple times */
|
|
| 367 | + if (isAlreadyLoaded(path)) {
|
|
| 368 | + IF_DEBUG(linker,
|
|
| 369 | + debugBelch("ignoring repeated load of %" PATH_FMT "\n", path));
|
|
| 370 | + return 1; /* success */
|
|
| 371 | + }
|
|
| 372 | + |
|
| 373 | + char *gnuFileIndex = NULL;
|
|
| 374 | + int gnuFileIndexSize = 0;
|
|
| 375 | + |
|
| 376 | + size_t fileNameSize = 32;
|
|
| 377 | + char *fileName = stgMallocBytes(fileNameSize, "loadArchive(fileName)");
|
|
| 378 | + |
|
| 379 | + f = pathopen(path, WSTR("rb"));
|
|
| 380 | + if (!f)
|
|
| 381 | + FAIL("loadObj: can't read `%" PATH_FMT "'", path);
|
|
| 382 | + |
|
| 383 | + enum ArchiveFormat archive_fmt;
|
|
| 384 | + if (!identifyArchiveFormat(f, path, &archive_fmt)) {
|
|
| 385 | + FAIL("failed to identify archive format of %" PATH_FMT ".", path);
|
|
| 386 | + }
|
|
| 387 | + bool isThin = archive_fmt == ThinArchive;
|
|
| 388 | + |
|
| 332 | 389 | DEBUG_LOG("loading archive contents\n");
|
| 333 | 390 | |
| 334 | 391 | while (1) {
|
| 392 | + size_t n;
|
|
| 335 | 393 | DEBUG_LOG("reading at %ld\n", ftell(f));
|
| 336 | 394 | n = fread ( fileName, 1, 16, f );
|
| 337 | 395 | if (n != 16) {
|
| ... | ... | @@ -351,6 +409,7 @@ HsInt loadArchive_ (pathchar *path) |
| 351 | 409 | }
|
| 352 | 410 | #endif
|
| 353 | 411 | |
| 412 | + char tmp[32];
|
|
| 354 | 413 | n = fread ( tmp, 1, 12, f );
|
| 355 | 414 | if (n != 12)
|
| 356 | 415 | FAIL("Failed reading mod time from `%" PATH_FMT "'", path);
|
| ... | ... | @@ -369,9 +428,16 @@ HsInt loadArchive_ (pathchar *path) |
| 369 | 428 | tmp[10] = '\0';
|
| 370 | 429 | for (n = 0; isdigit(tmp[n]); n++);
|
| 371 | 430 | tmp[n] = '\0';
|
| 372 | - memberSize = atoi(tmp);
|
|
| 431 | + size_t memberSize;
|
|
| 432 | + {
|
|
| 433 | + char *end;
|
|
| 434 | + memberSize = strtol(tmp, &end, 10);
|
|
| 435 | + if (tmp == end) {
|
|
| 436 | + FAIL("Failed to decode member size");
|
|
| 437 | + }
|
|
| 438 | + }
|
|
| 373 | 439 | |
| 374 | - DEBUG_LOG("size of this archive member is %d\n", memberSize);
|
|
| 440 | + DEBUG_LOG("size of this archive member is %zd\n", memberSize);
|
|
| 375 | 441 | n = fread ( tmp, 1, 2, f );
|
| 376 | 442 | if (n != 2)
|
| 377 | 443 | FAIL("Failed reading magic from `%" PATH_FMT "'", path);
|
| ... | ... | @@ -379,7 +445,7 @@ HsInt loadArchive_ (pathchar *path) |
| 379 | 445 | FAIL("Failed reading magic from `%" PATH_FMT "' at %ld. Got %c%c",
|
| 380 | 446 | path, ftell(f), tmp[0], tmp[1]);
|
| 381 | 447 | |
| 382 | - isGnuIndex = 0;
|
|
| 448 | + bool isGnuIndex = false;
|
|
| 383 | 449 | /* Check for BSD-variant large filenames */
|
| 384 | 450 | if (0 == strncmp(fileName, "#1/", 3)) {
|
| 385 | 451 | size_t n = 0;
|
| ... | ... | @@ -419,7 +485,7 @@ HsInt loadArchive_ (pathchar *path) |
| 419 | 485 | else if (0 == strncmp(fileName, "//", 2)) {
|
| 420 | 486 | fileName[0] = '\0';
|
| 421 | 487 | thisFileNameSize = 0;
|
| 422 | - isGnuIndex = 1;
|
|
| 488 | + isGnuIndex = true;
|
|
| 423 | 489 | }
|
| 424 | 490 | /* Check for a file in the GNU file index */
|
| 425 | 491 | else if (fileName[0] == '/') {
|
| ... | ... | @@ -460,12 +526,8 @@ HsInt loadArchive_ (pathchar *path) |
| 460 | 526 | |
| 461 | 527 | DEBUG_LOG("Found member file `%s'\n", fileName);
|
| 462 | 528 | |
| 463 | - /* TODO: Stop relying on file extensions to determine input formats.
|
|
| 464 | - Instead try to match file headers. See #13103. */
|
|
| 465 | - isObject = (thisFileNameSize >= 2 && strncmp(fileName + thisFileNameSize - 2, ".o" , 2) == 0)
|
|
| 466 | - || (thisFileNameSize >= 3 && strncmp(fileName + thisFileNameSize - 3, ".lo" , 3) == 0)
|
|
| 467 | - || (thisFileNameSize >= 4 && strncmp(fileName + thisFileNameSize - 4, ".p_o", 4) == 0)
|
|
| 468 | - || (thisFileNameSize >= 4 && strncmp(fileName + thisFileNameSize - 4, ".obj", 4) == 0);
|
|
| 529 | + bool is_symbol_table = strcmp("", fileName) == 0;
|
|
| 530 | + enum ObjectFileFormat object_fmt = is_symbol_table ? NotObject : identifyObjectFile(f);
|
|
| 469 | 531 | |
| 470 | 532 | #if defined(OBJFORMAT_PEi386)
|
| 471 | 533 | /*
|
| ... | ... | @@ -479,15 +541,15 @@ HsInt loadArchive_ (pathchar *path) |
| 479 | 541 | *
|
| 480 | 542 | * Linker members (e.g. filename / are skipped since they are not needed)
|
| 481 | 543 | */
|
| 482 | - isImportLib = thisFileNameSize >= 4 && strncmp(fileName + thisFileNameSize - 4, ".dll", 4) == 0;
|
|
| 544 | + bool isImportLib = thisFileNameSize >= 4 && strncmp(fileName + thisFileNameSize - 4, ".dll", 4) == 0;
|
|
| 545 | +#else
|
|
| 546 | + bool isImportLib = false;
|
|
| 483 | 547 | #endif // windows
|
| 484 | 548 | |
| 485 | 549 | DEBUG_LOG("\tthisFileNameSize = %d\n", (int)thisFileNameSize);
|
| 486 | - DEBUG_LOG("\tisObject = %d\n", isObject);
|
|
| 487 | - |
|
| 488 | - if (isObject) {
|
|
| 489 | - pathchar *archiveMemberName;
|
|
| 550 | + DEBUG_LOG("\tisObject = %d\n", object_fmt);
|
|
| 490 | 551 | |
| 552 | + if ((!is_symbol_table && isThin) || object_fmt != NotObject) {
|
|
| 491 | 553 | DEBUG_LOG("Member is an object file...loading...\n");
|
| 492 | 554 | |
| 493 | 555 | #if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
|
| ... | ... | @@ -505,14 +567,13 @@ HsInt loadArchive_ (pathchar *path) |
| 505 | 567 | image = stgMallocBytes(memberSize, "loadArchive(image)");
|
| 506 | 568 | #endif
|
| 507 | 569 | if (isThin) {
|
| 508 | - if (!readThinArchiveMember(n, memberSize, path,
|
|
| 509 | - fileName, image)) {
|
|
| 570 | + if (!readThinArchiveMember(n, memberSize, path, fileName, image)) {
|
|
| 510 | 571 | goto fail;
|
| 511 | 572 | }
|
| 512 | 573 | }
|
| 513 | 574 | else
|
| 514 | 575 | {
|
| 515 | - n = fread ( image, 1, memberSize, f );
|
|
| 576 | + size_t n = fread ( image, 1, memberSize, f );
|
|
| 516 | 577 | if (n != memberSize) {
|
| 517 | 578 | FAIL("error whilst reading `%" PATH_FMT "'", path);
|
| 518 | 579 | }
|
| ... | ... | @@ -523,16 +584,18 @@ HsInt loadArchive_ (pathchar *path) |
| 523 | 584 | // I don't understand why this extra +1 is needed here; pathprintf
|
| 524 | 585 | // should have given us the correct length but in practice it seems
|
| 525 | 586 | // to be one byte short on Win32.
|
| 526 | - archiveMemberName = stgMallocBytes((size+1+1) * sizeof(pathchar), "loadArchive(file)");
|
|
| 587 | + pathchar *archiveMemberName = stgMallocBytes((size+1+1) * sizeof(pathchar), "loadArchive(file)");
|
|
| 527 | 588 | pathprintf(archiveMemberName, size+1, WSTR("%" PATH_FMT "(#%d:%.*s)"),
|
| 528 | 589 | path, memberIdx, (int)thisFileNameSize, fileName);
|
| 529 | 590 | |
| 530 | 591 | ObjectCode *oc = mkOc(STATIC_OBJECT, path, image, memberSize, false, archiveMemberName,
|
| 531 | 592 | misalignment);
|
| 532 | 593 | #if defined(OBJFORMAT_MACHO)
|
| 594 | + ASSERT(object_fmt == MachO32 || object_fmt == MachO64);
|
|
| 533 | 595 | ocInit_MachO( oc );
|
| 534 | 596 | #endif
|
| 535 | 597 | #if defined(OBJFORMAT_ELF)
|
| 598 | + ASSERT(object_fmt == ELF);
|
|
| 536 | 599 | ocInit_ELF( oc );
|
| 537 | 600 | #endif
|
| 538 | 601 | |
| ... | ... | @@ -577,7 +640,7 @@ while reading filename from `%" PATH_FMT "'", path); |
| 577 | 640 | "Skipping...\n");
|
| 578 | 641 | n = fseek(f, memberSize, SEEK_CUR);
|
| 579 | 642 | if (n != 0)
|
| 580 | - FAIL("error whilst seeking by %d in `%" PATH_FMT "'",
|
|
| 643 | + FAIL("error whilst seeking by %zd in `%" PATH_FMT "'",
|
|
| 581 | 644 | memberSize, path);
|
| 582 | 645 | }
|
| 583 | 646 | #endif
|
| ... | ... | @@ -588,7 +651,7 @@ while reading filename from `%" PATH_FMT "'", path); |
| 588 | 651 | if (!isThin || thisFileNameSize == 0) {
|
| 589 | 652 | n = fseek(f, memberSize, SEEK_CUR);
|
| 590 | 653 | if (n != 0)
|
| 591 | - FAIL("error whilst seeking by %d in `%" PATH_FMT "'",
|
|
| 654 | + FAIL("error whilst seeking by %zd in `%" PATH_FMT "'",
|
|
| 592 | 655 | memberSize, path);
|
| 593 | 656 | }
|
| 594 | 657 | }
|
| ... | ... | @@ -52,7 +52,12 @@ data Opts = Opts |
| 52 | 52 | , optNm :: ProgOpt
|
| 53 | 53 | , optReadelf :: ProgOpt
|
| 54 | 54 | , optMergeObjs :: ProgOpt
|
| 55 | + , optLlc :: ProgOpt
|
|
| 56 | + , optOpt :: ProgOpt
|
|
| 57 | + , optLlvmAs :: ProgOpt
|
|
| 55 | 58 | , optWindres :: ProgOpt
|
| 59 | + , optOtool :: ProgOpt
|
|
| 60 | + , optInstallNameTool :: ProgOpt
|
|
| 56 | 61 | -- Note we don't actually configure LD into anything but
|
| 57 | 62 | -- see #23857 and #22550 for the very unfortunate story.
|
| 58 | 63 | , optLd :: ProgOpt
|
| ... | ... | @@ -99,8 +104,13 @@ emptyOpts = Opts |
| 99 | 104 | , optNm = po0
|
| 100 | 105 | , optReadelf = po0
|
| 101 | 106 | , optMergeObjs = po0
|
| 107 | + , optLlc = po0
|
|
| 108 | + , optOpt = po0
|
|
| 109 | + , optLlvmAs = po0
|
|
| 102 | 110 | , optWindres = po0
|
| 103 | 111 | , optLd = po0
|
| 112 | + , optOtool = po0
|
|
| 113 | + , optInstallNameTool = po0
|
|
| 104 | 114 | , optUnregisterised = Nothing
|
| 105 | 115 | , optTablesNextToCode = Nothing
|
| 106 | 116 | , optUseLibFFIForAdjustors = Nothing
|
| ... | ... | @@ -112,7 +122,8 @@ emptyOpts = Opts |
| 112 | 122 | po0 = emptyProgOpt
|
| 113 | 123 | |
| 114 | 124 | _optCc, _optCxx, _optCpp, _optHsCpp, _optJsCpp, _optCmmCpp, _optCcLink, _optAr,
|
| 115 | - _optRanlib, _optNm, _optReadelf, _optMergeObjs, _optWindres, _optLd
|
|
| 125 | + _optRanlib, _optNm, _optReadelf, _optMergeObjs, _optLlc, _optOpt, _optLlvmAs,
|
|
| 126 | + _optWindres, _optLd, _optOtool, _optInstallNameTool
|
|
| 116 | 127 | :: Lens Opts ProgOpt
|
| 117 | 128 | _optCc = Lens optCc (\x o -> o {optCc=x})
|
| 118 | 129 | _optCxx = Lens optCxx (\x o -> o {optCxx=x})
|
| ... | ... | @@ -126,8 +137,13 @@ _optRanlib = Lens optRanlib (\x o -> o {optRanlib=x}) |
| 126 | 137 | _optNm = Lens optNm (\x o -> o {optNm=x})
|
| 127 | 138 | _optReadelf = Lens optReadelf (\x o -> o {optReadelf=x})
|
| 128 | 139 | _optMergeObjs = Lens optMergeObjs (\x o -> o {optMergeObjs=x})
|
| 140 | +_optLlc = Lens optLlc (\x o -> o {optLlc=x})
|
|
| 141 | +_optOpt = Lens optOpt (\x o -> o {optOpt=x})
|
|
| 142 | +_optLlvmAs = Lens optLlvmAs (\x o -> o {optLlvmAs=x})
|
|
| 129 | 143 | _optWindres = Lens optWindres (\x o -> o {optWindres=x})
|
| 130 | -_optLd = Lens optLd (\x o -> o {optLd= x})
|
|
| 144 | +_optLd = Lens optLd (\x o -> o {optLd=x})
|
|
| 145 | +_optOtool = Lens optOtool (\x o -> o {optOtool=x})
|
|
| 146 | +_optInstallNameTool = Lens optInstallNameTool (\x o -> o {optInstallNameTool=x})
|
|
| 131 | 147 | |
| 132 | 148 | _optTriple :: Lens Opts (Maybe String)
|
| 133 | 149 | _optTriple = Lens optTriple (\x o -> o {optTriple=x})
|
| ... | ... | @@ -183,8 +199,13 @@ options = |
| 183 | 199 | , progOpts "nm" "nm archiver" _optNm
|
| 184 | 200 | , progOpts "readelf" "readelf utility" _optReadelf
|
| 185 | 201 | , progOpts "merge-objs" "linker for merging objects" _optMergeObjs
|
| 202 | + , progOpts "llc" "LLVM llc utility" _optLlc
|
|
| 203 | + , progOpts "opt" "LLVM opt utility" _optOpt
|
|
| 204 | + , progOpts "llvm-as" "Assembler used for LLVM backend (typically clang)" _optLlvmAs
|
|
| 186 | 205 | , progOpts "windres" "windres utility" _optWindres
|
| 187 | 206 | , progOpts "ld" "linker" _optLd
|
| 207 | + , progOpts "otool" "otool utility" _optOtool
|
|
| 208 | + , progOpts "install-name-tool" "install-name-tool utility" _optInstallNameTool
|
|
| 188 | 209 | ]
|
| 189 | 210 | where
|
| 190 | 211 | progOpts :: String -> String -> Lens Opts ProgOpt -> [OptDescr (Opts -> Opts)]
|
| ... | ... | @@ -436,6 +457,11 @@ mkTarget opts = do |
| 436 | 457 | when (isNothing mergeObjs && not (arSupportsDashL ar)) $
|
| 437 | 458 | throwE "Neither a object-merging tool (e.g. ld -r) nor an ar that supports -L is available"
|
| 438 | 459 | |
| 460 | + -- LLVM toolchain
|
|
| 461 | + llc <- optional $ findProgram "llc" (optLlc opts) ["llc"]
|
|
| 462 | + opt <- optional $ findProgram "opt" (optOpt opts) ["opt"]
|
|
| 463 | + llvmAs <- optional $ findProgram "llvm assembler" (optLlvmAs opts) ["clang"]
|
|
| 464 | + |
|
| 439 | 465 | -- Windows-specific utilities
|
| 440 | 466 | windres <-
|
| 441 | 467 | case archOS_OS archOs of
|
| ... | ... | @@ -444,6 +470,15 @@ mkTarget opts = do |
| 444 | 470 | return (Just windres)
|
| 445 | 471 | _ -> return Nothing
|
| 446 | 472 | |
| 473 | + -- Darwin-specific utilities
|
|
| 474 | + (otool, installNameTool) <-
|
|
| 475 | + case archOS_OS archOs of
|
|
| 476 | + OSDarwin -> do
|
|
| 477 | + otool <- findProgram "otool" (optOtool opts) ["otool"]
|
|
| 478 | + installNameTool <- findProgram "install_name_tool" (optInstallNameTool opts) ["install_name_tool"]
|
|
| 479 | + return (Just otool, Just installNameTool)
|
|
| 480 | + _ -> return (Nothing, Nothing)
|
|
| 481 | + |
|
| 447 | 482 | -- various other properties of the platform
|
| 448 | 483 | tgtWordSize <- checkWordSize cc
|
| 449 | 484 | tgtEndianness <- checkEndianness cc
|
| ... | ... | @@ -480,7 +515,12 @@ mkTarget opts = do |
| 480 | 515 | , tgtRanlib = ranlib
|
| 481 | 516 | , tgtNm = nm
|
| 482 | 517 | , tgtMergeObjs = mergeObjs
|
| 518 | + , tgtLlc = llc
|
|
| 519 | + , tgtOpt = opt
|
|
| 520 | + , tgtLlvmAs = llvmAs
|
|
| 483 | 521 | , tgtWindres = windres
|
| 522 | + , tgtOtool = otool
|
|
| 523 | + , tgtInstallNameTool = installNameTool
|
|
| 484 | 524 | , tgtWordSize
|
| 485 | 525 | , tgtEndianness
|
| 486 | 526 | , tgtUnregisterised
|
| ... | ... | @@ -22,15 +22,6 @@ data WordSize = WS4 | WS8 |
| 22 | 22 | data Endianness = LittleEndian | BigEndian
|
| 23 | 23 | deriving (Show, Read, Eq, Ord)
|
| 24 | 24 | |
| 25 | --- TODO(#23674): Move the remaining relevant `settings-xxx` to Target:
|
|
| 26 | --- * llc command
|
|
| 27 | --- * opt command
|
|
| 28 | --- * install_name_tool
|
|
| 29 | --- * otool command
|
|
| 30 | ---
|
|
| 31 | --- Those are all things that are put into GHC's settings, and that might be
|
|
| 32 | --- different across targets
|
|
| 33 | - |
|
| 34 | 25 | -- | A 'Target' consists of:
|
| 35 | 26 | --
|
| 36 | 27 | -- * a target architecture and operating system
|
| ... | ... | @@ -72,8 +63,18 @@ data Target = Target |
| 72 | 63 | , tgtMergeObjs :: Maybe MergeObjs
|
| 73 | 64 | -- ^ We don't need a merge objects tool if we @Ar@ supports @-L@
|
| 74 | 65 | |
| 66 | + -- LLVM backend toolchain
|
|
| 67 | + , tgtLlc :: Maybe Program
|
|
| 68 | + , tgtOpt :: Maybe Program
|
|
| 69 | + , tgtLlvmAs :: Maybe Program
|
|
| 70 | + -- ^ assembler used to assemble LLVM backend output; typically @clang@
|
|
| 71 | + |
|
| 75 | 72 | -- Windows-specific tools
|
| 76 | 73 | , tgtWindres :: Maybe Program
|
| 74 | + |
|
| 75 | + -- Darwin-specific tools
|
|
| 76 | + , tgtOtool :: Maybe Program
|
|
| 77 | + , tgtInstallNameTool :: Maybe Program
|
|
| 77 | 78 | }
|
| 78 | 79 | deriving (Read, Eq, Ord)
|
| 79 | 80 | |
| ... | ... | @@ -121,6 +122,11 @@ instance Show Target where |
| 121 | 122 | , ", tgtRanlib = " ++ show tgtRanlib
|
| 122 | 123 | , ", tgtNm = " ++ show tgtNm
|
| 123 | 124 | , ", tgtMergeObjs = " ++ show tgtMergeObjs
|
| 125 | + , ", tgtLlc = " ++ show tgtLlc
|
|
| 126 | + , ", tgtOpt = " ++ show tgtOpt
|
|
| 127 | + , ", tgtLlvmAs = " ++ show tgtLlvmAs
|
|
| 124 | 128 | , ", tgtWindres = " ++ show tgtWindres
|
| 129 | + , ", tgtOtool = " ++ show tgtOtool
|
|
| 130 | + , ", tgtInstallNameTool = " ++ show tgtInstallNameTool
|
|
| 125 | 131 | , "}"
|
| 126 | 132 | ] |