[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 4 commits: Add code comments to allocator code
by Marge Bot (@marge-bot) 02 Jun '26
by Marge Bot (@marge-bot) 02 Jun '26
02 Jun '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
6b3044a0 by David Eichmann at 2026-05-30T11:58:48-04:00
Add code comments to allocator code
- - - - -
f4e04210 by Matthew Pickering at 2026-05-30T11:59:34-04:00
hadrian: Refactor system-cxx-std-lib rules
I noticed a few things wrong with the hadrian rules for
`system-cxx-std-lib` rules.
* For `text` there is an ad-hoc check to depend on `system-cxx-std-lib`
outside of `configurePackage`.
* The `system-cxx-std-lib` dependency is not read from cabal files.
* Recache is not called on the packge database after the `.conf` file is
generated, a more natural place for this rule is `registerRules`.
Treating this uniformly like other packages is complicated by it not
having any source code or a cabal file. However we can do a bit better
by reporting the dependency firstly in `PackageData` and then needing
the `.conf` file in the same place as every other package in
`configurePackage`.
This commit increases the `shakeVersion`, to provide backwards
compatibility to previous builds with different PackageData.
Fixes #25303
Co-authored-by: Sven Tennie <sven.tennie(a)gmail.com>
- - - - -
2224e4eb by Simon Jakobi at 2026-06-02T00:13:09-04:00
compiler: use nubOrd from containers
Address #27103 by replacing GHC.Utils.Misc.ordNub[On] with
Data.Containers.ListUtils.nubOrd[On].
Note that nubOrd suffers from a small inefficiency, a fix for which
will be included in the next containers release:
https://github.com/haskell/containers/issues/1202
- - - - -
13652abf by David Eichmann at 2026-06-02T00:13:10-04:00
Hadrian: disable response files for GHC/Haddock builders on non-Windows
This makes debugging build errors easier on non-windows hosts.
See issue #27230
- - - - -
20 changed files:
- + changelog.d/hadrian-system-cxx-std-lib-25303
- compiler/GHC/CmmToAsm/BlockLayout.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Linker/Unit.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Misc.hs
- ghc/GHCi/UI.hs
- hadrian/src/Builder.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Hadrian/Utilities.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Register.hs
- rts/sm/BlockAlloc.c
- rts/sm/MBlock.c
Changes:
=====================================
changelog.d/hadrian-system-cxx-std-lib-25303
=====================================
@@ -0,0 +1,22 @@
+section: packaging
+synopsis: Fix Hadrian rules for system-cxx-std-lib package dependency
+issues: #25303
+mrs: !16013
+description: {
+ Hadrian's handling of the `system-cxx-std-lib` virtual package has been
+ fixed and made more uniform.
+
+ Previously, `text` had an ad-hoc rule outside of `configurePackage` to
+ declare a dependency on `system-cxx-std-lib`, the dependency was not
+ discovered from cabal files, and the package database was not recached after
+ the `.conf` file was generated.
+
+ The dependency is now read from cabal files via a new
+ `dependsOnSystemCxxStdLib` field in `PackageData`, and the `.conf` file
+ is needed inside `configurePackage` alongside all other package
+ dependencies, consistent with how every other package is handled.
+
+ `shakeVersion` has been bumped to ensure existing build databases are
+ invalidated when upgrading, preventing binary deserialisation errors due to
+ the changed `PackageData` type.
+}
=====================================
compiler/GHC/CmmToAsm/BlockLayout.hs
=====================================
@@ -36,6 +36,7 @@ import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Misc
+import Data.Containers.ListUtils (nubOrd)
import Data.List (sortOn, sortBy, nub)
import Data.List.NonEmpty (nonEmpty)
import qualified Data.List.NonEmpty as NE
@@ -426,7 +427,7 @@ combineNeighbourhood edges chains
applyEdges :: [CfgEdge] -> FrontierMap -> FrontierMap -> Set.Set (BlockId, BlockId)
-> ([BlockChain], Set.Set (BlockId,BlockId))
applyEdges [] chainEnds _chainFronts combined =
- (ordNub $ map snd $ mapElems chainEnds, combined)
+ (nubOrd $ map snd $ mapElems chainEnds, combined)
applyEdges ((CfgEdge from to _w):edges) chainEnds chainFronts combined
| Just (c1_e,c1) <- mapLookup from chainEnds
, Just (c2_f,c2) <- mapLookup to chainFronts
=====================================
compiler/GHC/Driver/Backpack.hs
=====================================
@@ -76,6 +76,7 @@ import GHC.Data.FastString
import qualified GHC.Data.EnumSet as EnumSet
import qualified GHC.Data.ShortText as ST
+import Data.Containers.ListUtils (nubOrd)
import Data.List ( partition )
import System.Exit
import Control.Monad
@@ -763,14 +764,14 @@ hsunitModuleGraph do_link unit = do
let inodes = instantiationNodes (homeUnitId $ hsc_home_unit hsc_env) (hsc_units hsc_env)
-- TODO: Backpack mode does not properly support ExternalPackage nodes yet
-- Module nodes do not get given package dependencies (see hsModuleToModSummary).
- let pkg_nodes = ordNub $ map (\(_, iud) -> UnitNode [] (instUnitInstanceOf iud)) inodes
+ let pkg_nodes = nubOrd $ map (\(_, iud) -> UnitNode [] (instUnitInstanceOf iud)) inodes
let graph_nodes = nodes ++ req_nodes ++ (map (uncurry InstantiationNode) $ inodes) ++ pkg_nodes
key_nodes = map mkNodeKey graph_nodes
all_nodes = graph_nodes ++ [LinkNode key_nodes (homeUnitId $ hsc_home_unit hsc_env) | do_link]
-- This error message is not very good but .bkp mode is just for testing so
-- better to be direct rather than pretty.
when
- (length key_nodes /= length (ordNub key_nodes))
+ (length key_nodes /= length (nubOrd key_nodes))
(pprPanic "Duplicate nodes keys in backpack file" (ppr key_nodes))
-- 3. Return the kaboodle
=====================================
compiler/GHC/Driver/Session/Units.hs
=====================================
@@ -25,7 +25,6 @@ import qualified GHC.Unit.State as State
import GHC.Types.SrcLoc
import GHC.Types.SourceError
-import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Monad ( liftIO, mapMaybeM )
@@ -35,6 +34,7 @@ import System.IO
import System.Exit
import System.FilePath
import Control.Monad
+import Data.Containers.ListUtils (nubOrdOn)
import Data.List ( partition, (\\) )
import qualified Data.Set as Set
import GHC.Prelude
@@ -204,7 +204,7 @@ checkDuplicateUnits dflags flags =
where
uids = map (second homeUnitId_) flags
- deduplicated_uids = ordNubOn snd uids
+ deduplicated_uids = nubOrdOn snd uids
duplicate_ids = Set.fromList (map snd uids \\ map snd deduplicated_uids)
duplicate_flags = filter (flip Set.member duplicate_ids . snd) uids
=====================================
compiler/GHC/HsToCore/Usage.hs
=====================================
@@ -32,6 +32,7 @@ import GHC.Unit.Module.Deps
import GHC.Data.Maybe
import GHC.Data.FastString
+import Data.Containers.ListUtils (nubOrdOn)
import Data.List (sortBy)
import Data.Map (Map)
import qualified Data.Map as Map
@@ -180,7 +181,7 @@ the TH splice.
-- modules and direct object files for pkg dependencies
mkObjectUsage :: Plugins -> FinderCache -> [LinkableUsage] -> PkgsLoaded -> IO [Usage]
mkObjectUsage plugins fc th_links_needed th_pkgs_needed = do
- let ls = ordNubOn linkableModule (th_links_needed ++ plugins_links_needed)
+ let ls = nubOrdOn linkableModule (th_links_needed ++ plugins_links_needed)
ds = concatMap loaded_pkg_hs_objs $ eltsUDFM (plusUDFM th_pkgs_needed plugin_pkgs_needed) -- TODO possibly record loaded_pkg_non_hs_objs as well
(plugins_links_needed, plugin_pkgs_needed) = loadedPluginDeps plugins
concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds)
=====================================
compiler/GHC/Linker/Unit.hs
=====================================
@@ -25,6 +25,7 @@ import qualified GHC.Data.ShortText as ST
import GHC.Settings
import Control.Monad
+import Data.Containers.ListUtils (nubOrd)
import Data.List (nub)
import Data.Semigroup ( Semigroup(..) )
import System.Directory
@@ -95,7 +96,7 @@ collectArchives namever ways pc =
filterM doesFileExist [ searchPath </> ("lib" ++ lib ++ ".a")
| searchPath <- searchPaths
, lib <- libs ]
- where searchPaths = ordNub . filter notNull . libraryDirsForWay ways $ pc
+ where searchPaths = nubOrd . filter notNull . libraryDirsForWay ways $ pc
libs = unitHsLibs namever ways pc ++ (map ST.unpack . unitExtDepLibsStaticSys $ pc)
getLibs :: GhcNameVersion -> Ways -> UnitEnv -> [UnitId] -> IO [(String,String)]
=====================================
compiler/GHC/Rename/Pat.hs
=====================================
@@ -79,6 +79,7 @@ import GHC.Core.TyCon ( isKindName )
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad ( when, ap, guard, unless )
+import Data.Containers.ListUtils (nubOrdOn)
import Data.Foldable
import Data.Function ( on )
import Data.Functor.Identity ( Identity (..) )
@@ -667,7 +668,7 @@ rnPatAndThen mk (OrPat _ pats)
; pats' <- rnLPatsAndThen mk pats
; let bndrs = collectPatsBinders CollVarTyVarBinders (NE.toList pats')
; liftCps $ setSrcSpan loc $ checkErr (null bndrs) $
- TcRnOrPatBindsVariables (NE.fromList (ordNubOn getOccName bndrs))
+ TcRnOrPatBindsVariables (NE.fromList (nubOrdOn getOccName bndrs))
; return (OrPat noExtField pats') }
rnPatAndThen mk (SumPat _ pat alt arity)
=====================================
compiler/GHC/Unit/Info.hs
=====================================
@@ -49,6 +49,7 @@ import GHC.Unit.Database
import GHC.Settings
+import Data.Containers.ListUtils (nubOrd)
import Data.Version
import Data.Bifunctor
import Data.List (isPrefixOf, stripPrefix)
@@ -185,7 +186,7 @@ mkUnitPprInfo ufs i = UnitPprInfo
-- | Find all the include directories in the given units
collectIncludeDirs :: [UnitInfo] -> [FilePath]
-collectIncludeDirs ps = map ST.unpack $ ordNub (filter (not . ST.null) (concatMap unitIncludeDirs ps))
+collectIncludeDirs ps = map ST.unpack $ nubOrd (filter (not . ST.null) (concatMap unitIncludeDirs ps))
-- | Find all the C-compiler options in the given units
collectExtraCcOpts :: [UnitInfo] -> [String]
@@ -193,7 +194,7 @@ collectExtraCcOpts ps = map ST.unpack (concatMap unitCcOptions ps)
-- | Find all the library directories in the given units for the given ways
collectLibraryDirs :: Ways -> [UnitInfo] -> [FilePath]
-collectLibraryDirs ws = ordNub . filter notNull . concatMap (libraryDirsForWay ws)
+collectLibraryDirs ws = nubOrd . filter notNull . concatMap (libraryDirsForWay ws)
-- | Find all the frameworks in the given units
collectFrameworks :: [UnitInfo] -> [String]
@@ -201,7 +202,7 @@ collectFrameworks ps = map ST.unpack (concatMap unitExtDepFrameworks ps)
-- | Find all the package framework paths in these and the preload packages
collectFrameworksDirs :: [UnitInfo] -> [String]
-collectFrameworksDirs ps = map ST.unpack (ordNub (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps)))
+collectFrameworksDirs ps = map ST.unpack (nubOrd (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps)))
-- | Either the 'unitLibraryDirs' or 'unitLibraryDynDirs' as appropriate for the way.
libraryDirsForWay :: Ways -> UnitInfo -> [String]
=====================================
compiler/GHC/Unit/State.hs
=====================================
@@ -112,6 +112,7 @@ import GHC.Utils.Exception
import System.Directory
import System.FilePath as FilePath
import Control.Monad
+import Data.Containers.ListUtils (nubOrd)
import Data.Graph (stronglyConnComp, SCC(..))
import Data.Char ( toUpper )
import Data.List ( intersperse, partition, sortBy, sortOn, sort )
@@ -1705,7 +1706,7 @@ mkUnitState logger cfg = do
basicLinkedUnits = fmap (RealUnit . Definite)
$ filter (flip elemUniqMap pkg_db)
$ unitConfigAutoLink cfg
- preload3 = ordNub $ (basicLinkedUnits ++ preload1)
+ preload3 = nubOrd $ (basicLinkedUnits ++ preload1)
-- Close the preload packages with their dependencies
dep_preload <- mayThrowUnitErr
=====================================
compiler/GHC/Utils/Misc.hs
=====================================
@@ -59,7 +59,7 @@ module GHC.Utils.Misc (
replaceAt, dropTail, capitalise,
-- * Sorting
- sortWith, minWith, nubSort, ordNub, ordNubOn,
+ sortWith, minWith, nubSort,
-- * Comparisons
isEqual,
@@ -570,23 +570,6 @@ minWith get_key xs = assert (not (null xs) )
nubSort :: Ord a => [a] -> [a]
nubSort = Set.toAscList . Set.fromList
--- | Remove duplicates but keep elements in order.
--- O(n * log n)
-ordNub :: Ord a => [a] -> [a]
-ordNub xs = ordNubOn id xs
-
--- | Remove duplicates but keep elements in order.
--- O(n * log n)
-ordNubOn :: Ord b => (a -> b) -> [a] -> [a]
-ordNubOn f xs
- = go Set.empty xs
- where
- go _ [] = []
- go s (x:xs)
- | Set.member (f x) s = go s xs
- | otherwise = x : go (Set.insert (f x) s) xs
-
-
{-
************************************************************************
* *
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -128,6 +128,7 @@ import Control.Monad.Trans.Except
import Data.Array
import qualified Data.ByteString.Char8 as BS
import Data.Char
+import Data.Containers.ListUtils (nubOrd)
import Data.Function
import qualified Data.Foldable as Foldable
import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef )
@@ -786,7 +787,7 @@ installInteractiveHomeUnits dflags = do
-- This is mostly for a clear separation of concerns,
-- to indicate we only care about unit dependencies from package dbs.
& filter (not . selectHptFlag (HUG.allUnits $ hsc_HUG hsc_env))
- & ordNub
+ & nubOrd
else
packageFlags dflags0
@@ -871,7 +872,7 @@ installInteractiveHomeUnits dflags = do
prefix =
longestCommonPrefix stacks
in
- prefix ++ ordNub (concatMap (List.drop (length prefix)) stacks)
+ prefix ++ nubOrd (concatMap (List.drop (length prefix)) stacks)
reportError :: GhciMonad m => GhciCommandMessage -> m ()
reportError err = do
@@ -1249,7 +1250,7 @@ generatePromptFunctionFromString promptS modules_names line =
processString ('%':'s':xs) =
liftM2 (<>) (return modules_list) (processString xs)
where
- modules_list = hsep . map text . ordNub $ modules_names
+ modules_list = hsep . map text . nubOrd $ modules_names
processString ('%':'l':xs) =
liftM2 (<>) (return $ ppr line) (processString xs)
processString ('%':'d':xs) =
=====================================
hadrian/src/Builder.hs
=====================================
@@ -39,7 +39,6 @@ import Packages
import GHC.IO.Encoding (getFileSystemEncoding)
import qualified Data.ByteString as BS
import qualified GHC.Foreign as GHC
-import GHC.ResponseFile
import GHC.Toolchain (Target(..))
import qualified GHC.Toolchain as Toolchain
@@ -346,7 +345,15 @@ instance H.Builder Builder where
Haddock BuildPackage -> runHaddock path buildArgs buildInputs
- Ghc _ _ -> runGhcWithResponse path buildArgs buildInputs buildOptions
+ Ghc _ _ ->
+ -- Use a response file for ghc invocations to avoid issues with command line
+ -- size limit on Windows (#26637).
+ -- NB: we can't put the buildArgs in a response file, because some flags require
+ -- empty arguments (such as the -dep-suffix flag), but that isn't supported
+ -- yet due to #26560.
+ withResponseFileOnWindows
+ (\buildInputs' -> cmd [path] buildArgs buildInputs' buildOptions)
+ buildInputs
HsCpp -> captureStdout
@@ -380,29 +387,15 @@ instance H.Builder Builder where
_ -> cmd' [path] buildArgs buildOptions
--- | Invoke @haddock@ given a path to it and a list of arguments. The arguments
--- are passed in a response file.
+-- | Invoke @haddock@ given a path to it and a list of arguments. On Windows,
+-- the input file arguments are passed as a response file.
runHaddock :: FilePath -- ^ path to @haddock@
-> [String]
-> [FilePath] -- ^ input file paths
-> Action ()
-runHaddock haddockPath flagArgs fileInputs = withResponseFile $ \tmp -> do
- writeFile' tmp $ escapeArgs fileInputs
- cmd [haddockPath] flagArgs ('@' : tmp)
-
--- | Use a response file for ghc invocations to avoid issues with command line
--- size limit on Windows (#26637).
-runGhcWithResponse :: FilePath -- ^ Path to ghc
- -> [String] -- ^ Arguments passed on the command line
- -> [FilePath] -- ^ Input file paths (passed via response file)
- -> [CmdOption]
- -> Action ()
-runGhcWithResponse ghcPath buildArgs buildInputs buildOptions = withResponseFile $ \tmp -> do
- -- We can't put the buildArgs in a response file, because some flags require
- -- empty arguments (such as the -dep-suffix flag), but that isn't supported
- -- yet due to #26560.
- writeFile' tmp (escapeArgs buildInputs)
- cmd [ghcPath] buildArgs ('@' : tmp) buildOptions
+runHaddock haddockPath flagArgs fileInputs = withResponseFileOnWindows
+ (cmd [haddockPath] flagArgs)
+ fileInputs
-- TODO: Some builders are required only on certain platforms. For example,
-- 'Objdump' is only required on OpenBSD and AIX. Add support for platform
=====================================
hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
=====================================
@@ -81,10 +81,11 @@ parsePackageData pkg = do
sorted = sort [ C.unPackageName p | C.Dependency p _ _ <- allDeps ]
deps = nubOrd sorted \\ [name]
depPkgs = mapMaybe findPackageByName deps
+ cxxStdLib = elem "system-cxx-std-lib" deps
return $ PackageData name version
(C.fromShortText (C.synopsis pd))
(C.fromShortText (C.description pd))
- depPkgs gpd
+ depPkgs cxxStdLib gpd
where
-- Collect an overapproximation of dependencies by ignoring conditionals
collectDeps :: Maybe (C.CondTree v [C.Dependency] a) -> [C.Dependency]
@@ -138,7 +139,9 @@ configurePackage :: Context -> Action ()
configurePackage context@Context {..} = do
putProgressInfo $ "| Configure package " ++ quote (pkgName package)
gpd <- pkgGenericDescription package
- depPkgs <- packageDependencies <$> readPackageData package
+ pd <- readPackageData package
+ let depPkgs = packageDependencies pd
+ needSystemCxxStdLib = dependsOnSystemCxxStdLib pd
-- Stage packages are those we have in this stage.
stagePkgs <- stagePackages stage
@@ -157,7 +160,12 @@ configurePackage context@Context {..} = do
-- We'll need those packages in our package database.
deps <- sequence [ pkgConfFile (context { package = pkg, iplace = forceBaseAfterGhcInternal pkg })
| pkg <- depPkgs, pkg `elem` stagePkgs ]
- need $ extraPreConfigureDeps ++ deps
+ -- system-cxx-std-lib is magic.. it doesn't have a cabal file or source code, so we have
+ -- to treat it specially as `pkgConfFile` uses `readPackageData` to compute the version.
+ systemCxxStdLib <- sequence [ systemCxxStdLibConfPath (PackageDbLoc stage iplace) | needSystemCxxStdLib ]
+ need $ extraPreConfigureDeps
+ ++ deps
+ ++ systemCxxStdLib
-- Figure out what hooks we need.
let configureFile = replaceFileName (pkgCabalFile package) "configure"
=====================================
hadrian/src/Hadrian/Haskell/Cabal/Type.hs
=====================================
@@ -30,6 +30,7 @@ data PackageData = PackageData
, synopsis :: String
, description :: String
, packageDependencies :: [Package]
+ , dependsOnSystemCxxStdLib :: Bool
, genericPackageDescription :: GenericPackageDescription
} deriving (Eq, Generic, Show)
=====================================
hadrian/src/Hadrian/Utilities.hs
=====================================
@@ -14,7 +14,7 @@ module Hadrian.Utilities (
-- * Paths
BuildRoot (..), buildRoot, buildRootRules, isGeneratedSource,
- KeepResponseFiles (..), keepResponseFiles, withResponseFile,
+ KeepResponseFiles (..), keepResponseFiles, withResponseFile, withResponseFileOnWindows,
-- * File system operations
copyFile, copyFileUntracked, createFileLink, fixFile,
@@ -48,8 +48,11 @@ import Data.Typeable (TypeRep, typeOf)
import Development.Shake hiding (Normal)
import Development.Shake.Classes
import Development.Shake.FilePath
+import GHC.ResponseFile (escapeArgs)
import System.Environment (lookupEnv)
+import System.Info.Extra (isWindows)
import System.IO (hClose, openTempFile)
+import System.IO.Error (isPermissionError)
import qualified Data.ByteString as BS
import qualified Control.Exception.Base as IO
@@ -57,8 +60,7 @@ import qualified Data.HashMap.Strict as Map
import qualified System.Directory.Extra as IO
import qualified System.Info.Extra as IO
import qualified System.IO as IO
-import System.IO.Error (isPermissionError)
-import qualified System.FilePath.Posix as Posix
+import qualified System.FilePath.Posix as Posix
-- | Extract a value from a singleton list, or terminate with an error message
-- if the list does not contain exactly one value.
@@ -328,6 +330,21 @@ keepResponseFiles = do
KeepResponseFiles keep <- userSetting (KeepResponseFiles False)
return keep
+-- | Run an action either with command arguments direcly or by, on Windows,
+-- placing those arguments into a response file escaped with @GHC.ResponseFile.escapeArgs@.
+--
+-- With @--keep-response-files@, the file is left on disk (if used)
+withResponseFileOnWindows ::
+ ([String] -> Action a) -- ^ Action to perform given arguments (of the form @["\@reponseFilePath"]@ on Windows)
+ -> [String] -- ^ Command arguments
+ -> Action a
+withResponseFileOnWindows action commandArgs = do
+ if isWindows
+ then withResponseFile $ \tmp -> do
+ writeFile' tmp (escapeArgs commandArgs)
+ action ['@' : tmp]
+ else action commandArgs
+
-- | Run an action with a response file path.
--
-- With @--keep-response-files@, the file is left on disk.
=====================================
hadrian/src/Main.hs
=====================================
@@ -63,7 +63,13 @@ main = do
shakeColor <- shouldUseColor
let options :: ShakeOptions
options = shakeOptions
- { shakeChange = ChangeModtimeAndDigest
+ { -- Bump shakeVersion whenever a type stored in the Shake oracle
+ -- changes its Binary representation (e.g. fields added/removed
+ -- from PackageData or other oracle value types). This forces
+ -- Shake to wipe the stale database instead of crashing on
+ -- deserialisation.
+ shakeVersion = "2"
+ , shakeChange = ChangeModtimeAndDigest
, shakeFiles = buildRoot -/- Base.shakeFilesDir
, shakeProgress = Progress.hadrianProgress cwd
, shakeRebuild = rebuild
=====================================
hadrian/src/Rules/Generate.hs
=====================================
@@ -242,9 +242,6 @@ copyRules = do
prefix -/- "html/**" <~ return "utils/haddock/haddock-api/resources"
prefix -/- "latex/**" <~ return "utils/haddock/haddock-api/resources"
- forM_ [Inplace, Final] $ \iplace ->
- root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
- copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file
generateRules :: Rules ()
generateRules = do
=====================================
hadrian/src/Rules/Register.hs
=====================================
@@ -6,7 +6,6 @@ module Rules.Register (
import Base
import Context
-import Flavour
import Oracles.Setting
import Hadrian.BuildPath
import Hadrian.Expression
@@ -48,14 +47,6 @@ configurePackageRules = do
isGmp <- (== "gmp") <$> interpretInContext ctx getBignumBackend
when isGmp $
need [buildP -/- "include/ghc-gmp.h"]
- when (pkg == text) $ do
- simdutf <- textWithSIMDUTF <$> flavour
- when simdutf $ do
- -- This is required, otherwise you get Error: hadrian:
- -- Encountered missing or private dependencies:
- -- system-cxx-std-lib ==1.0
- cxxStdLib <- systemCxxStdLibConfPath $ PackageDbLoc stage Inplace
- need [cxxStdLib]
Cabal.configurePackage ctx
root -/- "**/autogen/cabal_macros.h" %> \out -> do
@@ -105,6 +96,12 @@ registerPackageRules rs stage iplace = do
target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
writeFileLines stamp []
+ -- Special rule for registering system-cxx-std-lib
+ root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
+ copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file
+ buildWithResources rs $
+ target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
+
-- Register a package.
root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- "*.conf" %> \conf -> do
historyDisable
=====================================
rts/sm/BlockAlloc.c
=====================================
@@ -549,6 +549,8 @@ allocGroupOnNode (uint32_t node, W_ n)
ln++;
}
+ // If no free blocks exist then allocate a new megablock and keep just a
+ // chunk of it.
if (ln == NUM_FREE_LISTS) {
#if 0 /* useful for debugging fragmentation */
if ((W_)mblocks_allocated * BLOCKS_PER_MBLOCK * BLOCK_SIZE_W
@@ -1020,6 +1022,9 @@ freeGroup(bdescr *p)
}
// coalesce backwards
+ // Note that p is not a megablock/megagroup, so there are still live blocks on
+ // this megablock. Hence we can't coalesce backwards past the first block
+ // descriptor of this megablock.
if (p != FIRST_BDESCR(MBLOCK_ROUND_DOWN(p)))
{
bdescr *prev;
=====================================
rts/sm/MBlock.c
=====================================
@@ -95,6 +95,10 @@ typedef struct free_list {
} free_list;
static free_list *free_list_head;
+
+// The address in `mblock_address_space` just after the highest MBlock. This
+// will be the address of the next new MBlock committed when the free list is
+// empty.
static W_ mblock_high_watermark;
/*
* it is quite important that these are in the same cache line as they
@@ -103,22 +107,47 @@ static W_ mblock_high_watermark;
*/
struct mblock_address_range mblock_address_space = { 0, 0, {} };
+// Search for the first committed MBlock at or after startingAt.
+//
+// start_iter [in/out]: The free_list or a subset of it. Must contain all
+// entries for MBlocks at or after startingAt. On return this is set to the
+// free_list entry just after the returned MBlock. If no MBlock was found, This
+// is set to NULL (the search will have reached the end of the free list).
+//
+// startingAt [in]: address from which to start searching. This must be to the
+// start of an MBlock.
+//
+// return: The address of the committed MBlock. NULL if no committed MBLock was
+// found.
+//
static void *getAllocatedMBlock(free_list **start_iter, W_ startingAt)
{
+ // We simultaneously traverse the free list and the mblock_address_space.
free_list *iter;
W_ p = startingAt;
for (iter = *start_iter; iter != NULL; iter = iter->next)
{
+ // The current free MBlock, `iter`, is past the current MBlock, `p`.
+ // This means that `p` is committed (if it was free, then we would have
+ // found it on the free list). Stop searching.
if (p < iter->address)
break;
+ // Note that if `p > iter->address`, then we don't bump `p`. This just
+ // means we are skipping entries in the free list that correspond to
+ // MBlocks before `startingAt`.
if (p == iter->address)
+ // Move to the next MBlock. The MBlock may be committed,
+ // uncommitted, or even past mblock_high_watermark.
p += iter->size;
}
+ // Output current free list entry.
*start_iter = iter;
+ // If we reached mblock_high_watermark, then we didn't find any committed
+ // MBlocks.
if (p >= mblock_high_watermark)
return NULL;
@@ -152,6 +181,11 @@ void * getNextMBlock(void **state STG_UNUSED, void *mblock)
return getAllocatedMBlock(casted_state, (W_)mblock + MBLOCK_SIZE);
}
+// Used to implement getCommittedMBlocks. Search the free list for n contiguous
+// free MBlocks, and commit those MBlocks, updating the free_list. Returns the
+// address of the start of those MBlocks. Returns NULL if no n contiguous
+// MBlocks were found in the free list. Unlike getFreshMBlocks, this doesn't
+// attempt to allocate new MBlocks past mblock_high_watermark.
static void *getReusableMBlocks(uint32_t n)
{
struct free_list *iter;
@@ -163,7 +197,10 @@ static void *getReusableMBlocks(uint32_t n)
if (iter->size < size)
continue;
+ // We've found a large enough group of MBlocks.
addr = (void*)iter->address;
+
+ // Update the free list.
iter->address += size;
iter->size -= size;
if (iter->size == 0) {
@@ -190,6 +227,9 @@ static void *getReusableMBlocks(uint32_t n)
return NULL;
}
+// Used to implement getCommittedMBlocks. Commit n new MBlocks starting at
+// mblock_high_watermark. May exit with an out of memory error if we've passed
+// mblock_address_space.end (this is unlikely).
static void *getFreshMBlocks(uint32_t n)
{
W_ size = MBLOCK_SIZE * (W_)n;
@@ -207,6 +247,8 @@ static void *getFreshMBlocks(uint32_t n)
return addr;
}
+// Commit n new MBlocks. Tries to reuse freed MBlocks, else commits new
+// MBlock(s) at mblock_high_watermark.
static void *getCommittedMBlocks(uint32_t n)
{
void *p;
@@ -220,6 +262,11 @@ static void *getCommittedMBlocks(uint32_t n)
return p;
}
+// Decommit n contiguous MBlocks starting at the given address.
+//
+// addr [in]: address of the start of the n MBlocks (in mblock_address_space).
+//
+// n [in]: number of contiguous MBlocks to decommit.
static void decommitMBlocks(char *addr, uint32_t n)
{
struct free_list *iter, *prev;
@@ -228,17 +275,24 @@ static void decommitMBlocks(char *addr, uint32_t n)
osDecommitMemory(addr, size);
+ // Update the free list.
prev = NULL;
for (iter = free_list_head; iter != NULL; iter = iter->next)
{
prev = iter;
+ // iter is still entirely behind and not contiguous with the MBlocks so
+ // continue traversing free_list.
if (iter->address + iter->size < address)
continue;
+ // The MBlocks are after and contiguous to iter. Simply modify the
+ // current entry to include n more MBlocks and possibly coalesce.
if (iter->address + iter->size == address) {
iter->size += size;
+ // If the current free_list entry now reaches mblock_high_watermark,
+ // remove the entry and decrement mblock_high_watermark.
if (address + size == mblock_high_watermark) {
mblock_high_watermark -= iter->size;
if (iter->prev) {
@@ -251,6 +305,8 @@ static void decommitMBlocks(char *addr, uint32_t n)
return;
}
+ // If the current free_list entry now reaches the next free_list
+ // entry, coalesce them.
if (iter->next &&
iter->next->address == iter->address + iter->size) {
struct free_list *next;
@@ -269,6 +325,8 @@ static void decommitMBlocks(char *addr, uint32_t n)
stgFree(next);
}
return;
+
+ // The MBlocks are before and contiguous to iter.
} else if (address + size == iter->address) {
iter->address = address;
iter->size += size;
@@ -280,6 +338,9 @@ static void decommitMBlocks(char *addr, uint32_t n)
ASSERT(iter->prev->address + iter->prev->size < iter->address);
}
return;
+
+ // The MBlocks are before and not contiguous to iter. Insert a new entry
+ // just before iter.
} else {
struct free_list *new_iter;
@@ -311,6 +372,7 @@ static void decommitMBlocks(char *addr, uint32_t n)
if (address + size == mblock_high_watermark) {
mblock_high_watermark -= size;
} else {
+ // Add a new entry to the end of the free list.
struct free_list *new_iter;
new_iter = stgMallocBytes(sizeof(struct free_list), "freeMBlocks");
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c80f15faa8059f87825f586b375208…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c80f15faa8059f87825f586b375208…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fix-26953] 28 commits: EPA: Fix exact printing namespace-specified wildcards
by recursion-ninja (@recursion-ninja) 02 Jun '26
by recursion-ninja (@recursion-ninja) 02 Jun '26
02 Jun '26
recursion-ninja pushed to branch wip/fix-26953 at Glasgow Haskell Compiler / GHC
Commits:
1f096790 by Alan Zimmerman at 2026-05-23T18:43:20-04:00
EPA: Fix exact printing namespace-specified wildcards
Ensures correct printing of imports of the form
import Data.Bool (data True(data ..))
import Data.Bool (data True(type ..))
Closes #27291
- - - - -
56ada7c0 by Mrjtjmn at 2026-05-23T18:44:19-04:00
Fix ambiguous syntax of BangPatterns in users guide
Update documentation for the BangPatterns extension to specify
how surrounding whitespace affects interpretation of `!`.
* Only when there is whitespace before `!` and no whitespace after,
it is recognized as a BangPattern.
* Other cases `⟨varid⟩!⟨varid⟩`, `⟨varid⟩ ! ⟨varid⟩`, `⟨varid⟩! ⟨varid⟩`
are treated as infix operators.
- - - - -
579aa0b7 by Simon Jakobi at 2026-05-25T16:31:26-04:00
Ensure that SetOps.{minusList,unionListsOrd} can be specialized
...by marking them INLINABLE. Haddock allocates 0.1–0.3% less as a
result.
This also removes some redundant constraints on unionListsOrd.
- - - - -
cccf45da by Cheng Shao at 2026-05-25T16:32:13-04:00
wasm: ensure post-linker output is synchronous ESM
This patch fixes wasm backend's post-linker output script to ensure
it's synchronous ESM and doesn't use top-level await, which doesn't
work in ServiceWorkers. Fixes #27257.
- - - - -
8db331a3 by Zubin Duggal at 2026-05-26T04:54:03-04:00
Update to semaphore-compat 2.0.0 using v2 of the protocol
On Linux and other POSIX platforms, GHC's -jsem jobserver client now
speaks v2 of the semaphore-compat protocol, which uses Unix domain
sockets in place of POSIX named semaphores. This avoids the libc-ABI
issues that affected the old implementation. Windows is unaffected
and continues to use the v1 protocol (Win32 named semaphores); its
reported protocol version remains v1.
When GHC receives a -jsem name whose protocol version it does not
support, it emits a -Wsemaphore-version-mismatch warning and falls
back to -j<N> rather than crashing. ghc --info exposes the supported
version in a new "Semaphore version" entry so cabal-install can detect
a mismatch before invoking GHC.
Users on a cabal-install that predates the v2 update will continue to
build successfully on Linux/POSIX, but will lose the cross-process
-jsem coordination and fall back to -j<N> per GHC invocation. Users
must upgrade to a cabal-install that supports protocol v2 to recover
full parallelism.
Also fix a leak in cleanupSem (#27253): cleanupSem used to snapshot
heldTokens and release them before killing the loop, while the loop's
in-flight acquire/release children could still be mutating it.
Cleanup now runs inside the loop's own exit handler, after draining
the active child via a new activeChild TVar, so the snapshot has no
concurrent mutator.
See also:
- GHC proposal amendment: https://github.com/ghc-proposals/ghc-proposals/pull/673
- cabal-install patch: https://github.com/haskell/cabal/pull/11628
- semaphore-compat MR: https://gitlab.haskell.org/ghc/semaphore-compat/-/merge_requests/8
Bump semaphore-compat submodule to 2.0.0
Fixes #25087 and #27253
- - - - -
17be4f1f by Alan Zimmerman at 2026-05-26T04:54:52-04:00
EPA: Record semicolons in HsModifier
Ensure the semi colons are captured in the ParsedSource for code like
%True;; %False;
instance C D
It makes HsModifier (and hence HsModifierOf) LocatedA, so the semi
colons can be recorded as [TrailingAnn]
Also rename pprHsModifiers to pprLHsModifiers to match.
Closes #27294
- - - - -
8f991755 by fendor at 2026-05-26T11:02:52-04:00
Revert prog003 acceptance
We thought the commit 286f1adff3e78d775ff325caff71d0cee25d710b fixed the
test, but due to changes to ghci, modules loaded during the GHCi
session, the test was actually no longer testing what it set out to do,
"fixing" the broken test.
As modules are added to the `interactive-session` home unit, the object code needs
to be compiled with `-this-unit-id interactive-session`, otherwise the
object code won't be used.
Once this has been fixed in the test, the test fails as expected again.
- - - - -
277a3687 by mangoiv at 2026-05-26T11:03:40-04:00
libraries/process: bump submodule to v1.6.29.0
This submodule bump resolves a segfault on macos 15.
Fixes #27144
- - - - -
6779bb0c by mangoiv at 2026-05-26T11:03:40-04:00
libraries/unix: in submodule, don't pick branch 2.7
The 2.7 branch is outdated and the module has been advanced far beyond
it anyway, so remove that line.
- - - - -
4a645683 by Simon Peyton Jones at 2026-05-27T21:41:59-04:00
Trim the continuation in mkDupableContWithDmds
When there are no remaining argument demands, it means the application
is bottoming. In this case, we can trim the continuation to avoid the
panic that was observed in #27261.
See Note [Trimming the continuation for bottoming functions] in
GHC.Core.Opt.Simplify.Iteration.
- - - - -
8ab506ff by Cheng Shao at 2026-05-27T21:42:47-04:00
ghci: fix module name string lifetime in hs_hpc_module invocation
This patch makes hpcAddModule pass a properly malloced module name
string to hs_hpc_module, instead of using useAsCString which causes
use-after-free of module name string. Fixes #27297.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
b0233814 by sheaf at 2026-05-27T21:43:31-04:00
Relax acceptance threshold for T10421
As seen in #27289, the 1% acceptance threshold for this text was
overly narrow, resulting in spurious test failures. This commit widens
the acceptance threshold to 2%. Fixes #27289.
- - - - -
63ce5770 by Luite Stegeman at 2026-05-28T12:23:35-04:00
Fixes for black holes
- suspend duplicate work for eager black holes
- detect eager black holes in checkBlockingQueues
- don't overwrite existing black holes even if they're not
in an eager blackhole frame
- don't deadlock on self when thunk is already blackholed
Fixes #26936
- - - - -
037a80dc by Tom McLaughlin at 2026-05-28T12:24:36-04:00
Event/Windows.hsc: rethrow exceptions in overlapped IO
This prevents the WinIO manager from swallowing exceptions in overlapped IO. It
was added to make WinIO support possible in the `network` library. See
https://gitlab.haskell.org/ghc/ghc/-/issues/27283.
We also bump __IO_MANAGER_WINIO__ to 2 so libraries can gate on this using CPP.
- - - - -
2d53bcdb by Wolfgang Jeltsch at 2026-05-28T12:25:21-04:00
Allow `downsweep` to use nodes of an existing module graph
To this end, `downsweep` has not been able to use the nodes of a module
graph obtained from a previous downsweeping round. In some GHC API
applications, downsweeping is performed somewhat incrementally and
therefore could profit from reusing such existing results. This
contribution makes this possible.
Resolves #27054.
Co-authored-by: Matthew Pickering <matthewtpickering(a)gmail.com>
- - - - -
f4fbb583 by Simon Jakobi at 2026-05-28T12:26:04-04:00
Add regression test for T11226
Closes #11226.
- - - - -
ed29a5e6 by Sven Tennie at 2026-05-28T17:30:36-04:00
Add optional config setting for LibDir (#19174)
Previously, the `libDir` was derived from `topDir`. This won't work for
inplace stage2 cross-compilers where binaries and libraries are in
different stage dirs (`_build/stage1/` for executables and
`_build/stage2` for libraries).
`LibDir` is set in the inplace `settings` files. For bindists, we
generate a new `settings` file with no `LibDir` entry. GHC then defaults
to use `topDir` as `libDir` again. This keeps the bindist relocatable.
If `LibDir` is a relative path, it is interpreted relatively to
`topDir`.
The global package db is part of the `lib/` folder. If we want to point
for inplace cross-compilers to the succeeding stage's folder, this is
done by setting `LibDir`. Thus, the global package db must be found
relative to `libDir`` (which may default to `topDir` or be set by
`LibDir`).
The complexity of settings becomes scary. So, add a test to ensure
`LibDir` works as expected.
- - - - -
8339cf8f by Sven Tennie at 2026-05-28T17:30:36-04:00
Add Haddock to FileSettings
Helping to understand the fields' meanings without deeper analyses.
- - - - -
4ce251e4 by Sylvain Henry at 2026-05-28T17:31:39-04:00
foundation test: skip signed minBound `quot` (-1) (#27222)
`minBound `quot` (-1)` for fixed-width signed integers is platform
dependent: the mathematical result -minBound is not representable in
the type. On x86, IDIV traps; LLVM's sdiv is undefined behaviour in
this case; on AArch64/RISC-V, SDIV wraps to minBound.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
b8ba7e61 by Simon Jakobi at 2026-05-28T17:32:23-04:00
Prevent dictionary-passing in checkTyEqRhs
...by pre-specializing it to TcM.
Previously, wherever checkTyEqRhs was used in other modules, the
Core showed dictionary passing ($fMonadIOEnv). The added SPECIALIZE
pragma prevents this.
- - - - -
d603477f by David Eichmann at 2026-05-29T13:17:12-04:00
Hadrian: create a ghc-internal .def file per ghc-internal dll
The .def file generated from rts/win32/libHSghc-internal.def.in contains
the name of the ghc-internal dll. The correct dll name differs based
on if the dll is inplace/final and if using the Dynamic way. Previously,
this was not accounted for and inconsistent dlls names where used. That
led to failure when loading dlls at runtime in experiments with windows
dynamic linking.
- - - - -
1fc21753 by Sylvain Henry at 2026-05-29T13:18:14-04:00
ghc-bignum: copy backend interface haddocks to Native backend (#27305)
The haddock comments documenting the BigNat backend interface (function
contracts, expected MutableWordArray# sizes, return-value semantics, etc.)
were attached to the FFI backend module. Copy them to the Native backend
so they remain in tree once the FFI backend is removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
717059df by Sylvain Henry at 2026-05-29T13:18:14-04:00
ghc-bignum: remove FFI backend (#27305)
The FFI backend of ghc-bignum (now part of ghc-internal) had no known
users and is easy to recreate by relinking ghc-internal with a custom
backend. Remove the backend module, the bignum-ffi cabal flag, and the
ffi option from Hadrian's --bignum selector. The backend interface
documentation now lives in the Native backend module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
4bb3b1d8 by Sylvain Henry at 2026-05-29T13:18:14-04:00
ghc-bignum: remove Check backend (#27305)
The Check backend of ghc-bignum (now part of ghc-internal) compared the
selected backend's output against the Native backend for validation.
It had no known users. Remove the backend module, the bignum-check
cabal flag, the bignumCheck Hadrian flavour field, and the check-
prefix in Hadrian's --bignum selector.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
6b3044a0 by David Eichmann at 2026-05-30T11:58:48-04:00
Add code comments to allocator code
- - - - -
f4e04210 by Matthew Pickering at 2026-05-30T11:59:34-04:00
hadrian: Refactor system-cxx-std-lib rules
I noticed a few things wrong with the hadrian rules for
`system-cxx-std-lib` rules.
* For `text` there is an ad-hoc check to depend on `system-cxx-std-lib`
outside of `configurePackage`.
* The `system-cxx-std-lib` dependency is not read from cabal files.
* Recache is not called on the packge database after the `.conf` file is
generated, a more natural place for this rule is `registerRules`.
Treating this uniformly like other packages is complicated by it not
having any source code or a cabal file. However we can do a bit better
by reporting the dependency firstly in `PackageData` and then needing
the `.conf` file in the same place as every other package in
`configurePackage`.
This commit increases the `shakeVersion`, to provide backwards
compatibility to previous builds with different PackageData.
Fixes #25303
Co-authored-by: Sven Tennie <sven.tennie(a)gmail.com>
- - - - -
26c4ba79 by Alan Zimmerman at 2026-06-01T21:40:07-04:00
EPA: Fix exact printing namespace-specified wildcards
Ensures correct printing of imports of the form
import Data.Bool (data True(data ..))
import Data.Bool (data True(type ..))
Closes #27291
- - - - -
54796507 by Recursion Ninja at 2026-06-01T21:40:07-04:00
Decoupling 'L.H.S' from 'GHC.Types.SourceText'
* Migrated 'IntegralLit' to 'L.H.S.Lit'.
* Migrated 'FractionalLit' to 'L.H.S.Lit'.
* Migrated 'StringLiteral' to 'L.H.S.Lit'.
* Added TTG extension points to the types above.
* Added nice export list to 'GHC.Hs.Lit'.
* Added 'rnOverLitVal' and 'tcOverLitVal' functions to 'GHC.Hs.Lit'.
* Added instance 'Anno (StringLiteral (GhcPass p)) = SrcSpanAnnN'
* Moved [Notes] about 'SourceText' from 'L.H.S.*' to 'GHC.*'.
* Removed all references to 'SourceText' from 'L.H.S'.
* Removed the trailing comma record field from 'StringLiteral'
* Renamed exported functions for nomenclature consistency.
* Deprecated the renamed functions
Resolves issue #26953
- - - - -
176 changed files:
- .gitmodules
- + changelog.d/T27261
- + changelog.d/bump-process
- + changelog.d/fix-blackhole-handling
- + changelog.d/hadrian-system-cxx-std-lib-25303
- + changelog.d/jobserver-leak-fix
- + changelog.d/libdir-setting
- + changelog.d/module-graph-reuse-in-downsweep
- + changelog.d/remove-bignum-check-backend
- + changelog.d/remove-bignum-ffi-backend
- + changelog.d/semaphore-v2
- + changelog.d/wasm-fix-serviceworker
- + changelog.d/windows-rethrow-overlapped-exception
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Data/List/SetOps.hs
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/Types.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/SysTools/Cpp.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/PkgQual.hs
- compiler/GHC/Types/SourceText.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Binds/InlinePragma.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/stolen_syntax.rst
- docs/users_guide/using-warnings.rst
- docs/users_guide/using.rst
- hadrian/README.md
- hadrian/doc/user-settings.md
- hadrian/src/CommandLine.hs
- hadrian/src/Flavour.hs
- hadrian/src/Flavour/Type.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Packages.hs
- libraries/ghc-bignum/ghc-bignum.cabal
- + libraries/ghc-boot/GHC/Data/ShortByteString.hs
- libraries/ghc-boot/GHC/Settings/Utils.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghc-internal/bignum-backend.rst
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Check.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/FFI.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Selected.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc
- libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Run.hs
- libraries/process
- libraries/semaphore-compat
- rts/Messages.c
- rts/ThreadPaused.c
- rts/Threads.c
- rts/Updates.h
- rts/include/rts/storage/ClosureMacros.h
- rts/sm/BlockAlloc.c
- rts/sm/MBlock.c
- rts/win32/libHSghc-internal.def.in
- testsuite/tests/MiniQuickCheck.hs
- testsuite/tests/diagnostic-codes/codes.stdout
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/A.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/B.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/C.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/D.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/X.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/Y.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/Z.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.stdout
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/downsweep/all.T
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- + testsuite/tests/ghc-api/settings/LibDir.hs
- + testsuite/tests/ghc-api/settings/LibDir.stdout
- + testsuite/tests/ghc-api/settings/all.T
- testsuite/tests/ghci/prog003/prog003.T
- testsuite/tests/ghci/prog003/prog003.script
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/perf/should_run/T11226.hs
- + testsuite/tests/perf/should_run/T11226.stdout
- testsuite/tests/perf/should_run/all.T
- testsuite/tests/printer/Makefile
- testsuite/tests/printer/PprModifiers.hs
- + testsuite/tests/printer/Test27291.hs
- testsuite/tests/printer/all.T
- + testsuite/tests/simplCore/should_compile/T27261.hs
- + testsuite/tests/simplCore/should_compile/T27261_aux.hs
- testsuite/tests/simplCore/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/LexParseRn.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- utils/jsffi/prelude.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/44d09eb3c82c34778d5d4982c1b0d4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/44d09eb3c82c34778d5d4982c1b0d4…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T25450-march-native] 10 commits: Add --print-enabled-cpu-features flag
by Simon Jakobi (@sjakobi2) 02 Jun '26
by Simon Jakobi (@sjakobi2) 02 Jun '26
02 Jun '26
Simon Jakobi pushed to branch wip/sjakobi/T25450-march-native at Glasgow Haskell Compiler / GHC
Commits:
d177606f by Simon Jakobi at 2026-06-01T22:51:53+02:00
Add --print-enabled-cpu-features flag
GHC now supports a new mode flag --print-enabled-cpu-features, which
prints a JSON object describing the CPU features currently enabled for
code generation, together with a set of -m... flags that reproduce the
effective feature set for the current target. Dynamic options such as
-mavx2 and -mbmi2 are respected.
$ ghc -mavx2 --print-enabled-cpu-features
{"tag":"enabled-cpu-features","version":1,"target":"x86_64-linux-gnu",
"features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],
"as_m_flags":["-mavx2"]}
The primary purpose of this flag is for testing the -march=native option
(#25450).
Assisted-by: Claude Opus 4.8 <noreply(a)anthropic.com>
- - - - -
4851f684 by Simon Jakobi at 2026-06-02T00:37:14+02:00
Initial PLAN.md for T25450
- - - - -
69bd97c5 by Simon Jakobi at 2026-06-02T00:37:14+02:00
Initial implementation sketch from Codex
- - - - -
58057a37 by Simon Jakobi at 2026-06-02T00:37:15+02:00
Update PLAN.md
- - - - -
2ebb98e7 by Simon Jakobi at 2026-06-02T00:37:15+02:00
Add AGENTS.md
- - - - -
dcf90d0a by Simon Jakobi at 2026-06-02T00:37:15+02:00
AGENTS.md: Add implementation playbook
- - - - -
fc53b0c8 by Simon Jakobi at 2026-06-02T00:37:15+02:00
Updates
- - - - -
d56edd5c by Simon Jakobi at 2026-06-02T00:37:15+02:00
Implement -march=native for x86/x86_64
Probe the host CPU at flag-parse time and enable the matching CPU-feature
DynFlags, so the effect applies to both the NCG and LLVM backends.
The flag handler only records a marker (DynFlags.marchNative) since handlers
are pure; the CPUID probe and feature application run in parseDynamicFlagsFull,
which is in IO. detectX86CpuFeatures is memoized via cachedX86CpuFeatures so
the probe runs once per process. Detected SSE/AVX and BMI levels are collapsed
to their maximum and folded into the existing feature DynFlags, so the features
are treated exactly like the corresponding -m... flags and reuse the existing
implication logic.
-march=native is additive: it enables host features in addition to any explicit
-m... flags, independent of order, and never disables a feature. It is rejected
for non-x86 targets and when cross-compiling (host arch /= target arch).
The effective feature set is observable via --print-enabled-cpu-features, which
the new driver tests use.
Part of #25450.
Co-Authored-By: Claude Opus 4.7 <noreply(a)anthropic.com>
- - - - -
7aa7eb43 by Simon Jakobi at 2026-06-02T00:48:27+02:00
Add -march=native superset/additive tests; refresh PLAN.md status
Add march_native_superset and march_native_additive driver tests and
update PLAN.md to reflect the completed implementation and resolved
open questions.
Co-Authored-By: Claude Opus 4.7 <noreply(a)anthropic.com>
- - - - -
10d359b2 by Simon Jakobi at 2026-06-02T01:26:06+02:00
Add NCG asm test that -march=native enables popcnt
Compile-and-grep test confirming that -march=native enables SSE4.2 on a
capable host, so popCount emits a popcnt instruction. Gated on the host
actually having SSE4.2 via have_cpu_feature.
Co-Authored-By: Claude Opus 4.7 <noreply(a)anthropic.com>
- - - - -
25 changed files:
- + PLAN.md
- + changelog.d/march-native
- + changelog.d/print-enabled-cpu-features
- + compiler/GHC/Driver/CpuFeatures.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Session.hs
- + compiler/cbits/cpu_features_x86.c
- compiler/ghc.cabal.in
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Lint.hs
- ghc/GHC/Driver/Session/Mode.hs
- ghc/Main.hs
- testsuite/tests/codeGen/should_gen_asm/all.T
- + testsuite/tests/codeGen/should_gen_asm/march-native-enables-popcnt.asm
- + testsuite/tests/codeGen/should_gen_asm/march-native-enables-popcnt.hs
- testsuite/tests/driver/all.T
- + testsuite/tests/driver/march_native.stdout
- + testsuite/tests/driver/march_native_additive.stdout
- + testsuite/tests/driver/march_native_unsupported_arch.stderr
- + testsuite/tests/driver/print_enabled_cpu_features.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_avx2.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_avx512.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_bmi2.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_fma.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_unknown_flag.stderr
Changes:
=====================================
PLAN.md
=====================================
@@ -0,0 +1,142 @@
+# Implement `-march=native` for x86/x86_64 Using `GHC.Driver.CpuFeatures`
+
+## Summary
+Add support for `-march=native` (x86/x86_64, native compiler only). The flag probes the
+host CPU at parse time via an in-process CPUID/XGETBV helper and enables the matching
+CPU-feature `DynFlags`, so the effect applies to both the NCG and LLVM backends.
+
+This branch is based on `wip/sjakobi/T25450-print-cpu`, which already provides
+`ghc --print-enabled-cpu-features` and the `enabledCpuFeatures` / `showEnabledCpuFeatures`
+machinery in `GHC.Driver.Session`. That print mode is the primary tool for verifying and
+testing `-march=native`: detection sets `DynFlags`, the print mode reports them.
+
+## Public Interface Changes
+1. New dynamic flag: `-march=native`.
+2. New users-guide docs entry under platform flags.
+3. Behavior constraints:
+ - Supported only for target `x86`/`x86_64`.
+ - Rejected for cross-compilation (host CPU is irrelevant to a different target).
+ - Additive: applied once after the whole flag fold, it enables host features
+ *in addition* to any explicit `-m...` flags (order-independent, never disables).
+
+## Module / Architecture Changes
+1. `compiler/cbits/cpu_features_x86.c` — in-process CPUID/XGETBV probe (done).
+2. `compiler/GHC/Driver/CpuFeatures.hs` — mask decoder + naming (done). Build wiring in
+ `compiler/ghc.cabal.in` (done).
+3. `compiler/GHC/Driver/DynFlags.hs` — add a marker field `marchNative :: Bool` (default
+ `False`).
+4. `compiler/GHC/Driver/Session.hs` — flag registration + the IO application step (see below).
+
+## Detailed Implementation
+
+### 1. Flag parsing — pure marker only
+- File: `compiler/GHC/Driver/Session.hs`, near the existing `-m...` flags (~line 1710).
+- `make_ord_flag defGhcFlag "march=native" (noArg (\d -> d { marchNative = True }))`.
+- IMPORTANT: flag handlers run in `DynP = EwM (CmdLineP DynFlags)`, which is **pure** — they
+ cannot run the CPUID probe. The handler only records the request via the marker field.
+- Flag-surface note: a literal `"march=native"` entry means `-march=<other>` falls through to
+ a generic "unrecognised flag" error. For v1 this is acceptable; document that only `native`
+ is supported. (Optionally parse the `=value` later to emit a targeted message.)
+
+### 2. Feature application — the IO step
+- File: `compiler/GHC/Driver/Session.hs`, inside `parseDynamicFlagsFull`.
+- `parseDynamicFlagsFull` is already `MonadIO` and already performs `liftIO` work between the
+ pure flag fold (`dflags1`) and `makeDynFlagsConsistent` (`dflags2`/`dflags3`). Insert the
+ application there: after `dflags1`, before `makeDynFlagsConsistent`.
+ - If `marchNative dflags1` is set:
+ - Validate target arch is `ArchX86`/`ArchX86_64`; otherwise hard error.
+ - Validate not cross-compiling; otherwise hard error. (See open question on detection.)
+ - `feats <- liftIO detectX86CpuFeatures` (cached — see §4).
+ - Apply `feats` to `DynFlags` via a dedicated mapping helper (see §3), producing `dflags1'`.
+ - `makeDynFlagsConsistent` then propagates feature implications — do not reimplement them.
+- This path is shared with `parseDynamicFilePragma`, so the same logic also covers
+ `{-# OPTIONS_GHC -march=native #-}`. Decide whether to permit that; if so, caching matters.
+
+### 3. Mapping detected features to `DynFlags`
+The detected list is granular (`SSE2, SSE3, …, AVX2, BMI1, BMI2, …`), but several `DynFlags`
+fields are single ordered levels, so the mapper must **collapse ladders to their maximum**:
+- SSE/AVX ladder → highest present → `sseAvxVersion :: Maybe SseAvxVersion`
+ (`DynFlags.hs:461`). The `is*Enabled` predicates (`DynFlags.hs:1621-1642`) already imply the
+ lower rungs, so only the max level needs to be set.
+- BMI1/BMI2 → highest present → `bmiVersion :: Maybe BmiVersion`.
+- `AVX512F` + per-extension features → the individual bools `avx512f`, `avx512bw`,
+ `avx512cd`, `avx512dq`, `avx512vl`.
+- `FMA` → `fma`; `GFNI` → `gfni`.
+- `SSE2` is the x86_64 baseline (determined by the platform, not a flag) — nothing to set.
+
+### 4. Probe caching
+CPUID results are constant for the lifetime of the process, but `parseDynamicFlagsFull` runs
+per command-line *and* per file pragma. Memoize the probe once (top-level CAF backed by
+`unsafePerformIO` with `{-# NOINLINE #-}`, or detect once and thread the result) so repeated
+`-march=native` uses don't re-probe.
+
+### 5. Diagnostics and errors
+- Unsupported arch: clear error that `-march=native` is x86/x86_64-only.
+- Cross mode: clear error that `-march=native` is unavailable for cross-compilation.
+- The probe is in-process and returns a `Word64`; there is no subprocess, command, or stderr
+ to report. The only anomaly is a probe returning `0` (or lacking SSE2 on x86_64, where it is
+ baseline) — treat that as an internal error with a short diagnostic. (The earlier
+ "failing command + brief stderr" wording referred to an abandoned toolchain-probe approach
+ and no longer applies.)
+
+### 6. Backend behavior
+- NCG and LLVM are both driven by the same CPU-feature `DynFlags`, so no backend wiring
+ changes are needed — populating the fields in §3 is sufficient.
+
+### 7. Verification via `--print-enabled-cpu-features`
+- The base branch already prints effective enabled features as single-line JSON:
+ `{"tag":"enabled-cpu-features","version":1,"target":<triple>,"features":[…],"as_m_flags":[…]}`
+ with conventional names (`SSE4.2`, `AVX2`, `BMI2`) in canonical order.
+- `-march=native` must update the same `DynFlags` fields this mode reads, so its effect is
+ observable through `ghc -march=native --print-enabled-cpu-features`.
+
+### 8. Documentation
+- File: `docs/users_guide/using.rst`, alongside the other `-m...` options.
+- Describe: host CPU detection, x86/x86_64 only, non-cross only, positional, equivalent to
+ enabling the matching `-m...` options automatically.
+- Add a `changelog.d/` entry (the base branch already adds `changelog.d/print-enabled-cpu-features`).
+
+## Tests and Scenarios
+Lead with `--print-enabled-cpu-features` for deterministic, host-independent assertions.
+
+1. **Baseline (deterministic):** on x86_64, `ghc -march=native --print-enabled-cpu-features`
+ always lists `SSE2` in `features`.
+2. **Superset:** `features(-march=native)` ⊇ `features()` (run the print mode with and without
+ the flag and compare). Avoids hard-coding host-specific feature sets.
+3. **Additive:** an explicit `-m...` combined with `-march=native` yields the union (the
+ explicit feature is still present regardless of flag order).
+4. **Arch / cross guards:** compile-fail test for a non-x86 target and/or a cross context,
+ asserting the §5 error messages.
+5. **Optional NCG end-to-end:** one host-gated asm-grep test under
+ `testsuite/tests/codeGen/should_gen_asm` showing `-march=native` enables an expected x86
+ instruction path. Keep it secondary to the print-mode tests; do not rely on it as the main
+ signal. (There is no longer a meaningful probe-failure compile-fail test, since the probe
+ has no external tool to break.)
+
+## Open Questions
+1. **Cross-compilation detection.** *Resolved.* The guard compares the target arch against the
+ build-host arch: `arch == hostPlatformArch` in `applyMarchNative` (`Session.hs:3831`). A
+ mismatch raises the cross-compilation error from §5.
+2. **File-pragma scope.** *Resolved (permitted).* `applyMarchNative` runs in the shared
+ `parseDynamicFlagsFull` (`Session.hs:913`), so `-march=native` also takes effect in
+ `{-# OPTIONS_GHC #-}`. Repeated probing is harmless because the probe is memoized
+ (`cachedX86CpuFeatures`, §4).
+
+## Status
+1. Done: CPUID/XGETBV probe in `compiler/cbits/cpu_features_x86.c`.
+2. Done: decoder + naming in `compiler/GHC/Driver/CpuFeatures.hs`.
+3. Done: cabal wiring in `compiler/ghc.cabal.in`.
+4. Done (base branch): `--print-enabled-cpu-features` + `enabledCpuFeatures` reporting.
+5. Done: `marchNative` marker field in `DynFlags` (`DynFlags.hs:473,765`); flag registration
+ in `Session.hs:1752`.
+6. Done: IO application step `applyMarchNative` in `parseDynamicFlagsFull`
+ (`Session.hs:3816`) — arch guard, cross guard, and the ladder mapping in
+ `applyX86CpuFeatures` (`Session.hs:3839`).
+7. Done: probe caching via `cachedX86CpuFeatures` (top-level CAF, `NOINLINE`,
+ `CpuFeatures.hs:89`).
+8. Done: docs (`docs/users_guide/using.rst:1857`) and changelog (`changelog.d/march-native`).
+9. Tests. In `testsuite/tests/driver`: baseline SSE2 (`march_native`, §1), arch guard
+ (`march_native_unsupported_arch`, §4), superset (`march_native_superset`, §2), and additive
+ (`march_native_additive`, §3). In `testsuite/tests/codeGen/should_gen_asm`: NCG asm-grep
+ (`march-native-enables-popcnt`, §5) — gated on the host having SSE4.2 via
+ `have_cpu_feature`, so it deterministically expects a `popcnt` instruction.
=====================================
changelog.d/march-native
=====================================
@@ -0,0 +1,11 @@
+section: compiler
+synopsis: Add -march=native flag
+issues: #25450
+
+description:
+ GHC now supports ``-march=native`` on x86 and x86_64. It probes the CPU of the
+ machine running GHC and enables all of the corresponding ``-m...`` CPU-feature
+ options automatically (such as ``-msse4.2``, ``-mavx2``, ``-mbmi2`` and
+ ``-mfma``), for both the native code generator and the LLVM backend. The
+ detected features are enabled in addition to any explicitly requested feature
+ flags. The flag is rejected for non-x86 targets and when cross-compiling.
=====================================
changelog.d/print-enabled-cpu-features
=====================================
@@ -0,0 +1,16 @@
+section: compiler
+synopsis: Add --print-enabled-cpu-features flag
+issues: #25450
+mrs: !16117
+
+description:
+ GHC now supports a new mode flag ``--print-enabled-cpu-features``, which
+ prints a JSON object describing the CPU features currently enabled for code
+ generation, together with a set of ``-m...`` flags that reproduce the
+ effective feature set for the current target.
+ Dynamic options such as ``-mavx2`` and ``-mbmi2`` are respected. ::
+
+ $ ghc -mavx2 --print-enabled-cpu-features
+ {"tag":"enabled-cpu-features","version":1,"target":"x86_64-linux-gnu",
+ "features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],
+ "as_m_flags":["-mavx2"]}
=====================================
compiler/GHC/Driver/CpuFeatures.hs
=====================================
@@ -0,0 +1,115 @@
+{-# LANGUAGE CPP #-}
+
+module GHC.Driver.CpuFeatures
+ ( X86CpuFeature(..)
+ , detectX86CpuFeatureMask
+ , detectX86CpuFeatures
+ , cachedX86CpuFeatures
+ , decodeX86CpuFeatureMask
+ , x86CpuFeatureConventionalName
+ ) where
+
+import GHC.Prelude
+
+import Data.Bits (testBit)
+import Data.Word (Word64)
+import System.IO.Unsafe (unsafePerformIO)
+
+-- | x86 CPU features understood by GHC's native CPU feature probe.
+--
+-- The constructor order and decode order below are canonicalized for stable
+-- debug output.
+data X86CpuFeature
+ = SSE2
+ | SSE3
+ | SSSE3
+ | SSE4_1
+ | SSE4_2
+ | AVX
+ | AVX2
+ | AVX512F
+ | AVX512BW
+ | AVX512CD
+ | AVX512DQ
+ | AVX512VL
+ | BMI1
+ | BMI2
+ | FMA
+ | GFNI
+ deriving (Eq, Ord, Show)
+
+-- | Human-readable names used in the JSON/debug output.
+x86CpuFeatureConventionalName :: X86CpuFeature -> String
+x86CpuFeatureConventionalName feat = case feat of
+ SSE2 -> "SSE2"
+ SSE3 -> "SSE3"
+ SSSE3 -> "SSSE3"
+ SSE4_1 -> "SSE4.1"
+ SSE4_2 -> "SSE4.2"
+ AVX -> "AVX"
+ AVX2 -> "AVX2"
+ AVX512F -> "AVX512F"
+ AVX512BW -> "AVX512BW"
+ AVX512CD -> "AVX512CD"
+ AVX512DQ -> "AVX512DQ"
+ AVX512VL -> "AVX512VL"
+ BMI1 -> "BMI1"
+ BMI2 -> "BMI2"
+ FMA -> "FMA"
+ GFNI -> "GFNI"
+
+-- | Decode the bitmask returned by 'ghc_detect_x86_cpu_features'.
+--
+-- NOTE: Bit positions must match the enum in @compiler/cbits/cpu_features_x86.c@.
+decodeX86CpuFeatureMask :: Word64 -> [X86CpuFeature]
+decodeX86CpuFeatureMask mask =
+ [ feat
+ | (bit_ix, feat) <- cpuFeatureBitLayout
+ , testBit mask bit_ix
+ ]
+
+-- | Low-level FFI access to the C probe.
+detectX86CpuFeatureMask :: IO Word64
+#if defined(javascript_HOST_ARCH)
+detectX86CpuFeatureMask = pure 0
+#else
+detectX86CpuFeatureMask = c_ghc_detect_x86_cpu_features
+#endif
+
+-- | Probe host x86 CPU features and decode them into an ordered feature list.
+detectX86CpuFeatures :: IO [X86CpuFeature]
+detectX86CpuFeatures = decodeX86CpuFeatureMask <$> detectX86CpuFeatureMask
+
+-- | The host's x86 CPU features, probed once and memoized.
+--
+-- CPUID results are constant for the lifetime of the process, so probing more
+-- than once (e.g. once per @-march=native@ in a command line or file pragma)
+-- is wasteful. This is referentially transparent despite the FFI call.
+cachedX86CpuFeatures :: [X86CpuFeature]
+cachedX86CpuFeatures = unsafePerformIO detectX86CpuFeatures
+{-# NOINLINE cachedX86CpuFeatures #-}
+
+cpuFeatureBitLayout :: [(Int, X86CpuFeature)]
+cpuFeatureBitLayout =
+ [ (0, SSE2)
+ , (1, SSE3)
+ , (2, SSSE3)
+ , (3, SSE4_1)
+ , (4, SSE4_2)
+ , (5, AVX)
+ , (6, AVX2)
+ , (7, AVX512F)
+ , (8, AVX512BW)
+ , (9, AVX512CD)
+ , (10, AVX512DQ)
+ , (11, AVX512VL)
+ , (12, BMI1)
+ , (13, BMI2)
+ , (14, FMA)
+ , (15, GFNI)
+ ]
+
+#if !defined(javascript_HOST_ARCH)
+foreign import ccall unsafe "ghc_detect_x86_cpu_features"
+ c_ghc_detect_x86_cpu_features :: IO Word64
+#endif
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -470,6 +470,8 @@ data DynFlags = DynFlags {
fma :: Bool, -- ^ Enable FMA instructions.
gfni :: Bool, -- ^ Enable GFNI Instructions.
la664 :: Bool, -- ^ Enable LA664 instructions
+ marchNative :: Bool, -- ^ @-march=native@ was requested; the host
+ -- CPU features are applied during flag parsing.
-- Constants used to control the amount of optimization done.
@@ -760,6 +762,7 @@ defaultDynFlags mySettings =
gfni = False,
-- For LoongArch, la464 is used by default.
la664 = False,
+ marchNative = False,
maxInlineAllocSize = 128,
maxInlineMemcpyInsns = 32,
@@ -1615,6 +1618,7 @@ initPromotionTickContext dflags =
-- -----------------------------------------------------------------------------
-- SSE, AVX, FMA
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
isSse3Enabled :: DynFlags -> Bool
isSse3Enabled dflags = sseAvxVersion dflags >= Just SSE3 || isAvxEnabled dflags
@@ -1705,11 +1709,14 @@ We handle this as follows:
-- -----------------------------------------------------------------------------
-- LA664
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
+
isLa664Enabled :: DynFlags -> Bool
isLa664Enabled dflags = la664 dflags
-- -----------------------------------------------------------------------------
-- BMI2
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
isBmiEnabled :: DynFlags -> Bool
isBmiEnabled dflags = case platformArch (targetPlatform dflags) of
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -196,6 +196,8 @@ module GHC.Driver.Session (
-- * Compiler configuration suitable for display to the user
compilerInfo,
+ showEnabledCpuFeatures,
+ enabledCpuFeatures,
targetHasRTSWays,
@@ -243,6 +245,8 @@ import GHC.Platform
import GHC.Platform.Ways
import GHC.Platform.Profile
import GHC.Platform.ArchOS
+import GHC.Platform.Host (hostPlatformArch)
+import qualified GHC.Driver.CpuFeatures as Cpu
import GHC.Unit.Types
import GHC.Unit.Parser
@@ -277,6 +281,7 @@ import GHC.Utils.TmpFs
import GHC.Utils.Fingerprint
import GHC.Utils.Outputable
import GHC.Utils.Error (emptyDiagOpts, logInfo)
+import GHC.Utils.Json
import GHC.Settings
import GHC.CmmToAsm.CFG.Weight
import GHC.Core.Opt.CallerCC
@@ -903,8 +908,12 @@ parseDynamicFlagsFull activeFlags cmdline logger dflags0 args = do
unless (null errs) $ liftIO $ throwGhcExceptionIO $ errorsToGhcException $
map ((rdr . ppr . getLoc &&& unLoc) . errMsg) $ errs
+ -- Apply -march=native: probe the host CPU and enable the matching feature
+ -- flags. This needs IO (CPUID), so it cannot live in the pure flag handlers.
+ dflags1' <- applyMarchNative dflags1
+
-- check for disabled flags in safe haskell
- let (dflags2, sh_warns) = safeFlagCheck cmdline dflags1
+ let (dflags2, sh_warns) = safeFlagCheck cmdline dflags1'
theWays = ways dflags2
unless (allowed_combination theWays) $ liftIO $
@@ -1740,6 +1749,7 @@ dynamic_flags_deps = [
, make_ord_flag defGhcFlag "mavx512vl" (noArg (\d -> d { avx512vl = True }))
, make_ord_flag defGhcFlag "mfma" (noArg (\d -> d { fma = True }))
, make_ord_flag defGhcFlag "mgfni" (noArg (\d -> d { gfni = True }))
+ , make_ord_flag defGhcFlag "march=native" (noArg (\d -> d { marchNative = True }))
, make_ord_flag defGhcFlag "mla664" (noArg (\d -> d { la664 = True }))
@@ -3677,6 +3687,185 @@ compilerInfo dflags
queryCmdMaybe p f = expandDirectories (query (maybe "" (prgPath . p) . f))
queryFlagsMaybe p f = query (maybe "" (unwords . map escapeArg . prgFlags . p) . f)
+showEnabledCpuFeatures :: DynFlags -> String
+showEnabledCpuFeatures dflags = showSDocUnsafe $ renderJSON $ JSObject
+ [ ("tag", JSString "enabled-cpu-features")
+ -- Schema version of this JSON object; bump it whenever the shape or
+ -- meaning of the fields changes, so consumers can detect incompatibility.
+ , ("version", JSInt 1)
+ , ("target", JSString (platformMisc_targetPlatformString (platformMisc dflags)))
+ , ("features", JSArray (map JSString features))
+ -- A set of `-m...` flags that, passed to GHC for this target, reproduce
+ -- the effective feature set above. Note this need not be the flags the
+ -- user actually passed: implied features are folded in, and a feature
+ -- enabled by default may be reproduced by the empty set.
+ , ("as_m_flags", JSArray (map JSString asMFlags))
+ ]
+ where
+ (features, asMFlags) = enabledCpuFeatures dflags
+
+{- Note [Keeping enabledCpuFeatures in sync]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+`enabledCpuFeatures` must be updated whenever a new CPU feature flag is added
+to GHC. The three places to touch are, all in GHC.Driver.DynFlags:
+
+ 1. The flag registration (e.g. `make_ord_flag defGhcFlag "mnewfeat" ...`)
+ 2. The corresponding `is*Enabled` predicate
+ 3. The `enabledCpuFeatures` function below — add the feature to `features`
+ and, if it has a GHC `-m...` flag, to `as_m_flags` via the appropriate
+ architecture branch.
+
+See Note [Implications between X86 CPU feature flags] in GHC.Driver.DynFlags
+for the implication structure that `x86FeaturesAndFlags` and `x86AsMFlags`
+must respect.
+-}
+
+enabledCpuFeatures :: DynFlags -> ([String], [String])
+enabledCpuFeatures dflags = case platformArch (targetPlatform dflags) of
+ ArchX86_64 -> x86FeaturesAndFlags dflags
+ ArchX86 -> x86FeaturesAndFlags dflags
+ ArchLoongArch64 ->
+ ( fmaFeature ++ [ "LA664" | isLa664Enabled dflags ]
+ , fmaFlag ++ [ "-mla664" | isLa664Enabled dflags ]
+ )
+ _ -> (fmaFeature, fmaFlag)
+ where
+ -- `-mfma` is a cross-platform flag. On x86 it is folded into the
+ -- SSE/AVX hierarchy (handled in x86FeaturesAndFlags); on every other
+ -- architecture FMA stands on its own and gates FMA codegen via
+ -- isFmaEnabled in stgToCmmAllowFMAInstr. `fma dflags` is the source of
+ -- truth (it defaults to True on AArch64).
+ fmaFeature = [ "FMA" | fma dflags ]
+ fmaFlag = [ "-mfma" | fma dflags ]
+
+x86FeaturesAndFlags :: DynFlags -> ([String], [String])
+x86FeaturesAndFlags dflags =
+ -- SSE/SSE2 are determined by the target platform rather than a dynamic
+ -- flag, hence those predicates take Platform while the others take DynFlags.
+ ( [ "SSE" | isSseEnabled platform ]
+ ++ [ "SSE2" | isSse2Enabled platform ]
+ ++ [ "SSE3" | isSse3Enabled dflags ]
+ ++ [ "SSSE3" | isSsse3Enabled dflags ]
+ ++ [ "SSE4.1" | isSse4_1Enabled dflags ]
+ ++ [ "SSE4.2" | isSse4_2Enabled dflags ]
+ ++ [ "AVX" | isAvxEnabled dflags ]
+ ++ [ "AVX2" | isAvx2Enabled dflags ]
+ ++ [ "AVX512F" | isAvx512fEnabled dflags ]
+ ++ [ "AVX512BW" | isAvx512bwEnabled dflags ]
+ ++ [ "AVX512CD" | isAvx512cdEnabled dflags ]
+ ++ [ "AVX512DQ" | isAvx512dqEnabled dflags ]
+ ++ [ "AVX512ER" | isAvx512erEnabled dflags ]
+ ++ [ "AVX512PF" | isAvx512pfEnabled dflags ]
+ ++ [ "AVX512VL" | isAvx512vlEnabled dflags ]
+ ++ [ "BMI1" | isBmiEnabled dflags ]
+ ++ [ "BMI2" | isBmi2Enabled dflags ]
+ ++ [ "FMA" | isFmaEnabled dflags ]
+ ++ [ "GFNI" | isGfniEnabled dflags ]
+ , x86AsMFlags dflags
+ )
+ where
+ platform = targetPlatform dflags
+
+x86AsMFlags :: DynFlags -> [String]
+x86AsMFlags dflags =
+ avx512Flags
+ ++ vectorFlags
+ ++ bmiFlags
+ ++ fmaFlags
+ ++ gfniFlags
+ where
+ avx512Extensions =
+ [ ("-mavx512bw", avx512bw dflags)
+ , ("-mavx512cd", avx512cd dflags)
+ , ("-mavx512dq", avx512dq dflags)
+ , ("-mavx512er", avx512er dflags)
+ , ("-mavx512pf", avx512pf dflags)
+ , ("-mavx512vl", avx512vl dflags)
+ ]
+
+ hasAvx512Extension = any snd avx512Extensions
+ hasAvx512 = avx512f dflags || hasAvx512Extension
+
+ avx512Flags =
+ [ "-mavx512f" | avx512f dflags && not hasAvx512Extension ]
+ ++ [ flag | (flag, True) <- avx512Extensions ]
+
+ vectorFlags
+ | hasAvx512 = []
+ | otherwise =
+ case sseAvxVersion dflags of
+ Just AVX2 -> ["-mavx2"]
+ Just AVX1 -> ["-mavx"]
+ Just SSE42 -> ["-msse4.2"]
+ Just SSE4 -> ["-msse4"]
+ Just SSSE3 -> ["-mssse3"]
+ Just SSE3 -> ["-msse3"]
+ _ -> []
+
+ bmiFlags = case bmiVersion dflags of
+ Just BMI2 -> ["-mbmi2"]
+ Just BMI1 -> ["-mbmi"]
+ Nothing -> []
+
+ fmaFlags
+ | fma dflags && not hasAvx512 = ["-mfma"]
+ | otherwise = []
+
+ gfniFlags = [ "-mgfni" | gfni dflags ]
+
+-- | Apply a requested @-march=native@ by probing the host CPU and enabling the
+-- matching CPU-feature flags.
+--
+-- This runs in 'parseDynamicFlagsFull' rather than in a flag handler because the
+-- CPUID probe needs 'IO', whereas flag handlers are pure. The detected features
+-- are folded into the existing feature 'DynFlags' so that 'makeDynFlagsConsistent'
+-- and the backends treat them exactly like the corresponding @-m...@ flags.
+applyMarchNative :: MonadIO m => DynFlags -> m DynFlags
+applyMarchNative dflags
+ | not (marchNative dflags) = return dflags
+ | otherwise = do
+ let arch = platformArch (targetPlatform dflags)
+ unless (arch == ArchX86 || arch == ArchX86_64) $ liftIO $
+ throwGhcExceptionIO $ CmdLineError
+ "-march=native is only supported on x86 and x86_64 targets"
+ unless (arch == hostPlatformArch) $ liftIO $
+ throwGhcExceptionIO $ CmdLineError
+ "-march=native is not supported when cross-compiling"
+ return (applyX86CpuFeatures Cpu.cachedX86CpuFeatures dflags)
+
+-- | Enable the 'DynFlags' CPU-feature fields corresponding to a probed set of
+-- host x86 features. SSE/AVX and BMI levels are collapsed to their maximum,
+-- since 'sseAvxVersion' and 'bmiVersion' each record a single level.
+applyX86CpuFeatures :: [Cpu.X86CpuFeature] -> DynFlags -> DynFlags
+applyX86CpuFeatures feats dflags = dflags
+ { sseAvxVersion = foldr (max . Just) (sseAvxVersion dflags) sseLevels
+ , bmiVersion = foldr (max . Just) (bmiVersion dflags) bmiLevels
+ , avx512f = avx512f dflags || has Cpu.AVX512F
+ , avx512bw = avx512bw dflags || has Cpu.AVX512BW
+ , avx512cd = avx512cd dflags || has Cpu.AVX512CD
+ , avx512dq = avx512dq dflags || has Cpu.AVX512DQ
+ , avx512vl = avx512vl dflags || has Cpu.AVX512VL
+ , fma = fma dflags || has Cpu.FMA
+ , gfni = gfni dflags || has Cpu.GFNI
+ }
+ where
+ has feat = feat `elem` feats
+ sseLevels = [ lvl | feat <- feats, Just lvl <- [sseLevelOf feat] ]
+ bmiLevels = [ lvl | feat <- feats, Just lvl <- [bmiLevelOf feat] ]
+ sseLevelOf feat = case feat of
+ Cpu.SSE2 -> Just SSE2
+ Cpu.SSE3 -> Just SSE3
+ Cpu.SSSE3 -> Just SSSE3
+ Cpu.SSE4_1 -> Just SSE4
+ Cpu.SSE4_2 -> Just SSE42
+ Cpu.AVX -> Just AVX1
+ Cpu.AVX2 -> Just AVX2
+ _ -> Nothing
+ bmiLevelOf feat = case feat of
+ Cpu.BMI1 -> Just BMI1
+ Cpu.BMI2 -> Just BMI2
+ _ -> Nothing
+
-- | Query if the target RTS has the given 'Ways'. It's computed from
-- the @"RTS ways"@ field in the settings file.
targetHasRTSWays :: DynFlags -> Ways -> Bool
=====================================
compiler/cbits/cpu_features_x86.c
=====================================
@@ -0,0 +1,177 @@
+#include <HsFFI.h>
+#include <stdint.h>
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+#include <immintrin.h>
+#include <intrin.h>
+#endif
+
+#if !defined(_MSC_VER) && (defined(__i386__) || defined(__x86_64__))
+#include <cpuid.h>
+#endif
+
+enum {
+ GHC_X86_FEAT_SSE2 = 0,
+ GHC_X86_FEAT_SSE3,
+ GHC_X86_FEAT_SSSE3,
+ GHC_X86_FEAT_SSE4_1,
+ GHC_X86_FEAT_SSE4_2,
+ GHC_X86_FEAT_AVX,
+ GHC_X86_FEAT_AVX2,
+ GHC_X86_FEAT_AVX512F,
+ GHC_X86_FEAT_AVX512BW,
+ GHC_X86_FEAT_AVX512CD,
+ GHC_X86_FEAT_AVX512DQ,
+ GHC_X86_FEAT_AVX512VL,
+ GHC_X86_FEAT_BMI1,
+ GHC_X86_FEAT_BMI2,
+ GHC_X86_FEAT_FMA,
+ GHC_X86_FEAT_GFNI
+};
+
+#define SET_FEAT(mask, bit) ((mask) |= ((HsWord64)1ULL << (bit)))
+
+static int ghc_cpuid_count(uint32_t leaf, uint32_t subleaf,
+ uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
+{
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+ int regs[4];
+ __cpuidex(regs, (int)leaf, (int)subleaf);
+ *a = (uint32_t)regs[0];
+ *b = (uint32_t)regs[1];
+ *c = (uint32_t)regs[2];
+ *d = (uint32_t)regs[3];
+ return 1;
+#elif defined(__i386__) || defined(__x86_64__)
+ return __get_cpuid_count(leaf, subleaf, a, b, c, d);
+#else
+ (void)leaf;
+ (void)subleaf;
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ return 0;
+#endif
+}
+
+static uint64_t ghc_xgetbv0(void)
+{
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+ return (uint64_t)_xgetbv(0);
+#elif defined(__i386__) || defined(__x86_64__)
+ uint32_t eax, edx;
+ __asm__ volatile(".byte 0x0f, 0x01, 0xd0" /* xgetbv */
+ : "=a"(eax), "=d"(edx)
+ : "c"(0));
+ return ((uint64_t)edx << 32) | (uint64_t)eax;
+#else
+ return 0;
+#endif
+}
+
+HsWord64 ghc_detect_x86_cpu_features(void)
+{
+ HsWord64 feats = 0;
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
+ uint32_t a, b, c, d;
+ uint32_t max_basic = 0;
+
+ if (!ghc_cpuid_count(0, 0, &a, &b, &c, &d)) {
+ return 0;
+ }
+ max_basic = a;
+ if (max_basic < 1) {
+ return 0;
+ }
+
+ ghc_cpuid_count(1, 0, &a, &b, &c, &d);
+
+ {
+ int has_sse2 = !!(d & (1u << 26));
+ int has_sse3 = !!(c & (1u << 0));
+ int has_ssse3 = !!(c & (1u << 9));
+ int has_sse4_1 = !!(c & (1u << 19));
+ int has_sse4_2 = !!(c & (1u << 20));
+ int has_fma_hw = !!(c & (1u << 12));
+ int has_avx_hw = !!(c & (1u << 28));
+ int has_osxsave = !!(c & (1u << 27));
+
+ int avx_usable = 0;
+ int avx512_usable = 0;
+
+ if (has_osxsave) {
+ uint64_t xcr0 = ghc_xgetbv0();
+ avx_usable = ((xcr0 & 0x6u) == 0x6u); /* XMM + YMM state */
+ avx512_usable = ((xcr0 & 0xE6u) == 0xE6u); /* XMM+YMM+opmask+ZMM */
+ }
+
+ if (has_sse2) {
+ SET_FEAT(feats, GHC_X86_FEAT_SSE2);
+ }
+ if (has_sse3) {
+ SET_FEAT(feats, GHC_X86_FEAT_SSE3);
+ }
+ if (has_ssse3) {
+ SET_FEAT(feats, GHC_X86_FEAT_SSSE3);
+ }
+ if (has_sse4_1) {
+ SET_FEAT(feats, GHC_X86_FEAT_SSE4_1);
+ }
+ if (has_sse4_2) {
+ SET_FEAT(feats, GHC_X86_FEAT_SSE4_2);
+ }
+ if (has_avx_hw && avx_usable) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX);
+ }
+ if (has_fma_hw && avx_usable) {
+ SET_FEAT(feats, GHC_X86_FEAT_FMA);
+ }
+
+ if (max_basic >= 7 && ghc_cpuid_count(7, 0, &a, &b, &c, &d)) {
+ int has_bmi1 = !!(b & (1u << 3));
+ int has_avx2_hw = !!(b & (1u << 5));
+ int has_bmi2 = !!(b & (1u << 8));
+ int has_avx512f = !!(b & (1u << 16));
+ int has_avx512dq = !!(b & (1u << 17));
+ int has_avx512cd = !!(b & (1u << 28));
+ int has_avx512bw = !!(b & (1u << 30));
+ int has_avx512vl = !!(b & (1u << 31));
+ int has_gfni = !!(c & (1u << 8));
+
+ if (has_bmi1) {
+ SET_FEAT(feats, GHC_X86_FEAT_BMI1);
+ }
+ if (has_bmi2) {
+ SET_FEAT(feats, GHC_X86_FEAT_BMI2);
+ }
+ if (avx_usable && has_avx2_hw) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX2);
+ }
+
+ if (avx512_usable && has_avx512f) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX512F);
+ if (has_avx512bw) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX512BW);
+ }
+ if (has_avx512cd) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX512CD);
+ }
+ if (has_avx512dq) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX512DQ);
+ }
+ if (has_avx512vl) {
+ SET_FEAT(feats, GHC_X86_FEAT_AVX512VL);
+ }
+ }
+
+ if (has_gfni) {
+ SET_FEAT(feats, GHC_X86_FEAT_GFNI);
+ }
+ }
+ }
+#endif
+
+ return feats;
+}
=====================================
compiler/ghc.cabal.in
=====================================
@@ -187,6 +187,7 @@ Library
else
c-sources:
cbits/cutils.c
+ cbits/cpu_features_x86.c
cbits/genSym.c
cbits/keepCAFsForGHCi.c
@@ -514,6 +515,7 @@ Library
GHC.Driver.Config.StgToCmm
GHC.Driver.Config.Tidy
GHC.Driver.Config.StgToJS
+ GHC.Driver.CpuFeatures
GHC.Driver.DynFlags
GHC.Driver.IncludeSpecs
GHC.Driver.Downsweep
=====================================
docs/users_guide/using.rst
=====================================
@@ -488,6 +488,16 @@ The available mode flags are:
List the flags passed to the C compiler for the linking step
during GHC build.
+.. ghc-flag:: --print-enabled-cpu-features
+ :shortdesc: display the effective enabled CPU features for code generation
+ :type: mode
+ :category: modes
+
+ Print a JSON object describing the CPU features currently enabled for code
+ generation, together with a set of ``-m...`` flags that reproduce the
+ effective feature set for the current target.
+ Dynamic options such as ``-mavx2`` and ``-mbmi2`` are respected.
+
.. ghc-flag:: --print-debug-on
:shortdesc: print whether GHC was built with ``-DDEBUG``
:type: mode
@@ -1844,6 +1854,30 @@ Some flags only make sense for particular target platforms.
so this flag has no effect when used with the :ref:`native code generator <native-code-gen>`
or the :ref:`LLVM backend <llvm-code-gen>`.
+.. ghc-flag:: -march=native
+ :shortdesc: (x86 only) Enable all CPU features supported by the host
+ :type: dynamic
+ :category: platform-options
+
+ (x86/x86_64 only) Probe the CPU of the machine running GHC and enable all of
+ the corresponding ``-m...`` CPU-feature options automatically (for example
+ ``-msse4.2``, ``-mavx2``, ``-mbmi2``, ``-mfma``). The detected features apply
+ to both the :ref:`native code generator <native-code-gen>` and the
+ :ref:`LLVM backend <llvm-code-gen>`.
+
+ The detected features are enabled *in addition* to any CPU-feature flags you
+ pass explicitly, regardless of their order on the command line; ``-march=native``
+ never disables a feature.
+
+ .. warning::
+
+ Code compiled with ``-march=native`` may use instructions that are not
+ available on other CPUs, and is therefore not portable to a different
+ machine.
+
+ This flag is rejected when compiling for a non-x86 target or when
+ cross-compiling, since the host CPU is then unrelated to the target.
+
Haddock
-------
=====================================
ghc/GHC/Driver/Session/Lint.hs
=====================================
@@ -1,6 +1,6 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE NondecreasingIndentation #-}
-module GHC.Driver.Session.Lint (checkOptions) where
+module GHC.Driver.Session.Lint (checkOptions, unknownFlagsErr) where
import GHC.Driver.Backend
import GHC.Driver.Phases
=====================================
ghc/GHC/Driver/Session/Mode.hs
=====================================
@@ -77,6 +77,7 @@ isShowGhciUsageMode _ = False
data PostLoadMode
= ShowInterface FilePath -- ghc --show-iface
+ | PrintEnabledCpuFeatures -- ghc --print-enabled-cpu-features
| DoMkDependHS -- ghc -M
| StopBefore StopPhase -- ghc -E | -C | -S
-- StopBefore StopLn is the default
@@ -90,12 +91,13 @@ data PostLoadMode
| DoFrontend ModuleName -- ghc --frontend Plugin.Module
doMkDependHSMode, doMakeMode, doInteractiveMode, doRunMode,
- doAbiHashMode, showUnitsMode :: Mode
+ doAbiHashMode, printEnabledCpuFeaturesMode, showUnitsMode :: Mode
doMkDependHSMode = mkPostLoadMode DoMkDependHS
doMakeMode = mkPostLoadMode DoMake
doInteractiveMode = mkPostLoadMode DoInteractive
doRunMode = mkPostLoadMode DoRun
doAbiHashMode = mkPostLoadMode DoAbiHash
+printEnabledCpuFeaturesMode = mkPostLoadMode PrintEnabledCpuFeatures
showUnitsMode = mkPostLoadMode ShowPackages
showInterfaceMode :: FilePath -> Mode
@@ -203,6 +205,8 @@ mode_flags =
, defFlag "-show-options" (PassFlag (setMode showOptionsMode))
, defFlag "-supported-languages" (PassFlag (setMode showSupportedExtensionsMode))
, defFlag "-supported-extensions" (PassFlag (setMode showSupportedExtensionsMode))
+ , defFlag "-print-enabled-cpu-features"
+ (PassFlag (setMode printEnabledCpuFeaturesMode))
, defFlag "-show-packages" (PassFlag (setMode showUnitsMode))
] ++
[ defFlag k' (PassFlag (setMode (printSetting k)))
=====================================
ghc/Main.hs
=====================================
@@ -229,55 +229,64 @@ main' postLoadMode units dflags0 args flagWarnings = do
liftIO $ exitWith (ExitFailure 1)) $ do
liftIO $ printOrThrowDiagnostics logger4 (initPrintConfig dflags4) diag_opts flagWarnings'
- liftIO $ showBanner postLoadMode dflags4
-
- let (dflags5, srcs, objs) = parseTargetFiles dflags4 (map unLoc fileish_args)
-
- -- we've finished manipulating the DynFlags, update the session
- _ <- GHC.setSessionDynFlags dflags5
- dflags6 <- GHC.getSessionDynFlags
-
- -- Must do this before loading plugins
- liftIO $ initUniqSupply (initialUnique dflags6) (uniqueIncrement dflags6)
-
- -- Initialise plugins here because the plugin author might already expect this
- -- subsequent call to `getLogger` to be affected by a plugin.
- initializeSessionPlugins
- hsc_env <- getSession
- logger <- getLogger
-
-
- ---------------- Display configuration -----------
- case verbosity dflags6 of
- v | v == 4 -> liftIO $ dumpUnitsSimple hsc_env
- | v >= 5 -> liftIO $ dumpUnits hsc_env
- | otherwise -> return ()
-
- ---------------- Final sanity checking -----------
- liftIO $ checkOptions postLoadMode dflags6 srcs objs units
-
- ---------------- Do the business -----------
- handleSourceError (\e -> do
- GHC.printException e
- liftIO $ exitWith (ExitFailure 1)) $ do
- case postLoadMode of
- ShowInterface f -> liftIO $ showIface logger
- (hsc_dflags hsc_env)
- (hsc_units hsc_env)
- (hsc_NC hsc_env)
- f
- DoMake -> doMake units srcs
- DoMkDependHS -> doMkDependHS (map fst srcs)
- StopBefore p -> liftIO (oneShot hsc_env p srcs)
- DoInteractive -> ghciUI units srcs Nothing
- DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
- DoRun -> doRun units srcs args
- DoAbiHash -> abiHash (map fst srcs)
- ShowPackages -> liftIO $ showUnits hsc_env
- DoFrontend f -> doFrontend f srcs
- DoBackpack -> doBackpack (map fst srcs)
-
- liftIO $ dumpFinalStats logger
+ case postLoadMode of
+ PrintEnabledCpuFeatures -> liftIO $ do
+ -- This mode bypasses parseTargetFiles/checkOptions, so reject any
+ -- leftover flag-like arguments (e.g. a mistyped -mavx22) ourselves;
+ -- otherwise the typo would be silently ignored.
+ let unknown_opts = [ f | f@('-':_) <- map unLoc fileish_args ]
+ when (not (null unknown_opts)) (unknownFlagsErr unknown_opts)
+ putStrLn (showEnabledCpuFeatures dflags4)
+ _ -> do
+ liftIO $ showBanner postLoadMode dflags4
+
+ let (dflags5, srcs, objs) = parseTargetFiles dflags4 (map unLoc fileish_args)
+
+ -- we've finished manipulating the DynFlags, update the session
+ _ <- GHC.setSessionDynFlags dflags5
+ dflags6 <- GHC.getSessionDynFlags
+
+ -- Must do this before loading plugins
+ liftIO $ initUniqSupply (initialUnique dflags6) (uniqueIncrement dflags6)
+
+ -- Initialise plugins here because the plugin author might already expect this
+ -- subsequent call to `getLogger` to be affected by a plugin.
+ initializeSessionPlugins
+ hsc_env <- getSession
+ logger <- getLogger
+
+
+ ---------------- Display configuration -----------
+ case verbosity dflags6 of
+ v | v == 4 -> liftIO $ dumpUnitsSimple hsc_env
+ | v >= 5 -> liftIO $ dumpUnits hsc_env
+ | otherwise -> return ()
+
+ ---------------- Final sanity checking -----------
+ liftIO $ checkOptions postLoadMode dflags6 srcs objs units
+
+ ---------------- Do the business -----------
+ handleSourceError (\e -> do
+ GHC.printException e
+ liftIO $ exitWith (ExitFailure 1)) $ do
+ case postLoadMode of
+ ShowInterface f -> liftIO $ showIface logger
+ (hsc_dflags hsc_env)
+ (hsc_units hsc_env)
+ (hsc_NC hsc_env)
+ f
+ DoMake -> doMake units srcs
+ DoMkDependHS -> doMkDependHS (map fst srcs)
+ StopBefore p -> liftIO (oneShot hsc_env p srcs)
+ DoInteractive -> ghciUI units srcs Nothing
+ DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
+ DoRun -> doRun units srcs args
+ DoAbiHash -> abiHash (map fst srcs)
+ ShowPackages -> liftIO $ showUnits hsc_env
+ DoFrontend f -> doFrontend f srcs
+ DoBackpack -> doBackpack (map fst srcs)
+
+ liftIO $ dumpFinalStats logger
doRun :: [String] -> [(FilePath, Maybe Phase)] -> [Located String] -> Ghc ()
doRun units srcs args = do
@@ -515,4 +524,3 @@ abiHash strs = do
f <- fingerprintBinMem bh
putStrLn (showPpr dflags f)
-
=====================================
testsuite/tests/codeGen/should_gen_asm/all.T
=====================================
@@ -17,6 +17,11 @@ test('msse-option-order', [unless(arch('x86_64') or arch('i386'), skip),
when(unregisterised(), skip)], compile_grep_asm, ['hs', False, '-msse4.2 -msse2'])
test('mavx-should-enable-popcnt', [unless(arch('x86_64') or arch('i386'), skip),
when(unregisterised(), skip)], compile_grep_asm, ['hs', False, '-mavx'])
+# -march=native probes the host CPU, so gate on the host actually having SSE4.2
+# (have_cpu_feature reports nothing under cross, skipping the test there too).
+test('march-native-enables-popcnt',
+ [unless((arch('x86_64') or arch('i386')) and have_cpu_feature('sse4_2'), skip),
+ when(unregisterised(), skip)], compile_grep_asm, ['hs', False, '-march=native'])
test('avx512-int64-mul', [unless(arch('x86_64'), skip),
when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512dq -mavx512vl'])
test('avx512-int64-minmax', [unless(arch('x86_64'), skip),
=====================================
testsuite/tests/codeGen/should_gen_asm/march-native-enables-popcnt.asm
=====================================
@@ -0,0 +1 @@
+popcnt(?![0-9])
\ No newline at end of file
=====================================
testsuite/tests/codeGen/should_gen_asm/march-native-enables-popcnt.hs
=====================================
@@ -0,0 +1,11 @@
+-- `-march=native` enables the host's CPU features. On a host with SSE4.2
+-- (gated in all.T via have_cpu_feature) this makes popCount compile to a
+-- `popcnt` instruction rather than the SSE2-baseline software fallback.
+import Data.Bits
+
+{-# NOINLINE foo #-}
+foo :: Int -> Int
+foo x = 1 + popCount x
+
+main :: IO ()
+main = print (foo 42)
=====================================
testsuite/tests/driver/all.T
=====================================
@@ -1,3 +1,18 @@
+def normalise_enabled_cpu_target(msg):
+ return re.sub(r'"target":"[^"]+"', '"target":"TARGET"', msg)
+
+def normalise_unknown_flag(msg):
+ # Keep only the stable 'unrecognised flag' line; the program-name prefix,
+ # the suggestion list, and the usage trailer vary across configurations.
+ m = re.search(r'unrecognised flag: \S+', msg)
+ return m.group(0) + '\n' if m else msg
+
+def normalise_march_native_error(msg):
+ # Keep only the stable '-march=native ...' diagnostic; the program-name
+ # prefix and any usage trailer vary across configurations.
+ m = re.search(r'-march=native is [^\n]+', msg)
+ return m.group(0) + '\n' if m else msg
+
test('driver011', [extra_files(['A011.hs'])], makefile_test, ['test011'])
test('driver012', [extra_files(['A012.hs'])], makefile_test, ['test012'])
@@ -221,6 +236,77 @@ test('T9938B', [], makefile_test, [])
test('T9963', exit_code(1), run_command,
['{compiler} --interactive -ignore-dot-ghci --print-libdir'])
+test('print_enabled_cpu_features',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_avx2',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mavx2 --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_bmi2',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mbmi2 --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_fma',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mfma --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_avx512',
+ [unless(arch('x86_64'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mavx512dq -mavx512vl --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_unknown_flag',
+ [normalise_fun(normalise_unknown_flag), exit_code(1)],
+ run_command,
+ ['{compiler} -mavx22 --print-enabled-cpu-features'])
+
+# -march=native enables at least the x86_64 baseline (SSE2). The full feature
+# set is host-dependent, so we only assert the always-present baseline.
+test('march_native',
+ [unless(arch('x86_64') or arch('i386'), skip)],
+ run_command,
+ ['{compiler} -march=native --print-enabled-cpu-features | grep -o SSE2'])
+
+# On non-x86 targets -march=native must be rejected.
+test('march_native_unsupported_arch',
+ [when(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_march_native_error), exit_code(1)],
+ run_command,
+ ['{compiler} -march=native --print-enabled-cpu-features'])
+
+# -march=native is additive: its feature set is a superset of the default set.
+# We extract the "features" arrays with and without the flag and assert that no
+# baseline feature is dropped (comm -23 prints baseline-only entries; expect none).
+# This avoids hard-coding the host-specific feature set.
+test('march_native_superset',
+ [unless(arch('x86_64') or arch('i386'), skip)],
+ run_command,
+ ['{compiler} --print-enabled-cpu-features | '
+ 'sed \'s/.*"features":\\[//;s/].*//;s/"//g\' | tr \',\' \'\\n\' | sort > base.txt && '
+ '{compiler} -march=native --print-enabled-cpu-features | '
+ 'sed \'s/.*"features":\\[//;s/].*//;s/"//g\' | tr \',\' \'\\n\' | sort > native.txt && '
+ 'comm -23 base.txt native.txt'])
+
+# -march=native is additive with explicit -m flags, regardless of order: an
+# explicitly requested feature (here AVX2, forced on independent of the host) is
+# still present whether the flag comes before or after -march=native.
+test('march_native_additive',
+ [unless(arch('x86_64') or arch('i386'), skip)],
+ run_command,
+ ['{compiler} -mavx2 -march=native --print-enabled-cpu-features | grep -o AVX2 && '
+ '{compiler} -march=native -mavx2 --print-enabled-cpu-features | grep -o AVX2'])
+
test('T10219', normal, run_command,
# `-x hspp` in make mode should work.
# Note: need to specify `-x hspp` before the filename.
=====================================
testsuite/tests/driver/march_native.stdout
=====================================
@@ -0,0 +1 @@
+SSE2
=====================================
testsuite/tests/driver/march_native_additive.stdout
=====================================
@@ -0,0 +1,2 @@
+AVX2
+AVX2
=====================================
testsuite/tests/driver/march_native_unsupported_arch.stderr
=====================================
@@ -0,0 +1 @@
+-march=native is only supported on x86 and x86_64 targets
=====================================
testsuite/tests/driver/print_enabled_cpu_features.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2"],"as_m_flags":[]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_avx2.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],"as_m_flags":["-mavx2"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_avx512.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2","AVX512F","AVX512DQ","AVX512VL","FMA"],"as_m_flags":["-mavx512dq","-mavx512vl"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_bmi2.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","BMI1","BMI2"],"as_m_flags":["-mbmi2"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_fma.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","FMA"],"as_m_flags":["-mfma"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_unknown_flag.stderr
=====================================
@@ -0,0 +1,6 @@
+ghc: unrecognised flag: -mavx22
+did you mean one of:
+ -mavx2
+ -mavx
+
+Usage: For basic information, try the `--help' option.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/19ca1ae48d71b92c7d56672cf406ab…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/19ca1ae48d71b92c7d56672cf406ab…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fix-26953] 27 commits: EPA: Fix exact printing namespace-specified wildcards
by recursion-ninja (@recursion-ninja) 02 Jun '26
by recursion-ninja (@recursion-ninja) 02 Jun '26
02 Jun '26
recursion-ninja pushed to branch wip/fix-26953 at Glasgow Haskell Compiler / GHC
Commits:
99edbbf7 by Alan Zimmerman at 2026-06-01T21:11:49-04:00
EPA: Fix exact printing namespace-specified wildcards
Ensures correct printing of imports of the form
import Data.Bool (data True(data ..))
import Data.Bool (data True(type ..))
Closes #27291
- - - - -
94388138 by Mrjtjmn at 2026-06-01T21:11:56-04:00
Fix ambiguous syntax of BangPatterns in users guide
Update documentation for the BangPatterns extension to specify
how surrounding whitespace affects interpretation of `!`.
* Only when there is whitespace before `!` and no whitespace after,
it is recognized as a BangPattern.
* Other cases `⟨varid⟩!⟨varid⟩`, `⟨varid⟩ ! ⟨varid⟩`, `⟨varid⟩! ⟨varid⟩`
are treated as infix operators.
- - - - -
28ff684e by Simon Jakobi at 2026-06-01T21:11:56-04:00
Ensure that SetOps.{minusList,unionListsOrd} can be specialized
...by marking them INLINABLE. Haddock allocates 0.1–0.3% less as a
result.
This also removes some redundant constraints on unionListsOrd.
- - - - -
db091604 by Cheng Shao at 2026-06-01T21:11:56-04:00
wasm: ensure post-linker output is synchronous ESM
This patch fixes wasm backend's post-linker output script to ensure
it's synchronous ESM and doesn't use top-level await, which doesn't
work in ServiceWorkers. Fixes #27257.
- - - - -
342539e6 by Zubin Duggal at 2026-06-01T21:11:56-04:00
Update to semaphore-compat 2.0.0 using v2 of the protocol
On Linux and other POSIX platforms, GHC's -jsem jobserver client now
speaks v2 of the semaphore-compat protocol, which uses Unix domain
sockets in place of POSIX named semaphores. This avoids the libc-ABI
issues that affected the old implementation. Windows is unaffected
and continues to use the v1 protocol (Win32 named semaphores); its
reported protocol version remains v1.
When GHC receives a -jsem name whose protocol version it does not
support, it emits a -Wsemaphore-version-mismatch warning and falls
back to -j<N> rather than crashing. ghc --info exposes the supported
version in a new "Semaphore version" entry so cabal-install can detect
a mismatch before invoking GHC.
Users on a cabal-install that predates the v2 update will continue to
build successfully on Linux/POSIX, but will lose the cross-process
-jsem coordination and fall back to -j<N> per GHC invocation. Users
must upgrade to a cabal-install that supports protocol v2 to recover
full parallelism.
Also fix a leak in cleanupSem (#27253): cleanupSem used to snapshot
heldTokens and release them before killing the loop, while the loop's
in-flight acquire/release children could still be mutating it.
Cleanup now runs inside the loop's own exit handler, after draining
the active child via a new activeChild TVar, so the snapshot has no
concurrent mutator.
See also:
- GHC proposal amendment: https://github.com/ghc-proposals/ghc-proposals/pull/673
- cabal-install patch: https://github.com/haskell/cabal/pull/11628
- semaphore-compat MR: https://gitlab.haskell.org/ghc/semaphore-compat/-/merge_requests/8
Bump semaphore-compat submodule to 2.0.0
Fixes #25087 and #27253
- - - - -
bb4280c9 by Alan Zimmerman at 2026-06-01T21:11:56-04:00
EPA: Record semicolons in HsModifier
Ensure the semi colons are captured in the ParsedSource for code like
%True;; %False;
instance C D
It makes HsModifier (and hence HsModifierOf) LocatedA, so the semi
colons can be recorded as [TrailingAnn]
Also rename pprHsModifiers to pprLHsModifiers to match.
Closes #27294
- - - - -
c320215f by fendor at 2026-06-01T21:11:57-04:00
Revert prog003 acceptance
We thought the commit 286f1adff3e78d775ff325caff71d0cee25d710b fixed the
test, but due to changes to ghci, modules loaded during the GHCi
session, the test was actually no longer testing what it set out to do,
"fixing" the broken test.
As modules are added to the `interactive-session` home unit, the object code needs
to be compiled with `-this-unit-id interactive-session`, otherwise the
object code won't be used.
Once this has been fixed in the test, the test fails as expected again.
- - - - -
efc5841d by mangoiv at 2026-06-01T21:11:57-04:00
libraries/process: bump submodule to v1.6.29.0
This submodule bump resolves a segfault on macos 15.
Fixes #27144
- - - - -
98b1941f by mangoiv at 2026-06-01T21:11:57-04:00
libraries/unix: in submodule, don't pick branch 2.7
The 2.7 branch is outdated and the module has been advanced far beyond
it anyway, so remove that line.
- - - - -
c8471794 by Simon Peyton Jones at 2026-06-01T21:11:57-04:00
Trim the continuation in mkDupableContWithDmds
When there are no remaining argument demands, it means the application
is bottoming. In this case, we can trim the continuation to avoid the
panic that was observed in #27261.
See Note [Trimming the continuation for bottoming functions] in
GHC.Core.Opt.Simplify.Iteration.
- - - - -
f29d01cf by Cheng Shao at 2026-06-01T21:11:57-04:00
ghci: fix module name string lifetime in hs_hpc_module invocation
This patch makes hpcAddModule pass a properly malloced module name
string to hs_hpc_module, instead of using useAsCString which causes
use-after-free of module name string. Fixes #27297.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
a8b9093e by sheaf at 2026-06-01T21:11:57-04:00
Relax acceptance threshold for T10421
As seen in #27289, the 1% acceptance threshold for this text was
overly narrow, resulting in spurious test failures. This commit widens
the acceptance threshold to 2%. Fixes #27289.
- - - - -
f3fb85e2 by Luite Stegeman at 2026-06-01T21:11:57-04:00
Fixes for black holes
- suspend duplicate work for eager black holes
- detect eager black holes in checkBlockingQueues
- don't overwrite existing black holes even if they're not
in an eager blackhole frame
- don't deadlock on self when thunk is already blackholed
Fixes #26936
- - - - -
517ee508 by Tom McLaughlin at 2026-06-01T21:11:57-04:00
Event/Windows.hsc: rethrow exceptions in overlapped IO
This prevents the WinIO manager from swallowing exceptions in overlapped IO. It
was added to make WinIO support possible in the `network` library. See
https://gitlab.haskell.org/ghc/ghc/-/issues/27283.
We also bump __IO_MANAGER_WINIO__ to 2 so libraries can gate on this using CPP.
- - - - -
deb3584c by Wolfgang Jeltsch at 2026-06-01T21:11:57-04:00
Allow `downsweep` to use nodes of an existing module graph
To this end, `downsweep` has not been able to use the nodes of a module
graph obtained from a previous downsweeping round. In some GHC API
applications, downsweeping is performed somewhat incrementally and
therefore could profit from reusing such existing results. This
contribution makes this possible.
Resolves #27054.
Co-authored-by: Matthew Pickering <matthewtpickering(a)gmail.com>
- - - - -
72f9382f by Simon Jakobi at 2026-06-01T21:11:57-04:00
Add regression test for T11226
Closes #11226.
- - - - -
c44678f7 by Sven Tennie at 2026-06-01T21:11:57-04:00
Add optional config setting for LibDir (#19174)
Previously, the `libDir` was derived from `topDir`. This won't work for
inplace stage2 cross-compilers where binaries and libraries are in
different stage dirs (`_build/stage1/` for executables and
`_build/stage2` for libraries).
`LibDir` is set in the inplace `settings` files. For bindists, we
generate a new `settings` file with no `LibDir` entry. GHC then defaults
to use `topDir` as `libDir` again. This keeps the bindist relocatable.
If `LibDir` is a relative path, it is interpreted relatively to
`topDir`.
The global package db is part of the `lib/` folder. If we want to point
for inplace cross-compilers to the succeeding stage's folder, this is
done by setting `LibDir`. Thus, the global package db must be found
relative to `libDir`` (which may default to `topDir` or be set by
`LibDir`).
The complexity of settings becomes scary. So, add a test to ensure
`LibDir` works as expected.
- - - - -
66b7ff73 by Sven Tennie at 2026-06-01T21:11:57-04:00
Add Haddock to FileSettings
Helping to understand the fields' meanings without deeper analyses.
- - - - -
70e4fbce by Sylvain Henry at 2026-06-01T21:11:57-04:00
foundation test: skip signed minBound `quot` (-1) (#27222)
`minBound `quot` (-1)` for fixed-width signed integers is platform
dependent: the mathematical result -minBound is not representable in
the type. On x86, IDIV traps; LLVM's sdiv is undefined behaviour in
this case; on AArch64/RISC-V, SDIV wraps to minBound.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
8c274068 by Simon Jakobi at 2026-06-01T21:11:57-04:00
Prevent dictionary-passing in checkTyEqRhs
...by pre-specializing it to TcM.
Previously, wherever checkTyEqRhs was used in other modules, the
Core showed dictionary passing ($fMonadIOEnv). The added SPECIALIZE
pragma prevents this.
- - - - -
413d6ef7 by David Eichmann at 2026-06-01T21:11:57-04:00
Hadrian: create a ghc-internal .def file per ghc-internal dll
The .def file generated from rts/win32/libHSghc-internal.def.in contains
the name of the ghc-internal dll. The correct dll name differs based
on if the dll is inplace/final and if using the Dynamic way. Previously,
this was not accounted for and inconsistent dlls names where used. That
led to failure when loading dlls at runtime in experiments with windows
dynamic linking.
- - - - -
66f47558 by Sylvain Henry at 2026-06-01T21:11:57-04:00
ghc-bignum: copy backend interface haddocks to Native backend (#27305)
The haddock comments documenting the BigNat backend interface (function
contracts, expected MutableWordArray# sizes, return-value semantics, etc.)
were attached to the FFI backend module. Copy them to the Native backend
so they remain in tree once the FFI backend is removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
afc9e631 by Sylvain Henry at 2026-06-01T21:11:57-04:00
ghc-bignum: remove FFI backend (#27305)
The FFI backend of ghc-bignum (now part of ghc-internal) had no known
users and is easy to recreate by relinking ghc-internal with a custom
backend. Remove the backend module, the bignum-ffi cabal flag, and the
ffi option from Hadrian's --bignum selector. The backend interface
documentation now lives in the Native backend module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
2dcfd94f by Sylvain Henry at 2026-06-01T21:11:57-04:00
ghc-bignum: remove Check backend (#27305)
The Check backend of ghc-bignum (now part of ghc-internal) compared the
selected backend's output against the Native backend for validation.
It had no known users. Remove the backend module, the bignum-check
cabal flag, the bignumCheck Hadrian flavour field, and the check-
prefix in Hadrian's --bignum selector.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
c0b0e0c3 by David Eichmann at 2026-06-01T21:11:57-04:00
Add code comments to allocator code
- - - - -
fcb4cb3f by Matthew Pickering at 2026-06-01T21:11:58-04:00
hadrian: Refactor system-cxx-std-lib rules
I noticed a few things wrong with the hadrian rules for
`system-cxx-std-lib` rules.
* For `text` there is an ad-hoc check to depend on `system-cxx-std-lib`
outside of `configurePackage`.
* The `system-cxx-std-lib` dependency is not read from cabal files.
* Recache is not called on the packge database after the `.conf` file is
generated, a more natural place for this rule is `registerRules`.
Treating this uniformly like other packages is complicated by it not
having any source code or a cabal file. However we can do a bit better
by reporting the dependency firstly in `PackageData` and then needing
the `.conf` file in the same place as every other package in
`configurePackage`.
This commit increases the `shakeVersion`, to provide backwards
compatibility to previous builds with different PackageData.
Fixes #25303
Co-authored-by: Sven Tennie <sven.tennie(a)gmail.com>
- - - - -
44d09eb3 by Recursion Ninja at 2026-06-01T21:36:54-04:00
Decoupling 'L.H.S' from 'GHC.Types.SourceText'
* Migrated 'IntegralLit' to 'L.H.S.Lit'.
* Migrated 'FractionalLit' to 'L.H.S.Lit'.
* Migrated 'StringLiteral' to 'L.H.S.Lit'.
* Added TTG extension points to the types above.
* Added nice export list to 'GHC.Hs.Lit'.
* Added 'rnOverLitVal' and 'tcOverLitVal' functions to 'GHC.Hs.Lit'.
* Added instance 'Anno (StringLiteral (GhcPass p)) = SrcSpanAnnN'
* Moved [Notes] about 'SourceText' from 'L.H.S.*' to 'GHC.*'.
* Removed all references to 'SourceText' from 'L.H.S'.
* Removed the trailing comma record field from 'StringLiteral'
* Renamed exported functions for nomenclature consistency.
* Deprecated the renamed functions
Resolves issue #26953
- - - - -
176 changed files:
- .gitmodules
- + changelog.d/T27261
- + changelog.d/bump-process
- + changelog.d/fix-blackhole-handling
- + changelog.d/hadrian-system-cxx-std-lib-25303
- + changelog.d/jobserver-leak-fix
- + changelog.d/libdir-setting
- + changelog.d/module-graph-reuse-in-downsweep
- + changelog.d/remove-bignum-check-backend
- + changelog.d/remove-bignum-ffi-backend
- + changelog.d/semaphore-v2
- + changelog.d/wasm-fix-serviceworker
- + changelog.d/windows-rethrow-overlapped-exception
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Data/List/SetOps.hs
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/Types.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/SysTools/Cpp.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/PkgQual.hs
- compiler/GHC/Types/SourceText.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Binds/InlinePragma.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/stolen_syntax.rst
- docs/users_guide/using-warnings.rst
- docs/users_guide/using.rst
- hadrian/README.md
- hadrian/doc/user-settings.md
- hadrian/src/CommandLine.hs
- hadrian/src/Flavour.hs
- hadrian/src/Flavour/Type.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Packages.hs
- libraries/ghc-bignum/ghc-bignum.cabal
- + libraries/ghc-boot/GHC/Data/ShortByteString.hs
- libraries/ghc-boot/GHC/Settings/Utils.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghc-internal/bignum-backend.rst
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Check.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/FFI.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Selected.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc
- libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Run.hs
- libraries/process
- libraries/semaphore-compat
- rts/Messages.c
- rts/ThreadPaused.c
- rts/Threads.c
- rts/Updates.h
- rts/include/rts/storage/ClosureMacros.h
- rts/sm/BlockAlloc.c
- rts/sm/MBlock.c
- rts/win32/libHSghc-internal.def.in
- testsuite/tests/MiniQuickCheck.hs
- testsuite/tests/diagnostic-codes/codes.stdout
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/A.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/B.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/C.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/D.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/X.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/Y.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/Z.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.stdout
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/downsweep/all.T
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- + testsuite/tests/ghc-api/settings/LibDir.hs
- + testsuite/tests/ghc-api/settings/LibDir.stdout
- + testsuite/tests/ghc-api/settings/all.T
- testsuite/tests/ghci/prog003/prog003.T
- testsuite/tests/ghci/prog003/prog003.script
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/perf/should_run/T11226.hs
- + testsuite/tests/perf/should_run/T11226.stdout
- testsuite/tests/perf/should_run/all.T
- testsuite/tests/printer/Makefile
- testsuite/tests/printer/PprModifiers.hs
- + testsuite/tests/printer/Test27291.hs
- testsuite/tests/printer/all.T
- + testsuite/tests/simplCore/should_compile/T27261.hs
- + testsuite/tests/simplCore/should_compile/T27261_aux.hs
- testsuite/tests/simplCore/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/LexParseRn.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- utils/jsffi/prelude.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/08c2705f000360340804cdd6153be4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/08c2705f000360340804cdd6153be4…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/multi-caret] Add related locations to duplicate-declaration and duplicate-export errors
by Simon Jakobi (@sjakobi2) 02 Jun '26
by Simon Jakobi (@sjakobi2) 02 Jun '26
02 Jun '26
Simon Jakobi pushed to branch wip/sjakobi/multi-caret at Glasgow Haskell Compiler / GHC
Commits:
a1a2259b by Simon Jakobi at 2026-06-02T03:23:22+02:00
Add related locations to duplicate-declaration and duplicate-export errors
Attach diagnosticRelatedLocations (multi-caret) to:
* TcRnDuplicateDecls
* TcRnDuplicateExport
* TcRnDuplicateNamedDefaultExport
Enable -fdiagnostics-show-caret for the DuplicateExports and T25857
tests to exercise the new caret sections.
check_occs now threads LIE GhcPs so these export items can carry their
source spans. TcRnConflictingExports and TcRnDuplicateFieldExport were
also tried but reverted to IE GhcPs: their export items already appear
in the message text and name provenance is rendered too, so the carets
only duplicated the primary span.
Assisted-by: Claude Opus 4.8 <noreply(a)anthropic.com>
- - - - -
9 changed files:
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/Export.hs
- testsuite/tests/default/T25857.stderr
- testsuite/tests/default/all.T
- testsuite/tests/overloadedrecflds/should_fail/DuplicateExports.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/rename/should_fail/T7164.stderr
- testsuite/tests/rename/should_fail/all.T
Changes:
=====================================
compiler/GHC/Tc/Errors/Ppr.hs
=====================================
@@ -660,16 +660,16 @@ instance Diagnostic TcRnMessage where
$ formatExportItemError
(ppr export_item)
"attempts to export a default class declaration that is not visible here"
- TcRnDuplicateExport gre ie1 ie2
+ TcRnDuplicateExport gre lie1 lie2
-> mkSimpleDecorated $
hsep [ quotes (ppr $ greName gre)
- , text "is exported by", quotes (ppr ie1)
- , text "and", quotes (ppr ie2) ]
- TcRnDuplicateNamedDefaultExport nm ie1 ie2
- -> mkSimpleDecorated $
- hsep [ text "The named default declaration for" <+> quotes (ppr nm)
- , text "is exported by", quotes (ppr ie1)
- , text "and", quotes (ppr ie2) ]
+ , text "is exported by", quotes (ppr lie1)
+ , text "and", quotes (ppr lie2) ]
+ TcRnDuplicateNamedDefaultExport nm lie1 lie2
+ -> mkSimpleDecorated $
+ hsep [ text "The named default declaration for" <+> quotes (ppr nm)
+ , text "is exported by", quotes (ppr lie1)
+ , text "and", quotes (ppr lie2) ]
TcRnExportedParentChildMismatch parent_name ty_thing child parent_names
-> mkSimpleDecorated $
text "The type constructor" <+> quotes (ppr parent_name)
@@ -3464,6 +3464,12 @@ instance Diagnostic TcRnMessage where
-> diagnosticRelatedLocations msg'
TcRnBindingNameConflict _ locs
-> NE.tail locs
+ TcRnDuplicateDecls _ names
+ -> map nameSrcSpan (NE.init names)
+ TcRnDuplicateExport _ _lie1 lie2
+ -> [getLocA lie2]
+ TcRnDuplicateNamedDefaultExport _ _lie1 lie2
+ -> [getLocA lie2]
_ ->
[]
=====================================
compiler/GHC/Tc/Errors/Types.hs
=====================================
@@ -1607,14 +1607,14 @@ data TcRnMessage where
overloadedrecflds/should_fail/DuplicateExports
patsyn/should_compile/T11959
-}
- TcRnDuplicateExport :: GlobalRdrElt -> IE GhcPs -> IE GhcPs -> TcRnMessage
+ TcRnDuplicateExport :: GlobalRdrElt -> LIE GhcPs -> LIE GhcPs -> TcRnMessage
{-| TcRnDuplicateNamedDefaultExport is a warning (controlled by -Wduplicate-exports)
that occurs when a named default declaration appears in an export list
more than once.
-}
- TcRnDuplicateNamedDefaultExport :: TyCon -> IE GhcPs -> IE GhcPs -> TcRnMessage
+ TcRnDuplicateNamedDefaultExport :: TyCon -> LIE GhcPs -> LIE GhcPs -> TcRnMessage
{-| TcRnExportedParentChildMismatch is an error that occurs when an export is
bundled with a parent that it does not belong to
=====================================
compiler/GHC/Tc/Gen/Export.hs
=====================================
@@ -47,7 +47,7 @@ import GHC.Types.Id.Info
import GHC.Types.Name.Reader
import GHC.Types.Hint
-import Control.Arrow ( first )
+import Control.Arrow ( first, second )
import Control.Monad ( when )
import qualified Data.List.NonEmpty as NE
import Data.Traversable ( for )
@@ -142,7 +142,7 @@ data ExportAccum -- The type of the accumulating parameter of
= ExportAccum {
expacc_exp_occs :: ExportOccMap,
-- ^ Tracks exported occurrence names
- expacc_exp_dflts :: NameEnv (ClassDefaults, IE GhcPs),
+ expacc_exp_dflts :: NameEnv (ClassDefaults, LIE GhcPs),
-- ^ Tracks exported named default declarations
expacc_mods :: UniqMap ModuleName [Name],
-- ^ Tracks (re-)exported module names
@@ -186,7 +186,7 @@ accumExports f xs = do
where f' acc x
= fromMaybe (acc, Nothing) <$> attemptM (f acc x)
-type ExportOccMap = OccEnv (Name, IE GhcPs)
+type ExportOccMap = OccEnv (Name, LIE GhcPs)
-- Tracks what a particular exported OccName
-- in an export list refers to, and which item
-- it came from. It's illegal to export two distinct things
@@ -414,7 +414,7 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
; traceRn "efa" (ppr mod $$ ppr all_gres)
; addUsedGREs ExportDeprecationWarnings all_gres
- ; occs' <- check_occs occs ie new_gres
+ ; occs' <- check_occs occs (L loc ie) new_gres
-- This check_occs not only finds conflicts
-- between this item and others, but also
-- internally within this item. That is, if
@@ -484,7 +484,7 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
; traceRn "efa" (ppr mod $$ ppr all_gres)
; addUsedGREs ExportDeprecationWarnings all_gres
- ; occs' <- check_occs occs ie new_gres
+ ; occs' <- check_occs occs (L loc ie) new_gres
-- This check_occs not only finds conflicts
-- between this item and others, but also
-- internally within this item. That is, if
@@ -541,7 +541,7 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
name = greName gre
checkThLocalNameNoLift (ieLWrappedUserRdrName l name)
- occs' <- check_occs occs ie [gre]
+ occs' <- check_occs occs (L loc ie) [gre]
(export_warn_spans', dont_warn_export', warn_txt_rn)
<- process_warning export_warn_spans
dont_warn_export
@@ -579,14 +579,14 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
Just cls_dflts -> do
let cls = cd_class cls_dflts
case lookupNameEnv exp_dflts (className cls) of
- Just (_, ie') -> do
+ Just (_, lie') -> do
addDiagnostic $
- TcRnDuplicateNamedDefaultExport (classTyCon cls) ie ie'
+ TcRnDuplicateNamedDefaultExport (classTyCon cls) (L loc ie) lie'
return (Nothing, occs, exp_dflts)
Nothing ->
- return $ (Nothing, occs, extendNameEnv exp_dflts (className cls) (cls_dflts, ie))
+ return $ (Nothing, occs, extendNameEnv exp_dflts (className cls) (cls_dflts, L loc ie))
_ -> do
- occs' <- check_occs occs ie [gre]
+ occs' <- check_occs occs (L loc ie) [gre]
return (Just avail, occs', exp_dflts)
checkThLocalNameNoLift (ieLWrappedUserRdrName l name)
@@ -618,7 +618,7 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
all_names = map greName all_gres
checkThLocalNameNoLift (ieLWrappedUserRdrName l name)
- occs' <- check_occs occs ie all_gres
+ occs' <- check_occs occs (L loc ie) all_gres
(export_warn_spans', dont_warn_export', warn_txt_rn)
<- process_warning export_warn_spans
dont_warn_export
@@ -657,7 +657,7 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
all_names = map greName all_gres
checkThLocalNameNoLift (ieLWrappedUserRdrName l name)
- occs' <- check_occs occs ie all_gres
+ occs' <- check_occs occs (L loc ie) all_gres
(export_warn_spans', dont_warn_export', warn_txt_rn)
<- process_warning export_warn_spans
dont_warn_export
@@ -1044,12 +1044,13 @@ checkPatSynParent parent NoParent nm
-- | Insert the given 'GlobalRdrElt's into the 'ExportOccMap', checking that
-- each of the given 'GlobalRdrElt's does not appear multiple times in
-- the 'ExportOccMap', as per Note [Exporting duplicate declarations].
-check_occs :: ExportOccMap -> IE GhcPs -> [GlobalRdrElt] -> RnM ExportOccMap
-check_occs occs ie gres
+check_occs :: ExportOccMap -> LIE GhcPs -> [GlobalRdrElt] -> RnM ExportOccMap
+check_occs occs lie gres
-- 'gres' are the entities specified by 'ie'
= do { drf <- xoptM LangExt.DuplicateRecordFields
; foldlM (check drf) occs gres }
where
+ ie = unLoc lie
-- Check for distinct children exported with the same OccName (an error) or
-- for duplicate exports of the same child (a warning).
@@ -1067,20 +1068,21 @@ check_occs occs ie gres
| drf_enabled || not (isFieldOcc child_occ)
-> return occs'
| otherwise
- -> do { let flds = filter (\(_,ie') -> not $ dupFieldExport_ok ie ie')
+ -> do { let flds = filter (\(_,lie') -> not $ dupFieldExport_ok ie (unLoc lie'))
$ lookupFieldsOccEnv occs (occNameFS child_occ)
; case flds of { [] -> return occs'; clash1:clashes ->
- do { addDuplicateFieldExportErr (gre,ie) (clash1 NE.:| clashes)
+ do { addDuplicateFieldExportErr (gre, unLoc lie)
+ (fmap (second unLoc) (clash1 NE.:| clashes))
; return occs } } }
- Left (child', ie')
+ Left (child', lie')
| child == child' -- Duplicate export of a single Name: a warning.
- -> do { warnIf (not (dupExport_ok child ie ie')) (TcRnDuplicateExport gre ie ie')
+ -> do { warnIf (not (dupExport_ok child ie (unLoc lie'))) (TcRnDuplicateExport gre lie lie')
; return occs }
| otherwise -- Same OccName but different Name: an error.
-> do { global_env <- getGlobalRdrEnv
- ; addErr (exportClashErr global_env child' child ie' ie)
+ ; addErr (exportClashErr global_env child' child (unLoc lie') (unLoc lie))
; return occs }
where
child = greName gre
@@ -1088,10 +1090,10 @@ check_occs occs ie gres
-- Try to insert a child into the map, returning Left if there is something
-- already exported with the same OccName.
- try_insert :: ExportOccMap -> GlobalRdrElt -> Either (Name, IE GhcPs) ExportOccMap
+ try_insert :: ExportOccMap -> GlobalRdrElt -> Either (Name, LIE GhcPs) ExportOccMap
try_insert occs child
= case lookupOccEnv occs occ of
- Nothing -> Right (extendOccEnv occs occ (greName child, ie))
+ Nothing -> Right (extendOccEnv occs occ (greName child, lie))
Just x -> Left x
where
occ = greOccName child
=====================================
testsuite/tests/default/T25857.stderr
=====================================
@@ -1,3 +1,9 @@
T25857.hs:4:33: warning: [GHC-31584] [-Wduplicate-exports (in -Wdefault)]
The named default declaration for ‘IsString’ is exported by ‘default IsString’ and ‘default IsString’
+ |
+4 | IsString, default IsString, default IsString
+ | ^^^^^^^^^^^^^^^^
+ |
+4 | IsString, default IsString, default IsString
+ | ^^^^^^^^^^^^^^^^
=====================================
testsuite/tests/default/all.T
=====================================
@@ -32,7 +32,7 @@ test('default-fail07', normal, compile_fail, [''])
test('default-fail08', normal, compile_fail, [''])
test('T25775', normal, compile_fail, [''])
test('T25825', normal, compile, [''])
-test('T25857', normal, compile, [''])
+test('T25857', normal, compile, ['-fdiagnostics-show-caret'])
test('T25206', [extra_files(['T25206_helper.hs'])], multimod_compile, ['T25206', ''])
test('T25858', normal, compile_and_run, [''])
test('T25858v1', [extra_files(['T25858v1_helper.hs'])], multimod_compile_and_run, ['T25858v1', ''])
=====================================
testsuite/tests/overloadedrecflds/should_fail/DuplicateExports.stderr
=====================================
@@ -1,3 +1,9 @@
-
DuplicateExports.hs:6:29: error: [GHC-47854] [-Wduplicate-exports (in -Wdefault), Werror=duplicate-exports]
‘foo’ is exported by ‘foo’ and ‘T(foo, bar)’
+ |
+6 | module Export (T(foo, bar), foo, S(bar)) where
+ | ^^^^^^^^^^^
+ |
+6 | module Export (T(foo, bar), foo, S(bar)) where
+ | ^^^
+
=====================================
testsuite/tests/overloadedrecflds/should_fail/all.T
=====================================
@@ -35,7 +35,7 @@ test('T14953', [extra_files(['T14953_A.hs', 'T14953_B.hs'])],
multimod_compile_fail, ['T14953', ''])
test('T26480', extra_files(['T26480_aux1.hs', 'T26480_aux2.hs']), multimod_compile_fail, ['T26480', '-v0'])
test('T26480b', normal, compile_fail, [''])
-test('DuplicateExports', normal, compile_fail, [''])
+test('DuplicateExports', normal, compile_fail, ['-fdiagnostics-show-caret'])
test('T17420', [extra_files(['T17420A.hs'])], multimod_compile_fail,
['T17420', ''])
test('T17469', [extra_files(['T17469A.hs'])], multimod_compile_fail,
=====================================
testsuite/tests/rename/should_fail/T7164.stderr
=====================================
@@ -1,5 +1,11 @@
-
-T7164.hs:8:1: [GHC-29916]
+T7164.hs:8:1: error: [GHC-29916]
Multiple declarations of ‘derp’
Declared at: T7164.hs:5:5
T7164.hs:8:1
+ |
+5 | derp :: m a
+ | ^^^^^^^^^^^
+ |
+8 | derp = 123
+ | ^^^^
+
=====================================
testsuite/tests/rename/should_fail/all.T
=====================================
@@ -91,7 +91,7 @@ test('T6148a', normal, compile_fail, [''])
test('T6148b', normal, compile_fail, [''])
test('T6148c', normal, compile_fail, [''])
test('T6148d', normal, compile_fail, [''])
-test('T7164', normal, compile_fail, [''])
+test('T7164', normal, compile_fail, ['-fdiagnostics-show-caret'])
test('T7338', normal, compile_fail, [''])
test('T7338a', normal, compile_fail, [''])
test('T7454', normal, compile, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a1a2259b9a4cab30faa471a2060cb9a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a1a2259b9a4cab30faa471a2060cb9a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/multi-caret] 30 commits: Implement List.elem via foldr
by Simon Jakobi (@sjakobi2) 02 Jun '26
by Simon Jakobi (@sjakobi2) 02 Jun '26
02 Jun '26
Simon Jakobi pushed to branch wip/sjakobi/multi-caret at Glasgow Haskell Compiler / GHC
Commits:
72c8de5c by Simon Jakobi at 2026-05-23T18:41:42-04:00
Implement List.elem via foldr
...in order to allow specialization to Eq instances.
The implementation of notElem is updated for consistency.`
Corresponding CLC proposal:
https://github.com/haskell/core-libraries-committee/issues/412
Addresses #27096.
- - - - -
3268c610 by Alan Zimmerman at 2026-05-23T18:42:30-04:00
EPA: Fix span for qualified multiline string
Fix the span for a qualified multiline string like
Text."""
I'm a multiline
Text value
!
"""
to extend to the end of the entire string, not just the first line.
Closes #27274
- - - - -
1f096790 by Alan Zimmerman at 2026-05-23T18:43:20-04:00
EPA: Fix exact printing namespace-specified wildcards
Ensures correct printing of imports of the form
import Data.Bool (data True(data ..))
import Data.Bool (data True(type ..))
Closes #27291
- - - - -
56ada7c0 by Mrjtjmn at 2026-05-23T18:44:19-04:00
Fix ambiguous syntax of BangPatterns in users guide
Update documentation for the BangPatterns extension to specify
how surrounding whitespace affects interpretation of `!`.
* Only when there is whitespace before `!` and no whitespace after,
it is recognized as a BangPattern.
* Other cases `⟨varid⟩!⟨varid⟩`, `⟨varid⟩ ! ⟨varid⟩`, `⟨varid⟩! ⟨varid⟩`
are treated as infix operators.
- - - - -
579aa0b7 by Simon Jakobi at 2026-05-25T16:31:26-04:00
Ensure that SetOps.{minusList,unionListsOrd} can be specialized
...by marking them INLINABLE. Haddock allocates 0.1–0.3% less as a
result.
This also removes some redundant constraints on unionListsOrd.
- - - - -
cccf45da by Cheng Shao at 2026-05-25T16:32:13-04:00
wasm: ensure post-linker output is synchronous ESM
This patch fixes wasm backend's post-linker output script to ensure
it's synchronous ESM and doesn't use top-level await, which doesn't
work in ServiceWorkers. Fixes #27257.
- - - - -
8db331a3 by Zubin Duggal at 2026-05-26T04:54:03-04:00
Update to semaphore-compat 2.0.0 using v2 of the protocol
On Linux and other POSIX platforms, GHC's -jsem jobserver client now
speaks v2 of the semaphore-compat protocol, which uses Unix domain
sockets in place of POSIX named semaphores. This avoids the libc-ABI
issues that affected the old implementation. Windows is unaffected
and continues to use the v1 protocol (Win32 named semaphores); its
reported protocol version remains v1.
When GHC receives a -jsem name whose protocol version it does not
support, it emits a -Wsemaphore-version-mismatch warning and falls
back to -j<N> rather than crashing. ghc --info exposes the supported
version in a new "Semaphore version" entry so cabal-install can detect
a mismatch before invoking GHC.
Users on a cabal-install that predates the v2 update will continue to
build successfully on Linux/POSIX, but will lose the cross-process
-jsem coordination and fall back to -j<N> per GHC invocation. Users
must upgrade to a cabal-install that supports protocol v2 to recover
full parallelism.
Also fix a leak in cleanupSem (#27253): cleanupSem used to snapshot
heldTokens and release them before killing the loop, while the loop's
in-flight acquire/release children could still be mutating it.
Cleanup now runs inside the loop's own exit handler, after draining
the active child via a new activeChild TVar, so the snapshot has no
concurrent mutator.
See also:
- GHC proposal amendment: https://github.com/ghc-proposals/ghc-proposals/pull/673
- cabal-install patch: https://github.com/haskell/cabal/pull/11628
- semaphore-compat MR: https://gitlab.haskell.org/ghc/semaphore-compat/-/merge_requests/8
Bump semaphore-compat submodule to 2.0.0
Fixes #25087 and #27253
- - - - -
17be4f1f by Alan Zimmerman at 2026-05-26T04:54:52-04:00
EPA: Record semicolons in HsModifier
Ensure the semi colons are captured in the ParsedSource for code like
%True;; %False;
instance C D
It makes HsModifier (and hence HsModifierOf) LocatedA, so the semi
colons can be recorded as [TrailingAnn]
Also rename pprHsModifiers to pprLHsModifiers to match.
Closes #27294
- - - - -
8f991755 by fendor at 2026-05-26T11:02:52-04:00
Revert prog003 acceptance
We thought the commit 286f1adff3e78d775ff325caff71d0cee25d710b fixed the
test, but due to changes to ghci, modules loaded during the GHCi
session, the test was actually no longer testing what it set out to do,
"fixing" the broken test.
As modules are added to the `interactive-session` home unit, the object code needs
to be compiled with `-this-unit-id interactive-session`, otherwise the
object code won't be used.
Once this has been fixed in the test, the test fails as expected again.
- - - - -
277a3687 by mangoiv at 2026-05-26T11:03:40-04:00
libraries/process: bump submodule to v1.6.29.0
This submodule bump resolves a segfault on macos 15.
Fixes #27144
- - - - -
6779bb0c by mangoiv at 2026-05-26T11:03:40-04:00
libraries/unix: in submodule, don't pick branch 2.7
The 2.7 branch is outdated and the module has been advanced far beyond
it anyway, so remove that line.
- - - - -
4a645683 by Simon Peyton Jones at 2026-05-27T21:41:59-04:00
Trim the continuation in mkDupableContWithDmds
When there are no remaining argument demands, it means the application
is bottoming. In this case, we can trim the continuation to avoid the
panic that was observed in #27261.
See Note [Trimming the continuation for bottoming functions] in
GHC.Core.Opt.Simplify.Iteration.
- - - - -
8ab506ff by Cheng Shao at 2026-05-27T21:42:47-04:00
ghci: fix module name string lifetime in hs_hpc_module invocation
This patch makes hpcAddModule pass a properly malloced module name
string to hs_hpc_module, instead of using useAsCString which causes
use-after-free of module name string. Fixes #27297.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
b0233814 by sheaf at 2026-05-27T21:43:31-04:00
Relax acceptance threshold for T10421
As seen in #27289, the 1% acceptance threshold for this text was
overly narrow, resulting in spurious test failures. This commit widens
the acceptance threshold to 2%. Fixes #27289.
- - - - -
63ce5770 by Luite Stegeman at 2026-05-28T12:23:35-04:00
Fixes for black holes
- suspend duplicate work for eager black holes
- detect eager black holes in checkBlockingQueues
- don't overwrite existing black holes even if they're not
in an eager blackhole frame
- don't deadlock on self when thunk is already blackholed
Fixes #26936
- - - - -
037a80dc by Tom McLaughlin at 2026-05-28T12:24:36-04:00
Event/Windows.hsc: rethrow exceptions in overlapped IO
This prevents the WinIO manager from swallowing exceptions in overlapped IO. It
was added to make WinIO support possible in the `network` library. See
https://gitlab.haskell.org/ghc/ghc/-/issues/27283.
We also bump __IO_MANAGER_WINIO__ to 2 so libraries can gate on this using CPP.
- - - - -
2d53bcdb by Wolfgang Jeltsch at 2026-05-28T12:25:21-04:00
Allow `downsweep` to use nodes of an existing module graph
To this end, `downsweep` has not been able to use the nodes of a module
graph obtained from a previous downsweeping round. In some GHC API
applications, downsweeping is performed somewhat incrementally and
therefore could profit from reusing such existing results. This
contribution makes this possible.
Resolves #27054.
Co-authored-by: Matthew Pickering <matthewtpickering(a)gmail.com>
- - - - -
f4fbb583 by Simon Jakobi at 2026-05-28T12:26:04-04:00
Add regression test for T11226
Closes #11226.
- - - - -
ed29a5e6 by Sven Tennie at 2026-05-28T17:30:36-04:00
Add optional config setting for LibDir (#19174)
Previously, the `libDir` was derived from `topDir`. This won't work for
inplace stage2 cross-compilers where binaries and libraries are in
different stage dirs (`_build/stage1/` for executables and
`_build/stage2` for libraries).
`LibDir` is set in the inplace `settings` files. For bindists, we
generate a new `settings` file with no `LibDir` entry. GHC then defaults
to use `topDir` as `libDir` again. This keeps the bindist relocatable.
If `LibDir` is a relative path, it is interpreted relatively to
`topDir`.
The global package db is part of the `lib/` folder. If we want to point
for inplace cross-compilers to the succeeding stage's folder, this is
done by setting `LibDir`. Thus, the global package db must be found
relative to `libDir`` (which may default to `topDir` or be set by
`LibDir`).
The complexity of settings becomes scary. So, add a test to ensure
`LibDir` works as expected.
- - - - -
8339cf8f by Sven Tennie at 2026-05-28T17:30:36-04:00
Add Haddock to FileSettings
Helping to understand the fields' meanings without deeper analyses.
- - - - -
4ce251e4 by Sylvain Henry at 2026-05-28T17:31:39-04:00
foundation test: skip signed minBound `quot` (-1) (#27222)
`minBound `quot` (-1)` for fixed-width signed integers is platform
dependent: the mathematical result -minBound is not representable in
the type. On x86, IDIV traps; LLVM's sdiv is undefined behaviour in
this case; on AArch64/RISC-V, SDIV wraps to minBound.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
b8ba7e61 by Simon Jakobi at 2026-05-28T17:32:23-04:00
Prevent dictionary-passing in checkTyEqRhs
...by pre-specializing it to TcM.
Previously, wherever checkTyEqRhs was used in other modules, the
Core showed dictionary passing ($fMonadIOEnv). The added SPECIALIZE
pragma prevents this.
- - - - -
d603477f by David Eichmann at 2026-05-29T13:17:12-04:00
Hadrian: create a ghc-internal .def file per ghc-internal dll
The .def file generated from rts/win32/libHSghc-internal.def.in contains
the name of the ghc-internal dll. The correct dll name differs based
on if the dll is inplace/final and if using the Dynamic way. Previously,
this was not accounted for and inconsistent dlls names where used. That
led to failure when loading dlls at runtime in experiments with windows
dynamic linking.
- - - - -
1fc21753 by Sylvain Henry at 2026-05-29T13:18:14-04:00
ghc-bignum: copy backend interface haddocks to Native backend (#27305)
The haddock comments documenting the BigNat backend interface (function
contracts, expected MutableWordArray# sizes, return-value semantics, etc.)
were attached to the FFI backend module. Copy them to the Native backend
so they remain in tree once the FFI backend is removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
717059df by Sylvain Henry at 2026-05-29T13:18:14-04:00
ghc-bignum: remove FFI backend (#27305)
The FFI backend of ghc-bignum (now part of ghc-internal) had no known
users and is easy to recreate by relinking ghc-internal with a custom
backend. Remove the backend module, the bignum-ffi cabal flag, and the
ffi option from Hadrian's --bignum selector. The backend interface
documentation now lives in the Native backend module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
4bb3b1d8 by Sylvain Henry at 2026-05-29T13:18:14-04:00
ghc-bignum: remove Check backend (#27305)
The Check backend of ghc-bignum (now part of ghc-internal) compared the
selected backend's output against the Native backend for validation.
It had no known users. Remove the backend module, the bignum-check
cabal flag, the bignumCheck Hadrian flavour field, and the check-
prefix in Hadrian's --bignum selector.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
6b3044a0 by David Eichmann at 2026-05-30T11:58:48-04:00
Add code comments to allocator code
- - - - -
f4e04210 by Matthew Pickering at 2026-05-30T11:59:34-04:00
hadrian: Refactor system-cxx-std-lib rules
I noticed a few things wrong with the hadrian rules for
`system-cxx-std-lib` rules.
* For `text` there is an ad-hoc check to depend on `system-cxx-std-lib`
outside of `configurePackage`.
* The `system-cxx-std-lib` dependency is not read from cabal files.
* Recache is not called on the packge database after the `.conf` file is
generated, a more natural place for this rule is `registerRules`.
Treating this uniformly like other packages is complicated by it not
having any source code or a cabal file. However we can do a bit better
by reporting the dependency firstly in `PackageData` and then needing
the `.conf` file in the same place as every other package in
`configurePackage`.
This commit increases the `shakeVersion`, to provide backwards
compatibility to previous builds with different PackageData.
Fixes #25303
Co-authored-by: Sven Tennie <sven.tennie(a)gmail.com>
- - - - -
b335fbdc by Simon Jakobi at 2026-06-02T01:01:21+02:00
Add support for related locations in Diagnostic
* Convert TcRnBindingNameConflict to demonstrate this feature.
* Enable -fdiagnostics-show-caret in some tests to show what error
messages with multiple caret sections look like.
* Carry diagnostic related spans through MessageClass.
This prepares the ground for #22637. The diagnosticRelatedLocations
name is inspired by #23414.
- - - - -
335251cc by Simon Jakobi at 2026-06-02T01:08:39+02:00
Add related locations to duplicate-declaration and duplicate-export errors
Attach diagnosticRelatedLocations (multi-caret) to:
* TcRnDuplicateDecls
* TcRnDuplicateExport
* TcRnDuplicateNamedDefaultExport
Enable -fdiagnostics-show-caret for the DuplicateExports and T25857
tests to exercise the new caret sections.
check_occs now threads LIE GhcPs so these export items can carry their
source spans. TcRnConflictingExports and TcRnDuplicateFieldExport were
also tried but reverted to IE GhcPs: their export items already appear
in the message text and name provenance is rendered too, so the carets
only duplicated the primary span.
Assisted-by: Claude Opus 4.8 <noreply(a)anthropic.com>
- - - - -
172 changed files:
- .gitmodules
- + changelog.d/T27261
- + changelog.d/bump-process
- + changelog.d/elem-via-foldr-27096
- + changelog.d/fix-blackhole-handling
- + changelog.d/hadrian-system-cxx-std-lib-25303
- + changelog.d/jobserver-leak-fix
- + changelog.d/libdir-setting
- + changelog.d/module-graph-reuse-in-downsweep
- + changelog.d/remove-bignum-check-backend
- + changelog.d/remove-bignum-ffi-backend
- + changelog.d/semaphore-v2
- + changelog.d/wasm-fix-serviceworker
- + changelog.d/windows-rethrow-overlapped-exception
- compiler/GHC/Core/Opt/Monad.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Data/List/SetOps.hs
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Errors.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/Types.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/SysTools/Cpp.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error.hs
- compiler/GHC/Types/Error.hs-boot
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Utils/Error.hs
- compiler/GHC/Utils/Logger.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/stolen_syntax.rst
- docs/users_guide/using-warnings.rst
- docs/users_guide/using.rst
- ghc/GHCi/UI.hs
- hadrian/README.md
- hadrian/doc/user-settings.md
- hadrian/src/CommandLine.hs
- hadrian/src/Flavour.hs
- hadrian/src/Flavour/Type.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Packages.hs
- libraries/base/changelog.md
- libraries/base/tests/perf/ElemNoFusion_O1.stderr
- libraries/base/tests/perf/ElemNoFusion_O2.stderr
- libraries/ghc-bignum/ghc-bignum.cabal
- + libraries/ghc-boot/GHC/Data/ShortByteString.hs
- libraries/ghc-boot/GHC/Settings/Utils.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghc-internal/bignum-backend.rst
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Check.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/FFI.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Selected.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc
- libraries/ghc-internal/src/GHC/Internal/List.hs
- libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Run.hs
- libraries/process
- libraries/semaphore-compat
- rts/Messages.c
- rts/ThreadPaused.c
- rts/Threads.c
- rts/Updates.h
- rts/include/rts/storage/ClosureMacros.h
- rts/sm/BlockAlloc.c
- rts/sm/MBlock.c
- rts/win32/libHSghc-internal.def.in
- testsuite/tests/MiniQuickCheck.hs
- testsuite/tests/default/T25857.stderr
- testsuite/tests/default/all.T
- testsuite/tests/diagnostic-codes/codes.stdout
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/A.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/B.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/C.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/D.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/X.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/Y.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.modules/Z.hs
- + testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.stdout
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/downsweep/all.T
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- + testsuite/tests/ghc-api/settings/LibDir.hs
- + testsuite/tests/ghc-api/settings/LibDir.stdout
- + testsuite/tests/ghc-api/settings/all.T
- testsuite/tests/ghci/prog003/prog003.T
- testsuite/tests/ghci/prog003/prog003.script
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/overloadedrecflds/should_fail/DuplicateExports.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/patsyn/should_fail/T14114.stderr
- testsuite/tests/patsyn/should_fail/all.T
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/perf/should_run/T11226.hs
- + testsuite/tests/perf/should_run/T11226.stdout
- testsuite/tests/perf/should_run/all.T
- testsuite/tests/printer/Makefile
- testsuite/tests/printer/PprModifiers.hs
- + testsuite/tests/printer/PprQualifiedStrings.hs
- + testsuite/tests/printer/Test27291.hs
- testsuite/tests/printer/all.T
- testsuite/tests/rename/should_fail/T7164.stderr
- testsuite/tests/rename/should_fail/all.T
- testsuite/tests/rename/should_fail/rnfail004.stderr
- + testsuite/tests/simplCore/should_compile/T27261.hs
- + testsuite/tests/simplCore/should_compile/T27261_aux.hs
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_fail/tcfail038.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- utils/jsffi/prelude.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1f7ffaaadaa800daf07c937c690140…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1f7ffaaadaa800daf07c937c690140…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fix-26953] Decoupling 'L.H.S' from 'GHC.Types.SourceText'
by recursion-ninja (@recursion-ninja) 02 Jun '26
by recursion-ninja (@recursion-ninja) 02 Jun '26
02 Jun '26
recursion-ninja pushed to branch wip/fix-26953 at Glasgow Haskell Compiler / GHC
Commits:
08c2705f by Recursion Ninja at 2026-06-01T18:09:56-04:00
Decoupling 'L.H.S' from 'GHC.Types.SourceText'
* Migrated 'IntegralLit' to 'L.H.S.Lit'.
* Migrated 'FractionalLit' to 'L.H.S.Lit'.
* Migrated 'StringLiteral' to 'L.H.S.Lit'.
* Added TTG extension points to the types above.
* Added nice export list to 'GHC.Hs.Lit'.
* Added 'rnOverLitVal' and 'tcOverLitVal' functions to 'GHC.Hs.Lit'.
* Added instance 'Anno (StringLiteral (GhcPass p)) = SrcSpanAnnN'
* Moved [Notes] about 'SourceText' from 'L.H.S.*' to 'GHC.*'.
* Removed all references to 'SourceText' from 'L.H.S'.
* Removed the trailing comma record field from 'StringLiteral'
* Renamed exported functions for nomenclature consistency.
* Deprecated the renamed functions
Resolves issue #26953
- - - - -
52 changed files:
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/PkgQual.hs
- compiler/GHC/Types/SourceText.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Binds/InlinePragma.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Interface/LexParseRn.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/08c2705f000360340804cdd6153be42…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/08c2705f000360340804cdd6153be42…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/dcoutts/idle-gc-rewrite2
by Duncan Coutts (@dcoutts) 01 Jun '26
by Duncan Coutts (@dcoutts) 01 Jun '26
01 Jun '26
Duncan Coutts pushed new branch wip/dcoutts/idle-gc-rewrite2 at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/dcoutts/idle-gc-rewrite2
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T25450-print-cpu] Add --print-enabled-cpu-features flag
by Simon Jakobi (@sjakobi2) 01 Jun '26
by Simon Jakobi (@sjakobi2) 01 Jun '26
01 Jun '26
Simon Jakobi pushed to branch wip/sjakobi/T25450-print-cpu at Glasgow Haskell Compiler / GHC
Commits:
d177606f by Simon Jakobi at 2026-06-01T22:51:53+02:00
Add --print-enabled-cpu-features flag
GHC now supports a new mode flag --print-enabled-cpu-features, which
prints a JSON object describing the CPU features currently enabled for
code generation, together with a set of -m... flags that reproduce the
effective feature set for the current target. Dynamic options such as
-mavx2 and -mbmi2 are respected.
$ ghc -mavx2 --print-enabled-cpu-features
{"tag":"enabled-cpu-features","version":1,"target":"x86_64-linux-gnu",
"features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],
"as_m_flags":["-mavx2"]}
The primary purpose of this flag is for testing the -march=native option
(#25450).
Assisted-by: Claude Opus 4.8 <noreply(a)anthropic.com>
- - - - -
14 changed files:
- + changelog.d/print-enabled-cpu-features
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Session.hs
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Lint.hs
- ghc/GHC/Driver/Session/Mode.hs
- ghc/Main.hs
- testsuite/tests/driver/all.T
- + testsuite/tests/driver/print_enabled_cpu_features.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_avx2.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_avx512.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_bmi2.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_fma.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_unknown_flag.stderr
Changes:
=====================================
changelog.d/print-enabled-cpu-features
=====================================
@@ -0,0 +1,16 @@
+section: compiler
+synopsis: Add --print-enabled-cpu-features flag
+issues: #25450
+mrs: !16117
+
+description:
+ GHC now supports a new mode flag ``--print-enabled-cpu-features``, which
+ prints a JSON object describing the CPU features currently enabled for code
+ generation, together with a set of ``-m...`` flags that reproduce the
+ effective feature set for the current target.
+ Dynamic options such as ``-mavx2`` and ``-mbmi2`` are respected. ::
+
+ $ ghc -mavx2 --print-enabled-cpu-features
+ {"tag":"enabled-cpu-features","version":1,"target":"x86_64-linux-gnu",
+ "features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],
+ "as_m_flags":["-mavx2"]}
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -1615,6 +1615,7 @@ initPromotionTickContext dflags =
-- -----------------------------------------------------------------------------
-- SSE, AVX, FMA
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
isSse3Enabled :: DynFlags -> Bool
isSse3Enabled dflags = sseAvxVersion dflags >= Just SSE3 || isAvxEnabled dflags
@@ -1705,11 +1706,14 @@ We handle this as follows:
-- -----------------------------------------------------------------------------
-- LA664
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
+
isLa664Enabled :: DynFlags -> Bool
isLa664Enabled dflags = la664 dflags
-- -----------------------------------------------------------------------------
-- BMI2
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
isBmiEnabled :: DynFlags -> Bool
isBmiEnabled dflags = case platformArch (targetPlatform dflags) of
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -196,6 +196,8 @@ module GHC.Driver.Session (
-- * Compiler configuration suitable for display to the user
compilerInfo,
+ showEnabledCpuFeatures,
+ enabledCpuFeatures,
targetHasRTSWays,
@@ -277,6 +279,7 @@ import GHC.Utils.TmpFs
import GHC.Utils.Fingerprint
import GHC.Utils.Outputable
import GHC.Utils.Error (emptyDiagOpts, logInfo)
+import GHC.Utils.Json
import GHC.Settings
import GHC.CmmToAsm.CFG.Weight
import GHC.Core.Opt.CallerCC
@@ -3677,6 +3680,132 @@ compilerInfo dflags
queryCmdMaybe p f = expandDirectories (query (maybe "" (prgPath . p) . f))
queryFlagsMaybe p f = query (maybe "" (unwords . map escapeArg . prgFlags . p) . f)
+showEnabledCpuFeatures :: DynFlags -> String
+showEnabledCpuFeatures dflags = showSDocUnsafe $ renderJSON $ JSObject
+ [ ("tag", JSString "enabled-cpu-features")
+ -- Schema version of this JSON object; bump it whenever the shape or
+ -- meaning of the fields changes, so consumers can detect incompatibility.
+ , ("version", JSInt 1)
+ , ("target", JSString (platformMisc_targetPlatformString (platformMisc dflags)))
+ , ("features", JSArray (map JSString features))
+ -- A set of `-m...` flags that, passed to GHC for this target, reproduce
+ -- the effective feature set above. Note this need not be the flags the
+ -- user actually passed: implied features are folded in, and a feature
+ -- enabled by default may be reproduced by the empty set.
+ , ("as_m_flags", JSArray (map JSString asMFlags))
+ ]
+ where
+ (features, asMFlags) = enabledCpuFeatures dflags
+
+{- Note [Keeping enabledCpuFeatures in sync]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+`enabledCpuFeatures` must be updated whenever a new CPU feature flag is added
+to GHC. The three places to touch are, all in GHC.Driver.DynFlags:
+
+ 1. The flag registration (e.g. `make_ord_flag defGhcFlag "mnewfeat" ...`)
+ 2. The corresponding `is*Enabled` predicate
+ 3. The `enabledCpuFeatures` function below — add the feature to `features`
+ and, if it has a GHC `-m...` flag, to `as_m_flags` via the appropriate
+ architecture branch.
+
+See Note [Implications between X86 CPU feature flags] in GHC.Driver.DynFlags
+for the implication structure that `x86FeaturesAndFlags` and `x86AsMFlags`
+must respect.
+-}
+
+enabledCpuFeatures :: DynFlags -> ([String], [String])
+enabledCpuFeatures dflags = case platformArch (targetPlatform dflags) of
+ ArchX86_64 -> x86FeaturesAndFlags dflags
+ ArchX86 -> x86FeaturesAndFlags dflags
+ ArchLoongArch64 ->
+ ( fmaFeature ++ [ "LA664" | isLa664Enabled dflags ]
+ , fmaFlag ++ [ "-mla664" | isLa664Enabled dflags ]
+ )
+ _ -> (fmaFeature, fmaFlag)
+ where
+ -- `-mfma` is a cross-platform flag. On x86 it is folded into the
+ -- SSE/AVX hierarchy (handled in x86FeaturesAndFlags); on every other
+ -- architecture FMA stands on its own and gates FMA codegen via
+ -- isFmaEnabled in stgToCmmAllowFMAInstr. `fma dflags` is the source of
+ -- truth (it defaults to True on AArch64).
+ fmaFeature = [ "FMA" | fma dflags ]
+ fmaFlag = [ "-mfma" | fma dflags ]
+
+x86FeaturesAndFlags :: DynFlags -> ([String], [String])
+x86FeaturesAndFlags dflags =
+ -- SSE/SSE2 are determined by the target platform rather than a dynamic
+ -- flag, hence those predicates take Platform while the others take DynFlags.
+ ( [ "SSE" | isSseEnabled platform ]
+ ++ [ "SSE2" | isSse2Enabled platform ]
+ ++ [ "SSE3" | isSse3Enabled dflags ]
+ ++ [ "SSSE3" | isSsse3Enabled dflags ]
+ ++ [ "SSE4.1" | isSse4_1Enabled dflags ]
+ ++ [ "SSE4.2" | isSse4_2Enabled dflags ]
+ ++ [ "AVX" | isAvxEnabled dflags ]
+ ++ [ "AVX2" | isAvx2Enabled dflags ]
+ ++ [ "AVX512F" | isAvx512fEnabled dflags ]
+ ++ [ "AVX512BW" | isAvx512bwEnabled dflags ]
+ ++ [ "AVX512CD" | isAvx512cdEnabled dflags ]
+ ++ [ "AVX512DQ" | isAvx512dqEnabled dflags ]
+ ++ [ "AVX512ER" | isAvx512erEnabled dflags ]
+ ++ [ "AVX512PF" | isAvx512pfEnabled dflags ]
+ ++ [ "AVX512VL" | isAvx512vlEnabled dflags ]
+ ++ [ "BMI1" | isBmiEnabled dflags ]
+ ++ [ "BMI2" | isBmi2Enabled dflags ]
+ ++ [ "FMA" | isFmaEnabled dflags ]
+ ++ [ "GFNI" | isGfniEnabled dflags ]
+ , x86AsMFlags dflags
+ )
+ where
+ platform = targetPlatform dflags
+
+x86AsMFlags :: DynFlags -> [String]
+x86AsMFlags dflags =
+ avx512Flags
+ ++ vectorFlags
+ ++ bmiFlags
+ ++ fmaFlags
+ ++ gfniFlags
+ where
+ avx512Extensions =
+ [ ("-mavx512bw", avx512bw dflags)
+ , ("-mavx512cd", avx512cd dflags)
+ , ("-mavx512dq", avx512dq dflags)
+ , ("-mavx512er", avx512er dflags)
+ , ("-mavx512pf", avx512pf dflags)
+ , ("-mavx512vl", avx512vl dflags)
+ ]
+
+ hasAvx512Extension = any snd avx512Extensions
+ hasAvx512 = avx512f dflags || hasAvx512Extension
+
+ avx512Flags =
+ [ "-mavx512f" | avx512f dflags && not hasAvx512Extension ]
+ ++ [ flag | (flag, True) <- avx512Extensions ]
+
+ vectorFlags
+ | hasAvx512 = []
+ | otherwise =
+ case sseAvxVersion dflags of
+ Just AVX2 -> ["-mavx2"]
+ Just AVX1 -> ["-mavx"]
+ Just SSE42 -> ["-msse4.2"]
+ Just SSE4 -> ["-msse4"]
+ Just SSSE3 -> ["-mssse3"]
+ Just SSE3 -> ["-msse3"]
+ _ -> []
+
+ bmiFlags = case bmiVersion dflags of
+ Just BMI2 -> ["-mbmi2"]
+ Just BMI1 -> ["-mbmi"]
+ Nothing -> []
+
+ fmaFlags
+ | fma dflags && not hasAvx512 = ["-mfma"]
+ | otherwise = []
+
+ gfniFlags = [ "-mgfni" | gfni dflags ]
+
-- | Query if the target RTS has the given 'Ways'. It's computed from
-- the @"RTS ways"@ field in the settings file.
targetHasRTSWays :: DynFlags -> Ways -> Bool
=====================================
docs/users_guide/using.rst
=====================================
@@ -488,6 +488,16 @@ The available mode flags are:
List the flags passed to the C compiler for the linking step
during GHC build.
+.. ghc-flag:: --print-enabled-cpu-features
+ :shortdesc: display the effective enabled CPU features for code generation
+ :type: mode
+ :category: modes
+
+ Print a JSON object describing the CPU features currently enabled for code
+ generation, together with a set of ``-m...`` flags that reproduce the
+ effective feature set for the current target.
+ Dynamic options such as ``-mavx2`` and ``-mbmi2`` are respected.
+
.. ghc-flag:: --print-debug-on
:shortdesc: print whether GHC was built with ``-DDEBUG``
:type: mode
=====================================
ghc/GHC/Driver/Session/Lint.hs
=====================================
@@ -1,6 +1,6 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE NondecreasingIndentation #-}
-module GHC.Driver.Session.Lint (checkOptions) where
+module GHC.Driver.Session.Lint (checkOptions, unknownFlagsErr) where
import GHC.Driver.Backend
import GHC.Driver.Phases
=====================================
ghc/GHC/Driver/Session/Mode.hs
=====================================
@@ -77,6 +77,7 @@ isShowGhciUsageMode _ = False
data PostLoadMode
= ShowInterface FilePath -- ghc --show-iface
+ | PrintEnabledCpuFeatures -- ghc --print-enabled-cpu-features
| DoMkDependHS -- ghc -M
| StopBefore StopPhase -- ghc -E | -C | -S
-- StopBefore StopLn is the default
@@ -90,12 +91,13 @@ data PostLoadMode
| DoFrontend ModuleName -- ghc --frontend Plugin.Module
doMkDependHSMode, doMakeMode, doInteractiveMode, doRunMode,
- doAbiHashMode, showUnitsMode :: Mode
+ doAbiHashMode, printEnabledCpuFeaturesMode, showUnitsMode :: Mode
doMkDependHSMode = mkPostLoadMode DoMkDependHS
doMakeMode = mkPostLoadMode DoMake
doInteractiveMode = mkPostLoadMode DoInteractive
doRunMode = mkPostLoadMode DoRun
doAbiHashMode = mkPostLoadMode DoAbiHash
+printEnabledCpuFeaturesMode = mkPostLoadMode PrintEnabledCpuFeatures
showUnitsMode = mkPostLoadMode ShowPackages
showInterfaceMode :: FilePath -> Mode
@@ -203,6 +205,8 @@ mode_flags =
, defFlag "-show-options" (PassFlag (setMode showOptionsMode))
, defFlag "-supported-languages" (PassFlag (setMode showSupportedExtensionsMode))
, defFlag "-supported-extensions" (PassFlag (setMode showSupportedExtensionsMode))
+ , defFlag "-print-enabled-cpu-features"
+ (PassFlag (setMode printEnabledCpuFeaturesMode))
, defFlag "-show-packages" (PassFlag (setMode showUnitsMode))
] ++
[ defFlag k' (PassFlag (setMode (printSetting k)))
=====================================
ghc/Main.hs
=====================================
@@ -229,55 +229,64 @@ main' postLoadMode units dflags0 args flagWarnings = do
liftIO $ exitWith (ExitFailure 1)) $ do
liftIO $ printOrThrowDiagnostics logger4 (initPrintConfig dflags4) diag_opts flagWarnings'
- liftIO $ showBanner postLoadMode dflags4
-
- let (dflags5, srcs, objs) = parseTargetFiles dflags4 (map unLoc fileish_args)
-
- -- we've finished manipulating the DynFlags, update the session
- _ <- GHC.setSessionDynFlags dflags5
- dflags6 <- GHC.getSessionDynFlags
-
- -- Must do this before loading plugins
- liftIO $ initUniqSupply (initialUnique dflags6) (uniqueIncrement dflags6)
-
- -- Initialise plugins here because the plugin author might already expect this
- -- subsequent call to `getLogger` to be affected by a plugin.
- initializeSessionPlugins
- hsc_env <- getSession
- logger <- getLogger
-
-
- ---------------- Display configuration -----------
- case verbosity dflags6 of
- v | v == 4 -> liftIO $ dumpUnitsSimple hsc_env
- | v >= 5 -> liftIO $ dumpUnits hsc_env
- | otherwise -> return ()
-
- ---------------- Final sanity checking -----------
- liftIO $ checkOptions postLoadMode dflags6 srcs objs units
-
- ---------------- Do the business -----------
- handleSourceError (\e -> do
- GHC.printException e
- liftIO $ exitWith (ExitFailure 1)) $ do
- case postLoadMode of
- ShowInterface f -> liftIO $ showIface logger
- (hsc_dflags hsc_env)
- (hsc_units hsc_env)
- (hsc_NC hsc_env)
- f
- DoMake -> doMake units srcs
- DoMkDependHS -> doMkDependHS (map fst srcs)
- StopBefore p -> liftIO (oneShot hsc_env p srcs)
- DoInteractive -> ghciUI units srcs Nothing
- DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
- DoRun -> doRun units srcs args
- DoAbiHash -> abiHash (map fst srcs)
- ShowPackages -> liftIO $ showUnits hsc_env
- DoFrontend f -> doFrontend f srcs
- DoBackpack -> doBackpack (map fst srcs)
-
- liftIO $ dumpFinalStats logger
+ case postLoadMode of
+ PrintEnabledCpuFeatures -> liftIO $ do
+ -- This mode bypasses parseTargetFiles/checkOptions, so reject any
+ -- leftover flag-like arguments (e.g. a mistyped -mavx22) ourselves;
+ -- otherwise the typo would be silently ignored.
+ let unknown_opts = [ f | f@('-':_) <- map unLoc fileish_args ]
+ when (not (null unknown_opts)) (unknownFlagsErr unknown_opts)
+ putStrLn (showEnabledCpuFeatures dflags4)
+ _ -> do
+ liftIO $ showBanner postLoadMode dflags4
+
+ let (dflags5, srcs, objs) = parseTargetFiles dflags4 (map unLoc fileish_args)
+
+ -- we've finished manipulating the DynFlags, update the session
+ _ <- GHC.setSessionDynFlags dflags5
+ dflags6 <- GHC.getSessionDynFlags
+
+ -- Must do this before loading plugins
+ liftIO $ initUniqSupply (initialUnique dflags6) (uniqueIncrement dflags6)
+
+ -- Initialise plugins here because the plugin author might already expect this
+ -- subsequent call to `getLogger` to be affected by a plugin.
+ initializeSessionPlugins
+ hsc_env <- getSession
+ logger <- getLogger
+
+
+ ---------------- Display configuration -----------
+ case verbosity dflags6 of
+ v | v == 4 -> liftIO $ dumpUnitsSimple hsc_env
+ | v >= 5 -> liftIO $ dumpUnits hsc_env
+ | otherwise -> return ()
+
+ ---------------- Final sanity checking -----------
+ liftIO $ checkOptions postLoadMode dflags6 srcs objs units
+
+ ---------------- Do the business -----------
+ handleSourceError (\e -> do
+ GHC.printException e
+ liftIO $ exitWith (ExitFailure 1)) $ do
+ case postLoadMode of
+ ShowInterface f -> liftIO $ showIface logger
+ (hsc_dflags hsc_env)
+ (hsc_units hsc_env)
+ (hsc_NC hsc_env)
+ f
+ DoMake -> doMake units srcs
+ DoMkDependHS -> doMkDependHS (map fst srcs)
+ StopBefore p -> liftIO (oneShot hsc_env p srcs)
+ DoInteractive -> ghciUI units srcs Nothing
+ DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
+ DoRun -> doRun units srcs args
+ DoAbiHash -> abiHash (map fst srcs)
+ ShowPackages -> liftIO $ showUnits hsc_env
+ DoFrontend f -> doFrontend f srcs
+ DoBackpack -> doBackpack (map fst srcs)
+
+ liftIO $ dumpFinalStats logger
doRun :: [String] -> [(FilePath, Maybe Phase)] -> [Located String] -> Ghc ()
doRun units srcs args = do
@@ -515,4 +524,3 @@ abiHash strs = do
f <- fingerprintBinMem bh
putStrLn (showPpr dflags f)
-
=====================================
testsuite/tests/driver/all.T
=====================================
@@ -1,3 +1,12 @@
+def normalise_enabled_cpu_target(msg):
+ return re.sub(r'"target":"[^"]+"', '"target":"TARGET"', msg)
+
+def normalise_unknown_flag(msg):
+ # Keep only the stable 'unrecognised flag' line; the program-name prefix,
+ # the suggestion list, and the usage trailer vary across configurations.
+ m = re.search(r'unrecognised flag: \S+', msg)
+ return m.group(0) + '\n' if m else msg
+
test('driver011', [extra_files(['A011.hs'])], makefile_test, ['test011'])
test('driver012', [extra_files(['A012.hs'])], makefile_test, ['test012'])
@@ -221,6 +230,41 @@ test('T9938B', [], makefile_test, [])
test('T9963', exit_code(1), run_command,
['{compiler} --interactive -ignore-dot-ghci --print-libdir'])
+test('print_enabled_cpu_features',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_avx2',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mavx2 --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_bmi2',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mbmi2 --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_fma',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mfma --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_avx512',
+ [unless(arch('x86_64'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mavx512dq -mavx512vl --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_unknown_flag',
+ [normalise_fun(normalise_unknown_flag), exit_code(1)],
+ run_command,
+ ['{compiler} -mavx22 --print-enabled-cpu-features'])
+
test('T10219', normal, run_command,
# `-x hspp` in make mode should work.
# Note: need to specify `-x hspp` before the filename.
=====================================
testsuite/tests/driver/print_enabled_cpu_features.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2"],"as_m_flags":[]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_avx2.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],"as_m_flags":["-mavx2"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_avx512.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2","AVX512F","AVX512DQ","AVX512VL","FMA"],"as_m_flags":["-mavx512dq","-mavx512vl"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_bmi2.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","BMI1","BMI2"],"as_m_flags":["-mbmi2"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_fma.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","FMA"],"as_m_flags":["-mfma"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_unknown_flag.stderr
=====================================
@@ -0,0 +1,6 @@
+ghc: unrecognised flag: -mavx22
+did you mean one of:
+ -mavx2
+ -mavx
+
+Usage: For basic information, try the `--help' option.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d177606f4cdbbf63a6d6ed7cc19815d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d177606f4cdbbf63a6d6ed7cc19815d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T25450-print-cpu] Add --print-enabled-cpu-features flag
by Simon Jakobi (@sjakobi2) 01 Jun '26
by Simon Jakobi (@sjakobi2) 01 Jun '26
01 Jun '26
Simon Jakobi pushed to branch wip/sjakobi/T25450-print-cpu at Glasgow Haskell Compiler / GHC
Commits:
9af6e598 by Simon Jakobi at 2026-06-01T22:45:12+02:00
Add --print-enabled-cpu-features flag
GHC now supports a new mode flag --print-enabled-cpu-features, which
prints a JSON object describing the CPU features currently enabled for
code generation, together with a set of -m... flags that reproduce the
effective feature set for the current target. Dynamic options such as
-mavx2 and -mbmi2 are respected.
$ ghc -mavx2 --print-enabled-cpu-features
{"tag":"enabled-cpu-features","version":1,"target":"x86_64-linux-gnu",
"features":["SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],
"as_m_flags":["-mavx2"]}
The primary purpose of this flag is for testing the -march=native option
(#25450).
Assisted-by:
- - - - -
14 changed files:
- + changelog.d/print-enabled-cpu-features
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Session.hs
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Lint.hs
- ghc/GHC/Driver/Session/Mode.hs
- ghc/Main.hs
- testsuite/tests/driver/all.T
- + testsuite/tests/driver/print_enabled_cpu_features.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_avx2.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_avx512.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_bmi2.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_fma.stdout
- + testsuite/tests/driver/print_enabled_cpu_features_unknown_flag.stderr
Changes:
=====================================
changelog.d/print-enabled-cpu-features
=====================================
@@ -0,0 +1,16 @@
+section: compiler
+synopsis: Add --print-enabled-cpu-features flag
+issues: #25450
+mrs: !16117
+
+description:
+ GHC now supports a new mode flag ``--print-enabled-cpu-features``, which
+ prints a JSON object describing the CPU features currently enabled for code
+ generation, together with a set of ``-m...`` flags that reproduce the
+ effective feature set for the current target.
+ Dynamic options such as ``-mavx2`` and ``-mbmi2`` are respected. ::
+
+ $ ghc -mavx2 --print-enabled-cpu-features
+ {"tag":"enabled-cpu-features","version":1,"target":"x86_64-linux-gnu",
+ "features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],
+ "as_m_flags":["-mavx2"]}
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -1615,6 +1615,7 @@ initPromotionTickContext dflags =
-- -----------------------------------------------------------------------------
-- SSE, AVX, FMA
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
isSse3Enabled :: DynFlags -> Bool
isSse3Enabled dflags = sseAvxVersion dflags >= Just SSE3 || isAvxEnabled dflags
@@ -1705,11 +1706,14 @@ We handle this as follows:
-- -----------------------------------------------------------------------------
-- LA664
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
+
isLa664Enabled :: DynFlags -> Bool
isLa664Enabled dflags = la664 dflags
-- -----------------------------------------------------------------------------
-- BMI2
+-- See Note [Keeping enabledCpuFeatures in sync] in GHC.Driver.Session
isBmiEnabled :: DynFlags -> Bool
isBmiEnabled dflags = case platformArch (targetPlatform dflags) of
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -196,6 +196,8 @@ module GHC.Driver.Session (
-- * Compiler configuration suitable for display to the user
compilerInfo,
+ showEnabledCpuFeatures,
+ enabledCpuFeatures,
targetHasRTSWays,
@@ -277,6 +279,7 @@ import GHC.Utils.TmpFs
import GHC.Utils.Fingerprint
import GHC.Utils.Outputable
import GHC.Utils.Error (emptyDiagOpts, logInfo)
+import GHC.Utils.Json
import GHC.Settings
import GHC.CmmToAsm.CFG.Weight
import GHC.Core.Opt.CallerCC
@@ -3677,6 +3680,132 @@ compilerInfo dflags
queryCmdMaybe p f = expandDirectories (query (maybe "" (prgPath . p) . f))
queryFlagsMaybe p f = query (maybe "" (unwords . map escapeArg . prgFlags . p) . f)
+showEnabledCpuFeatures :: DynFlags -> String
+showEnabledCpuFeatures dflags = showSDocUnsafe $ renderJSON $ JSObject
+ [ ("tag", JSString "enabled-cpu-features")
+ -- Schema version of this JSON object; bump it whenever the shape or
+ -- meaning of the fields changes, so consumers can detect incompatibility.
+ , ("version", JSInt 1)
+ , ("target", JSString (platformMisc_targetPlatformString (platformMisc dflags)))
+ , ("features", JSArray (map JSString features))
+ -- A set of `-m...` flags that, passed to GHC for this target, reproduce
+ -- the effective feature set above. Note this need not be the flags the
+ -- user actually passed: implied features are folded in, and a feature
+ -- enabled by default may be reproduced by the empty set.
+ , ("as_m_flags", JSArray (map JSString asMFlags))
+ ]
+ where
+ (features, asMFlags) = enabledCpuFeatures dflags
+
+{- Note [Keeping enabledCpuFeatures in sync]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+`enabledCpuFeatures` must be updated whenever a new CPU feature flag is added
+to GHC. The three places to touch are, all in GHC.Driver.DynFlags:
+
+ 1. The flag registration (e.g. `make_ord_flag defGhcFlag "mnewfeat" ...`)
+ 2. The corresponding `is*Enabled` predicate
+ 3. The `enabledCpuFeatures` function below — add the feature to `features`
+ and, if it has a GHC `-m...` flag, to `as_m_flags` via the appropriate
+ architecture branch.
+
+See Note [Implications between X86 CPU feature flags] in GHC.Driver.DynFlags
+for the implication structure that `x86FeaturesAndFlags` and `x86AsMFlags`
+must respect.
+-}
+
+enabledCpuFeatures :: DynFlags -> ([String], [String])
+enabledCpuFeatures dflags = case platformArch (targetPlatform dflags) of
+ ArchX86_64 -> x86FeaturesAndFlags dflags
+ ArchX86 -> x86FeaturesAndFlags dflags
+ ArchLoongArch64 ->
+ ( fmaFeature ++ [ "LA664" | isLa664Enabled dflags ]
+ , fmaFlag ++ [ "-mla664" | isLa664Enabled dflags ]
+ )
+ _ -> (fmaFeature, fmaFlag)
+ where
+ -- `-mfma` is a cross-platform flag. On x86 it is folded into the
+ -- SSE/AVX hierarchy (handled in x86FeaturesAndFlags); on every other
+ -- architecture FMA stands on its own and gates FMA codegen via
+ -- isFmaEnabled in stgToCmmAllowFMAInstr. `fma dflags` is the source of
+ -- truth (it defaults to True on AArch64).
+ fmaFeature = [ "FMA" | fma dflags ]
+ fmaFlag = [ "-mfma" | fma dflags ]
+
+x86FeaturesAndFlags :: DynFlags -> ([String], [String])
+x86FeaturesAndFlags dflags =
+ -- SSE/SSE2 are determined by the target platform rather than a dynamic
+ -- flag, hence those predicates take Platform while the others take DynFlags.
+ ( [ "SSE" | isSseEnabled platform ]
+ ++ [ "SSE2" | isSse2Enabled platform ]
+ ++ [ "SSE3" | isSse3Enabled dflags ]
+ ++ [ "SSSE3" | isSsse3Enabled dflags ]
+ ++ [ "SSE4.1" | isSse4_1Enabled dflags ]
+ ++ [ "SSE4.2" | isSse4_2Enabled dflags ]
+ ++ [ "AVX" | isAvxEnabled dflags ]
+ ++ [ "AVX2" | isAvx2Enabled dflags ]
+ ++ [ "AVX512F" | isAvx512fEnabled dflags ]
+ ++ [ "AVX512BW" | isAvx512bwEnabled dflags ]
+ ++ [ "AVX512CD" | isAvx512cdEnabled dflags ]
+ ++ [ "AVX512DQ" | isAvx512dqEnabled dflags ]
+ ++ [ "AVX512ER" | isAvx512erEnabled dflags ]
+ ++ [ "AVX512PF" | isAvx512pfEnabled dflags ]
+ ++ [ "AVX512VL" | isAvx512vlEnabled dflags ]
+ ++ [ "BMI1" | isBmiEnabled dflags ]
+ ++ [ "BMI2" | isBmi2Enabled dflags ]
+ ++ [ "FMA" | isFmaEnabled dflags ]
+ ++ [ "GFNI" | isGfniEnabled dflags ]
+ , x86AsMFlags dflags
+ )
+ where
+ platform = targetPlatform dflags
+
+x86AsMFlags :: DynFlags -> [String]
+x86AsMFlags dflags =
+ avx512Flags
+ ++ vectorFlags
+ ++ bmiFlags
+ ++ fmaFlags
+ ++ gfniFlags
+ where
+ avx512Extensions =
+ [ ("-mavx512bw", avx512bw dflags)
+ , ("-mavx512cd", avx512cd dflags)
+ , ("-mavx512dq", avx512dq dflags)
+ , ("-mavx512er", avx512er dflags)
+ , ("-mavx512pf", avx512pf dflags)
+ , ("-mavx512vl", avx512vl dflags)
+ ]
+
+ hasAvx512Extension = any snd avx512Extensions
+ hasAvx512 = avx512f dflags || hasAvx512Extension
+
+ avx512Flags =
+ [ "-mavx512f" | avx512f dflags && not hasAvx512Extension ]
+ ++ [ flag | (flag, True) <- avx512Extensions ]
+
+ vectorFlags
+ | hasAvx512 = []
+ | otherwise =
+ case sseAvxVersion dflags of
+ Just AVX2 -> ["-mavx2"]
+ Just AVX1 -> ["-mavx"]
+ Just SSE42 -> ["-msse4.2"]
+ Just SSE4 -> ["-msse4"]
+ Just SSSE3 -> ["-mssse3"]
+ Just SSE3 -> ["-msse3"]
+ _ -> []
+
+ bmiFlags = case bmiVersion dflags of
+ Just BMI2 -> ["-mbmi2"]
+ Just BMI1 -> ["-mbmi"]
+ Nothing -> []
+
+ fmaFlags
+ | fma dflags && not hasAvx512 = ["-mfma"]
+ | otherwise = []
+
+ gfniFlags = [ "-mgfni" | gfni dflags ]
+
-- | Query if the target RTS has the given 'Ways'. It's computed from
-- the @"RTS ways"@ field in the settings file.
targetHasRTSWays :: DynFlags -> Ways -> Bool
=====================================
docs/users_guide/using.rst
=====================================
@@ -488,6 +488,16 @@ The available mode flags are:
List the flags passed to the C compiler for the linking step
during GHC build.
+.. ghc-flag:: --print-enabled-cpu-features
+ :shortdesc: display the effective enabled CPU features for code generation
+ :type: mode
+ :category: modes
+
+ Print a JSON object describing the CPU features currently enabled for code
+ generation, together with a set of ``-m...`` flags that reproduce the
+ effective feature set for the current target.
+ Dynamic options such as ``-mavx2`` and ``-mbmi2`` are respected.
+
.. ghc-flag:: --print-debug-on
:shortdesc: print whether GHC was built with ``-DDEBUG``
:type: mode
=====================================
ghc/GHC/Driver/Session/Lint.hs
=====================================
@@ -1,6 +1,6 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE NondecreasingIndentation #-}
-module GHC.Driver.Session.Lint (checkOptions) where
+module GHC.Driver.Session.Lint (checkOptions, unknownFlagsErr) where
import GHC.Driver.Backend
import GHC.Driver.Phases
=====================================
ghc/GHC/Driver/Session/Mode.hs
=====================================
@@ -77,6 +77,7 @@ isShowGhciUsageMode _ = False
data PostLoadMode
= ShowInterface FilePath -- ghc --show-iface
+ | PrintEnabledCpuFeatures -- ghc --print-enabled-cpu-features
| DoMkDependHS -- ghc -M
| StopBefore StopPhase -- ghc -E | -C | -S
-- StopBefore StopLn is the default
@@ -90,12 +91,13 @@ data PostLoadMode
| DoFrontend ModuleName -- ghc --frontend Plugin.Module
doMkDependHSMode, doMakeMode, doInteractiveMode, doRunMode,
- doAbiHashMode, showUnitsMode :: Mode
+ doAbiHashMode, printEnabledCpuFeaturesMode, showUnitsMode :: Mode
doMkDependHSMode = mkPostLoadMode DoMkDependHS
doMakeMode = mkPostLoadMode DoMake
doInteractiveMode = mkPostLoadMode DoInteractive
doRunMode = mkPostLoadMode DoRun
doAbiHashMode = mkPostLoadMode DoAbiHash
+printEnabledCpuFeaturesMode = mkPostLoadMode PrintEnabledCpuFeatures
showUnitsMode = mkPostLoadMode ShowPackages
showInterfaceMode :: FilePath -> Mode
@@ -203,6 +205,8 @@ mode_flags =
, defFlag "-show-options" (PassFlag (setMode showOptionsMode))
, defFlag "-supported-languages" (PassFlag (setMode showSupportedExtensionsMode))
, defFlag "-supported-extensions" (PassFlag (setMode showSupportedExtensionsMode))
+ , defFlag "-print-enabled-cpu-features"
+ (PassFlag (setMode printEnabledCpuFeaturesMode))
, defFlag "-show-packages" (PassFlag (setMode showUnitsMode))
] ++
[ defFlag k' (PassFlag (setMode (printSetting k)))
=====================================
ghc/Main.hs
=====================================
@@ -229,55 +229,64 @@ main' postLoadMode units dflags0 args flagWarnings = do
liftIO $ exitWith (ExitFailure 1)) $ do
liftIO $ printOrThrowDiagnostics logger4 (initPrintConfig dflags4) diag_opts flagWarnings'
- liftIO $ showBanner postLoadMode dflags4
-
- let (dflags5, srcs, objs) = parseTargetFiles dflags4 (map unLoc fileish_args)
-
- -- we've finished manipulating the DynFlags, update the session
- _ <- GHC.setSessionDynFlags dflags5
- dflags6 <- GHC.getSessionDynFlags
-
- -- Must do this before loading plugins
- liftIO $ initUniqSupply (initialUnique dflags6) (uniqueIncrement dflags6)
-
- -- Initialise plugins here because the plugin author might already expect this
- -- subsequent call to `getLogger` to be affected by a plugin.
- initializeSessionPlugins
- hsc_env <- getSession
- logger <- getLogger
-
-
- ---------------- Display configuration -----------
- case verbosity dflags6 of
- v | v == 4 -> liftIO $ dumpUnitsSimple hsc_env
- | v >= 5 -> liftIO $ dumpUnits hsc_env
- | otherwise -> return ()
-
- ---------------- Final sanity checking -----------
- liftIO $ checkOptions postLoadMode dflags6 srcs objs units
-
- ---------------- Do the business -----------
- handleSourceError (\e -> do
- GHC.printException e
- liftIO $ exitWith (ExitFailure 1)) $ do
- case postLoadMode of
- ShowInterface f -> liftIO $ showIface logger
- (hsc_dflags hsc_env)
- (hsc_units hsc_env)
- (hsc_NC hsc_env)
- f
- DoMake -> doMake units srcs
- DoMkDependHS -> doMkDependHS (map fst srcs)
- StopBefore p -> liftIO (oneShot hsc_env p srcs)
- DoInteractive -> ghciUI units srcs Nothing
- DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
- DoRun -> doRun units srcs args
- DoAbiHash -> abiHash (map fst srcs)
- ShowPackages -> liftIO $ showUnits hsc_env
- DoFrontend f -> doFrontend f srcs
- DoBackpack -> doBackpack (map fst srcs)
-
- liftIO $ dumpFinalStats logger
+ case postLoadMode of
+ PrintEnabledCpuFeatures -> liftIO $ do
+ -- This mode bypasses parseTargetFiles/checkOptions, so reject any
+ -- leftover flag-like arguments (e.g. a mistyped -mavx22) ourselves;
+ -- otherwise the typo would be silently ignored.
+ let unknown_opts = [ f | f@('-':_) <- map unLoc fileish_args ]
+ when (not (null unknown_opts)) (unknownFlagsErr unknown_opts)
+ putStrLn (showEnabledCpuFeatures dflags4)
+ _ -> do
+ liftIO $ showBanner postLoadMode dflags4
+
+ let (dflags5, srcs, objs) = parseTargetFiles dflags4 (map unLoc fileish_args)
+
+ -- we've finished manipulating the DynFlags, update the session
+ _ <- GHC.setSessionDynFlags dflags5
+ dflags6 <- GHC.getSessionDynFlags
+
+ -- Must do this before loading plugins
+ liftIO $ initUniqSupply (initialUnique dflags6) (uniqueIncrement dflags6)
+
+ -- Initialise plugins here because the plugin author might already expect this
+ -- subsequent call to `getLogger` to be affected by a plugin.
+ initializeSessionPlugins
+ hsc_env <- getSession
+ logger <- getLogger
+
+
+ ---------------- Display configuration -----------
+ case verbosity dflags6 of
+ v | v == 4 -> liftIO $ dumpUnitsSimple hsc_env
+ | v >= 5 -> liftIO $ dumpUnits hsc_env
+ | otherwise -> return ()
+
+ ---------------- Final sanity checking -----------
+ liftIO $ checkOptions postLoadMode dflags6 srcs objs units
+
+ ---------------- Do the business -----------
+ handleSourceError (\e -> do
+ GHC.printException e
+ liftIO $ exitWith (ExitFailure 1)) $ do
+ case postLoadMode of
+ ShowInterface f -> liftIO $ showIface logger
+ (hsc_dflags hsc_env)
+ (hsc_units hsc_env)
+ (hsc_NC hsc_env)
+ f
+ DoMake -> doMake units srcs
+ DoMkDependHS -> doMkDependHS (map fst srcs)
+ StopBefore p -> liftIO (oneShot hsc_env p srcs)
+ DoInteractive -> ghciUI units srcs Nothing
+ DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
+ DoRun -> doRun units srcs args
+ DoAbiHash -> abiHash (map fst srcs)
+ ShowPackages -> liftIO $ showUnits hsc_env
+ DoFrontend f -> doFrontend f srcs
+ DoBackpack -> doBackpack (map fst srcs)
+
+ liftIO $ dumpFinalStats logger
doRun :: [String] -> [(FilePath, Maybe Phase)] -> [Located String] -> Ghc ()
doRun units srcs args = do
@@ -515,4 +524,3 @@ abiHash strs = do
f <- fingerprintBinMem bh
putStrLn (showPpr dflags f)
-
=====================================
testsuite/tests/driver/all.T
=====================================
@@ -1,3 +1,12 @@
+def normalise_enabled_cpu_target(msg):
+ return re.sub(r'"target":"[^"]+"', '"target":"TARGET"', msg)
+
+def normalise_unknown_flag(msg):
+ # Keep only the stable 'unrecognised flag' line; the program-name prefix,
+ # the suggestion list, and the usage trailer vary across configurations.
+ m = re.search(r'unrecognised flag: \S+', msg)
+ return m.group(0) + '\n' if m else msg
+
test('driver011', [extra_files(['A011.hs'])], makefile_test, ['test011'])
test('driver012', [extra_files(['A012.hs'])], makefile_test, ['test012'])
@@ -221,6 +230,41 @@ test('T9938B', [], makefile_test, [])
test('T9963', exit_code(1), run_command,
['{compiler} --interactive -ignore-dot-ghci --print-libdir'])
+test('print_enabled_cpu_features',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_avx2',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mavx2 --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_bmi2',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mbmi2 --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_fma',
+ [unless(arch('x86_64') or arch('i386'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mfma --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_avx512',
+ [unless(arch('x86_64'), skip),
+ normalise_fun(normalise_enabled_cpu_target)],
+ run_command,
+ ['{compiler} -mavx512dq -mavx512vl --print-enabled-cpu-features'])
+
+test('print_enabled_cpu_features_unknown_flag',
+ [normalise_fun(normalise_unknown_flag), exit_code(1)],
+ run_command,
+ ['{compiler} -mavx22 --print-enabled-cpu-features'])
+
test('T10219', normal, run_command,
# `-x hspp` in make mode should work.
# Note: need to specify `-x hspp` before the filename.
=====================================
testsuite/tests/driver/print_enabled_cpu_features.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2"],"as_m_flags":[]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_avx2.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2"],"as_m_flags":["-mavx2"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_avx512.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","AVX2","AVX512F","AVX512DQ","AVX512VL","FMA"],"as_m_flags":["-mavx512dq","-mavx512vl"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_bmi2.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","BMI1","BMI2"],"as_m_flags":["-mbmi2"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_fma.stdout
=====================================
@@ -0,0 +1 @@
+{"tag":"enabled-cpu-features","version":1,"target":"TARGET","features":["SSE","SSE2","SSE3","SSSE3","SSE4.1","SSE4.2","AVX","FMA"],"as_m_flags":["-mfma"]}
=====================================
testsuite/tests/driver/print_enabled_cpu_features_unknown_flag.stderr
=====================================
@@ -0,0 +1,6 @@
+ghc: unrecognised flag: -mavx22
+did you mean one of:
+ -mavx2
+ -mavx
+
+Usage: For basic information, try the `--help' option.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9af6e598a33a0b01dc73e4f85f82392…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9af6e598a33a0b01dc73e4f85f82392…
You're receiving this email because of your account on gitlab.haskell.org.
1
0