Haskell.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

ghc-commits

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
ghc-commits@haskell.org

September 2026

  • 1 participants
  • 601 discussions
[Git][ghc/ghc][wip/az/epa-tidy-locatedxxx-22] 5 commits: Windows: enforce path convention in ./configure
by Alan Zimmerman (@alanz) 06 Sep '26

06 Sep '26
Alan Zimmerman pushed to branch wip/az/epa-tidy-locatedxxx-22 at Glasgow Haskell Compiler / GHC Commits: 5939ceaf by sheaf at 2026-09-05T22:06:18-04:00 Windows: enforce path convention in ./configure As detailed in Note [MSYS paths] in Hadrian.Utilities, the standing convention (using Windows-style paths with forward slashes) is now enforced in ./configure instead of within Hadrian, removing the need for 'cygpath' calls within Hadrian. Fixes #26683 - - - - - a6061455 by sheaf at 2026-09-05T22:06:18-04:00 Hadrian: introduce ExeSpawnPath Specific details about the filepath used to specify the executable to spawn with CreateProcess matters on Windows: whether we use forward or backward slashes, a leading ./, or an absolute path changes how the executable is found. This commit introduces 'ExeSpawnPath' which is a path that is guaranteed to be found when spawning a process. All command invocations now go through this type to ensure the path has been properly sanitised. See Note [NeedCurrentDirectoryForExePath] in Hadrian.Utilities. The same treatment is applied to hsc2hs. Updates hsc2hs submodule. - - - - - e28313e3 by sheaf at 2026-09-05T22:07:06-04:00 Preserve tick ordering in 'tickTickedExpr' 'GHC.Core.Utils.tickTickedExpr' tries to combine a tick 't1' into an existing stack of ticks 't2s'. There are two situations: 1. 't1' is subsumed by a tick in 't2s': drop it. 2. A tick in 't2s' is subsumed by 't1', say 't2'. This commit ensures that in case (2) we keep 't1' on the outside instead of replacing 't2' at its position in the stack. This avoids re-ordering source notes (which was the cause of #27749). This fixes a regression introduced in 2dadf3b0d05. Fixes #27749 - - - - - 3172f557 by sheaf at 2026-09-05T22:07:06-04:00 Consistently prefer local source note ticks GHC.Cmm.DebugBlock.cmmDebugGen (DWARF annotations) and GHC.Stg.Debug.quickSourcePos (-finfo-table-map) both contained logic to prioritise source note ticks from the current module. This commit commons up this logic and propagates it to a third consumer: IPE stack frames, in GHC.Driver.GenerateCgIPEStub. See the new function GHC.Types.Tickish.bestSourceNote. - - - - - f45a3d8e by Alan Zimmerman at 2026-09-06T09:49:56+01:00 EPA Fix HsCmdDo exact print with comments Exact printing of HsCmdDo was ignoring the location for the do statements, and this is an annotation that can have comments in it. Update it so we print the statements as a unit, including any comments. Also add the result of auditing that we capture comments in all needed places, noting that the remaining Anno SrcSpan instances are benign. - - - - - 38 changed files: - + changelog.d/T27749 - compiler/GHC/Cmm/DebugBlock.hs - compiler/GHC/Core/Utils.hs - compiler/GHC/Driver/GenerateCgIPEStub.hs - compiler/GHC/Driver/Main/Compile.hs - compiler/GHC/Hs/Doc.hs - compiler/GHC/Hs/Extension/Pass.hs - compiler/GHC/Stg/Debug.hs - compiler/GHC/Types/Tickish.hs - configure.ac - hadrian/src/Base.hs - hadrian/src/Builder.hs - hadrian/src/Hadrian/Builder.hs - hadrian/src/Hadrian/Builder/Ar.hs - hadrian/src/Hadrian/Oracles/Path.hs - hadrian/src/Hadrian/Utilities.hs - hadrian/src/Oracles/Setting.hs - hadrian/src/Oracles/TestSettings.hs - hadrian/src/Rules/BinaryDist.hs - hadrian/src/Rules/Changelog.hs - hadrian/src/Rules/Codes.hs - hadrian/src/Rules/Lint.hs - hadrian/src/Rules/Nofib.hs - hadrian/src/Rules/Test.hs - m4/find_python.m4 - + m4/fp_canonicalise_win_path.m4 - m4/fp_find_nm.m4 - m4/fp_find_root.m4 - m4/fp_prog_ar.m4 - m4/fp_prog_ar_args.m4 - m4/fp_prog_sh.m4 - m4/fptools_alex.m4 - m4/fptools_happy.m4 - + testsuite/tests/simplCore/should_compile/T27749.hs - + testsuite/tests/simplCore/should_compile/T27749.stderr - testsuite/tests/simplCore/should_compile/all.T - utils/check-exact/ExactPrint.hs - utils/hsc2hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d78b5aaaaae9b32ed33c0b57007f0d… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d78b5aaaaae9b32ed33c0b57007f0d… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][master] 2 commits: Preserve tick ordering in 'tickTickedExpr'
by Marge Bot (@marge-bot) 06 Sep '26

06 Sep '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: e28313e3 by sheaf at 2026-09-05T22:07:06-04:00 Preserve tick ordering in 'tickTickedExpr' 'GHC.Core.Utils.tickTickedExpr' tries to combine a tick 't1' into an existing stack of ticks 't2s'. There are two situations: 1. 't1' is subsumed by a tick in 't2s': drop it. 2. A tick in 't2s' is subsumed by 't1', say 't2'. This commit ensures that in case (2) we keep 't1' on the outside instead of replacing 't2' at its position in the stack. This avoids re-ordering source notes (which was the cause of #27749). This fixes a regression introduced in 2dadf3b0d05. Fixes #27749 - - - - - 3172f557 by sheaf at 2026-09-05T22:07:06-04:00 Consistently prefer local source note ticks GHC.Cmm.DebugBlock.cmmDebugGen (DWARF annotations) and GHC.Stg.Debug.quickSourcePos (-finfo-table-map) both contained logic to prioritise source note ticks from the current module. This commit commons up this logic and propagates it to a third consumer: IPE stack frames, in GHC.Driver.GenerateCgIPEStub. See the new function GHC.Types.Tickish.bestSourceNote. - - - - - 10 changed files: - + changelog.d/T27749 - compiler/GHC/Cmm/DebugBlock.hs - compiler/GHC/Core/Utils.hs - compiler/GHC/Driver/GenerateCgIPEStub.hs - compiler/GHC/Driver/Main/Compile.hs - compiler/GHC/Stg/Debug.hs - compiler/GHC/Types/Tickish.hs - + testsuite/tests/simplCore/should_compile/T27749.hs - + testsuite/tests/simplCore/should_compile/T27749.stderr - testsuite/tests/simplCore/should_compile/all.T Changes: ===================================== changelog.d/T27749 ===================================== @@ -0,0 +1,8 @@ +section: compiler +issues: #27749 +mrs: !16601 +synopsis: + Consistently prefer local source note ticks +description: + When generating IPE stack frames, we now insist on using a source location + that is local to the current module. ===================================== compiler/GHC/Cmm/DebugBlock.hs ===================================== @@ -47,9 +47,8 @@ import GHC.Cmm.Dataflow.Label import Data.Maybe import Data.List ( nubBy ) -import Data.List.NonEmpty ( NonEmpty (..), nonEmpty ) +import Data.List.NonEmpty ( NonEmpty (..) ) import qualified Data.List.NonEmpty as NE -import Data.Ord ( comparing ) import qualified Data.Map as Map import Data.Foldable ( toList ) import Data.Either ( partitionEithers ) @@ -152,10 +151,6 @@ cmmDebugGen modLoc decls = map (blocksForScope Nothing) topScopes -- from the same source file. Furthermore, dumps take priority -- (if we generated one, we probably want debug information to -- refer to it). - bestSrcTick = minimumBy (comparing rangeRating) - rangeRating (span, _) - | srcSpanFile span == thisFile = 1 - | otherwise = 2 :: Int thisFile = maybe nilFS mkFastString $ ml_hs_file modLoc -- Returns block tree for this scope as well as all nested @@ -189,17 +184,14 @@ cmmDebugGen modLoc decls = map (blocksForScope Nothing) topScopes blocks | top = seqList childs childs | otherwise = [] - -- A source tick scopes over all nested blocks. However - -- their source ticks might take priority. - isSourceTick (SourceNote span a) = Just (span, a) - isSourceTick _ = Nothing -- Collect ticks from all blocks inside the tick scope. -- We attempt to filter out duplicates while we're at it. ticks = nubBy (flip tickishContains) $ bCtxsTicks bctxs ++ ticksToCopy scope - stick = case nonEmpty $ mapMaybe isSourceTick ticks of - Nothing -> cstick - Just sticks -> Just $! bestSrcTick (sticks `NE.appendList` maybeToList cstick) + -- A source tick scopes over all nested blocks. However + -- their source ticks might take priority. + !stick = bestSourceNote True thisFile $ + ticks ++ map (uncurry SourceNote) (maybeToList cstick) -- | Build a map of blocks sorted by their tick scopes -- ===================================== compiler/GHC/Core/Utils.hs ===================================== @@ -426,8 +426,10 @@ tickTickedExpr preserve_anf t1 t2s e -- combination. -- See Note [Avoiding duplicate ticks] in GHC.Core.Opt.FloatOut -- and Note [Ordering of source notes] in GHC.Types.Tickish. - | Just t2s' <- combine_into_stack t2s - = apply_ticks t2s' e + | Just combined <- combine_into_stack t1 (NE.toList t2s) + = case combined of + DropIncomingTick -> apply_ticks t2s e + TickOutsideStack t1' t2s' -> Tick t1' (apply_ticks t2s' e) -- Case 2: 't1' can be commuted past all the ticks in the stack, e.g. because -- it has tighter placement properties than all the ticks in the stack. @@ -437,22 +439,48 @@ tickTickedExpr preserve_anf t1 t2s e -- Fallback: keep the new tick on the outside. | otherwise - = apply_ticks (t1 NE.:| NE.toList t2s) e + = Tick t1 (apply_ticks t2s e) where - apply_ticks :: NE.NonEmpty CoreTickish -> CoreExpr -> CoreExpr + apply_ticks :: Foldable f => f CoreTickish -> CoreExpr -> CoreExpr apply_ticks ts e' = foldr Tick e' ts + {-# INLINE apply_ticks #-} - -- Try to combine 't1' into a stack of ticks. - combine_into_stack :: NE.NonEmpty CoreTickish -> Maybe (NE.NonEmpty CoreTickish) - combine_into_stack (t2 NE.:| rest) - | Just t2' <- combineTickish_maybe t1 t2 - = Just (t2' NE.:| rest) - | r_hd : r_tl <- rest - , Just rest' <- combine_into_stack (r_hd NE.:| r_tl) - = Just (t2 NE.:| NE.toList rest') +-- | The result of combining a tick into a stack of ticks. +data CombineIntoStack + -- | Drop the incoming tick: it's subsumed by a tick in the stack. + = DropIncomingTick + -- | Keep the incoming tick on the outside (possibly merged with an inner tick), + -- and wrap it around the given stack (from which we removed subsumed ticks). + | TickOutsideStack !CoreTickish [CoreTickish] + +-- | Try to combine a tick into a stack of ticks, never re-ordering any ticks. +-- +-- - If the tick is subsumed by a tick in the stack, drop it. +-- - Otherwise merge it with the ticks it subsumes and keep the result outside +-- the whole stack (#27749), discarding the ticks it makes redundant. +combine_into_stack :: CoreTickish -> [CoreTickish] -> Maybe CombineIntoStack +combine_into_stack _ [] = Nothing +combine_into_stack s (t : ts) = + case combineTickish_maybe s t of + Just s1 + -- 's1 is redundant: drop it, keeping the stack as it is. + | s1 == t -> Just DropIncomingTick + -- 't' is redundant: put 's1' outside the stack. + -- Carry on, as 's1' may subsume further ticks in the stack. + | otherwise -> Just $ combine_into_stack s1 ts `orElse` TickOutsideStack s1 ts + -- Didn't combine: recur, and discard 't' if we end up putting a tick on the + -- outside that subsumes it. + Nothing -> retain t <$> combine_into_stack s ts + where + retain _ DropIncomingTick = DropIncomingTick -- retains it + retain t1 res@(TickOutsideStack s1 ss) + | Just t1' <- combineTickish_maybe s1 t1 + , s1 == t1' + -- s1 subsumes t1: drop t1 + = res | otherwise - = Nothing + = TickOutsideStack s1 (t1 : ss) {- Note [Pushing SCCs inwards] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ===================================== compiler/GHC/Driver/GenerateCgIPEStub.hs ===================================== @@ -28,7 +28,8 @@ import GHC.StgToCmm.Utils import GHC.StgToCmm.CgUtils (CgStream) import GHC.Types.IPE (InfoTableProvMap (provInfoTables), IpeSourceLocation) import GHC.Types.Name.Set (NonCaffySet) -import GHC.Types.Tickish (GenTickish (SourceNote)) +import GHC.Data.FastString (FastString) +import GHC.Types.Tickish (bestSourceNote) import GHC.Unit.Types (Module, moduleName) import GHC.Unit.Module (moduleNameString) import qualified GHC.Utils.Logger as Logger @@ -257,11 +258,12 @@ generateCgIPEStub hsc_env this_mod denv (nonCaffySet, moduleLFInfos, infoTablesW -- performance suffered considerably as a result (see #23103). lookupEstimatedTicks :: HscEnv + -> FastString -- ^ the source file of the module being compiled -> Map CmmInfoTable (Maybe IpeSourceLocation) -> IPEStats -> CmmGroupSRTs -> IO (Map CmmInfoTable (Maybe IpeSourceLocation), IPEStats) -lookupEstimatedTicks hsc_env ipes stats cmm_group_srts = +lookupEstimatedTicks hsc_env this_file ipes stats cmm_group_srts = -- Pass 2: Create an entry in the IPE map for every info table listed in -- this CmmGroupSRTs. If the info table is a stack info table and -- -finfo-table-map-with-stack is enabled, look up its estimated source @@ -286,9 +288,9 @@ lookupEstimatedTicks hsc_env ipes stats cmm_group_srts = labelsToSources :: Map CLabel IpeSourceLocation labelsToSources = if platformTablesNextToCode platform then - foldl' labelsToSourcesWithTNTC Map.empty cmm_group_srts + foldl' (labelsToSourcesWithTNTC this_file) Map.empty cmm_group_srts else - foldl' labelsToSourcesSansTNTC Map.empty cmm_group_srts + foldl' (labelsToSourcesSansTNTC this_file) Map.empty cmm_group_srts collectInfoTables :: (Map CmmInfoTable (Maybe IpeSourceLocation), IPEStats) @@ -331,15 +333,16 @@ lookupEstimatedTicks hsc_env ipes stats cmm_group_srts = -- | See Note [Stacktraces from Info Table Provenance Entries (IPE based stack unwinding)] labelsToSourcesWithTNTC - :: Map CLabel IpeSourceLocation + :: FastString -- ^ the source file of the module being compiled + -> Map CLabel IpeSourceLocation -> GenCmmDecl RawCmmStatics CmmTopInfo CmmGraph -> Map CLabel IpeSourceLocation -labelsToSourcesWithTNTC acc (CmmProc _ _ _ cmm_graph) = +labelsToSourcesWithTNTC this_file acc (CmmProc _ _ _ cmm_graph) = foldl' go acc (toBlockList cmm_graph) where go :: Map CLabel IpeSourceLocation -> CmmBlock -> Map CLabel IpeSourceLocation go acc block = - case (,) <$> returnFrameLabel <*> lastTickInBlock of + case (,) <$> returnFrameLabel <*> nearestTickInBlock of Just (clabel, src_loc) -> Map.insert clabel src_loc acc Nothing -> acc where @@ -351,20 +354,20 @@ labelsToSourcesWithTNTC acc (CmmProc _ _ _ cmm_graph) = (CmmCall _ (Just l) _ _ _ _) -> Just $ mkAsmTempLabel l _ -> Nothing - lastTickInBlock = foldr maybeTick Nothing (blockToList middleBlock) - - maybeTick :: CmmNode O O -> Maybe IpeSourceLocation -> Maybe IpeSourceLocation - maybeTick _ s@(Just _) = s - maybeTick (CmmTick (SourceNote span name)) Nothing = Just (span, name) - maybeTick _ _ = Nothing -labelsToSourcesWithTNTC acc _ = acc + -- The ticks enclosing the call, innermost first. + -- NB: the innermost tick may not be from the current module, due to inlining. + nearestTickInBlock = + bestSourceNote False this_file + [ t | CmmTick t <- reverse (blockToList middleBlock) ] +labelsToSourcesWithTNTC _ acc _ = acc -- | See Note [Stacktraces from Info Table Provenance Entries (IPE based stack unwinding)] labelsToSourcesSansTNTC - :: Map CLabel IpeSourceLocation + :: FastString -- ^ the source file of the module being compiled + -> Map CLabel IpeSourceLocation -> GenCmmDecl RawCmmStatics CmmTopInfo CmmGraph -> Map CLabel IpeSourceLocation -labelsToSourcesSansTNTC acc (CmmProc _ _ _ cmm_graph) = +labelsToSourcesSansTNTC this_file acc (CmmProc _ _ _ cmm_graph) = foldl' go acc (toBlockList cmm_graph) where go :: Map CLabel IpeSourceLocation -> CmmBlock -> Map CLabel IpeSourceLocation @@ -380,7 +383,9 @@ labelsToSourcesSansTNTC acc (CmmProc _ _ _ cmm_graph) = case (b, lastTick) of (CmmStore _ (CmmLit (CmmLabel l)) _, Just src_loc) -> (Map.insert l src_loc acc, Nothing) - (CmmTick (SourceNote span name), _) -> - (acc, Just (span, name)) + (CmmTick t, _) + -- Pick the innermost source note tick from the current file. + | Just src_loc <- bestSourceNote False this_file [t] -> + (acc, Just src_loc) _ -> (acc, lastTick) -labelsToSourcesSansTNTC acc _ = acc +labelsToSourcesSansTNTC _ acc _ = acc ===================================== compiler/GHC/Driver/Main/Compile.hs ===================================== @@ -699,7 +699,7 @@ hscGenHardCode hsc_env cgguts mod_loc output_filename = do Just _ -> do cmms <- {-# SCC "StgToCmm" #-} - doCodeGen hsc_env this_mod denv tycons + doCodeGen hsc_env this_mod mod_loc denv tycons cost_centre_info stg_binds @@ -957,14 +957,14 @@ This reduces residency towards the end of the CodeGen phase significantly (5-10%). -} -doCodeGen :: HscEnv -> Module -> InfoTableProvMap -> [TyCon] +doCodeGen :: HscEnv -> Module -> ModLocation -> InfoTableProvMap -> [TyCon] -> CollectedCCs -> [CgStgTopBinding] -- ^ Bindings come already annotated with fvs -> IO (CgStream CmmGroupSRTs CmmCgInfos) -- Note we produce a 'Stream' of CmmGroups, so that the -- backend can be run incrementally. Otherwise it generates all -- the C-- up front, which has a significant space cost. -doCodeGen hsc_env this_mod denv tycons +doCodeGen hsc_env this_mod mod_loc denv tycons cost_centre_info stg_binds_w_fvs = do let dflags = hsc_dflags hsc_env logger = hsc_logger hsc_env @@ -972,6 +972,7 @@ doCodeGen hsc_env this_mod denv tycons tmpfs = hsc_tmpfs hsc_env platform = targetPlatform dflags stg_ppr_opts = (initStgPprOpts dflags) + this_file = maybe nilFS mkFastString $ ml_hs_file mod_loc putDumpFileMaybe logger Opt_D_dump_stg_final "Final STG:" FormatSTG (pprGenStgTopBindings stg_ppr_opts stg_binds_w_fvs) @@ -1033,7 +1034,7 @@ doCodeGen hsc_env this_mod denv tycons -- Positions] in GHC.Stg.Debug. (ipes', stats') <- if (gopt Opt_InfoTableMap dflags) then - liftIO $ lookupEstimatedTicks hsc_env ipes stats cmm_srts + liftIO $ lookupEstimatedTicks hsc_env this_file ipes stats cmm_srts else return (ipes, stats) ===================================== compiler/GHC/Stg/Debug.hs ===================================== @@ -135,10 +135,12 @@ collectAlt alt = do e' <- collectExpr $ alt_rhs alt -- propagated downwards by 'withSpan'. It's "quick" because it works only using immediate context rather -- than looking at the parent context like 'withSpan' quickSourcePos :: FastString -> StgExpr -> Maybe SpanWithLabel -quickSourcePos cur_mod (StgTick (SourceNote ss m) e) - | srcSpanFile ss == cur_mod = Just (SpanWithLabel ss m) - | otherwise = quickSourcePos cur_mod e -quickSourcePos _ _ = Nothing +quickSourcePos cur_mod e + = uncurry SpanWithLabel <$> bestSourceNote False cur_mod (head_ticks e) + where + -- The ticks at the head of the expression, outermost first. + head_ticks (StgTick t e') = t : head_ticks e' + head_ticks _ = [] recordStgIdPosition :: Id -> Maybe SpanWithLabel -> Maybe SpanWithLabel -> M () recordStgIdPosition id best_span ss = do ===================================== compiler/GHC/Types/Tickish.hs ===================================== @@ -18,6 +18,7 @@ module GHC.Types.Tickish ( tickishContains, combineTickish_maybe, tickishCommutable, + bestSourceNote, -- * Breakpoint tick identifiers BreakpointId(..), BreakTickIndex @@ -32,7 +33,7 @@ import GHC.Core.Type import GHC.Unit.Module import GHC.Types.CostCentre -import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan ) +import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan, srcSpanFile ) import GHC.Types.Var import GHC.Utils.Panic @@ -40,6 +41,8 @@ import GHC.Utils.Panic import Language.Haskell.Syntax.Extension ( NoExtField ) import Data.Data +import Data.List ( partition ) +import Data.Maybe ( listToMaybe, mapMaybe ) import GHC.Utils.Binary import GHC.Utils.Outputable (Outputable (ppr), text, (<+>)) @@ -645,3 +648,25 @@ tickishContains (SourceNote sp1 n1) (SourceNote sp2 n2) -- compare the String last tickishContains t1 t2 = t1 == t2 + +-- | Choose the "best" source note in the given candidate list of ticks, +-- preferring source notes that are local to the source file being consdiered. +bestSourceNote + :: Bool + -- ^ accept a location in another module if there are none in the + -- current module? + -> FastString -- ^ the "local" source file + -> [GenTickish pass] -- ^ candidates (best first) + -> Maybe (RealSrcSpan, LexicalFastString) +bestSourceNote accept_outside_loc this_file ticks + = listToMaybe $ + if accept_outside_loc + then here ++ elsewhere + else here + where + (here, elsewhere) + = partition ((this_file ==) . srcSpanFile . fst) + $ mapMaybe source_location ticks + + source_location (SourceNote span name) = Just (span, name) + source_location _ = Nothing ===================================== testsuite/tests/simplCore/should_compile/T27749.hs ===================================== @@ -0,0 +1,9 @@ +module T27749 where + +select :: Maybe Int -> (Int -> Int) -> Int +select m k = case m of { Nothing -> 0; Just x -> k x } +{-# INLINE select #-} + +ordering :: Maybe Int -> Int -> Int +ordering m b = select m (\x -> x + b) +{-# OPAQUE ordering #-} ===================================== testsuite/tests/simplCore/should_compile/T27749.stderr ===================================== @@ -0,0 +1,4 @@ +ordering + = \ (m :: Maybe Int) (b :: Int) -> + src<T27749.hs:8:1-37> + src<T27749.hs:4:1-54> ===================================== testsuite/tests/simplCore/should_compile/all.T ===================================== @@ -612,3 +612,9 @@ test('T27296b', [], makefile_test, ['T27296b']) test('T27589', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques']) test('T27590', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques']) test('T27556', [only_ways('ghci'), extra_hc_opts('-O -fno-unoptimized-core-for-interpreter')], ghci_script, ['T27556.script']) + +# Check the stack of source notes at the top of the body of 'ordering' +# is in the correct order. +test('T27749', + multiline_grep_errmsg(r'ordering\n.*\n(\s+src<[^>]*>\n)+'), + compile, ['-O -g3 -ddump-simpl -dsuppress-uniques']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/a6061455d54e68ad2f45ff112fbd01… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/a6061455d54e68ad2f45ff112fbd01… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][master] 2 commits: Windows: enforce path convention in ./configure
by Marge Bot (@marge-bot) 06 Sep '26

06 Sep '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 5939ceaf by sheaf at 2026-09-05T22:06:18-04:00 Windows: enforce path convention in ./configure As detailed in Note [MSYS paths] in Hadrian.Utilities, the standing convention (using Windows-style paths with forward slashes) is now enforced in ./configure instead of within Hadrian, removing the need for 'cygpath' calls within Hadrian. Fixes #26683 - - - - - a6061455 by sheaf at 2026-09-05T22:06:18-04:00 Hadrian: introduce ExeSpawnPath Specific details about the filepath used to specify the executable to spawn with CreateProcess matters on Windows: whether we use forward or backward slashes, a leading ./, or an absolute path changes how the executable is found. This commit introduces 'ExeSpawnPath' which is a path that is guaranteed to be found when spawning a process. All command invocations now go through this type to ensure the path has been properly sanitised. See Note [NeedCurrentDirectoryForExePath] in Hadrian.Utilities. The same treatment is applied to hsc2hs. Updates hsc2hs submodule. - - - - - 25 changed files: - configure.ac - hadrian/src/Base.hs - hadrian/src/Builder.hs - hadrian/src/Hadrian/Builder.hs - hadrian/src/Hadrian/Builder/Ar.hs - hadrian/src/Hadrian/Oracles/Path.hs - hadrian/src/Hadrian/Utilities.hs - hadrian/src/Oracles/Setting.hs - hadrian/src/Oracles/TestSettings.hs - hadrian/src/Rules/BinaryDist.hs - hadrian/src/Rules/Changelog.hs - hadrian/src/Rules/Codes.hs - hadrian/src/Rules/Lint.hs - hadrian/src/Rules/Nofib.hs - hadrian/src/Rules/Test.hs - m4/find_python.m4 - + m4/fp_canonicalise_win_path.m4 - m4/fp_find_nm.m4 - m4/fp_find_root.m4 - m4/fp_prog_ar.m4 - m4/fp_prog_ar_args.m4 - m4/fp_prog_sh.m4 - m4/fptools_alex.m4 - m4/fptools_happy.m4 - utils/hsc2hs Changes: ===================================== configure.ac ===================================== @@ -238,16 +238,10 @@ if test "${WithGhc}" != "" then ghc_host_os=`"${WithGhc}" +RTS --info | grep 'Host OS' | sed -e 's/.*, "//' -e 's/")//'` + dnl NB: can't use FP_CANONICALISE_WIN_PATH here, as $windows is not yet set. if test "$ghc_host_os" = "mingw32" then - if test "${OSTYPE}" = "msys" - then - WithGhc=`echo "${WithGhc}" | sed "s#^/\([a-zA-Z]\)/#\1:/#"` - else - # Canonicalise to <drive>:/path/to/ghc - WithGhc=`cygpath -m "${WithGhc}"` - fi - echo "GHC path canonicalised to: ${WithGhc}" + WithGhc=`cygpath -m "${WithGhc}"` fi fi AC_SUBST([WithGhc]) @@ -329,12 +323,11 @@ else AC_CHECK_TARGET_TOOL([DlltoolCmd],[llvm-dlltool]) AC_CHECK_TARGET_TOOL([OBJDUMP],[objdump]) - WindresCmd="$(cygpath -m $WindresCmd)" - DlltoolCmd="$(cygpath -m $DlltoolCmd)" + FP_CANONICALISE_WIN_PATH([WindresCmd]) + FP_CANONICALISE_WIN_PATH([DlltoolCmd]) - if test "$Genlib" != ""; then - GenlibCmd="$(cygpath -m $Genlib)" - fi + GenlibCmd="$Genlib" + FP_CANONICALISE_WIN_PATH([GenlibCmd]) fi fi @@ -510,12 +503,8 @@ case $HostOS_CPP in ;; esac -if test "$HostOS" = "mingw32" -then - ObjdumpCmd=$(cygpath -m "$OBJDUMP") -else - ObjdumpCmd="$OBJDUMP" -fi +ObjdumpCmd="$OBJDUMP" +FP_CANONICALISE_WIN_PATH([ObjdumpCmd]) AC_SUBST([ObjdumpCmd]) dnl ** Which ranlib to use? @@ -524,12 +513,8 @@ AC_PROG_RANLIB if test "$RANLIB" = ":"; then AC_MSG_ERROR([cannot find ranlib in your PATH]) fi -if test "$HostOS" = "mingw32" -then - RanlibCmd=$(cygpath -m "$RANLIB") -else - RanlibCmd="$RANLIB" -fi +RanlibCmd="$RANLIB" +FP_CANONICALISE_WIN_PATH([RanlibCmd]) AC_SUBST([RanlibCmd]) LINKER_SUPPORTS_VERBATIM_LINKING @@ -791,13 +776,16 @@ AC_PROG_LN_S dnl ** Find the path to sed AC_PATH_PROGS(SedCmd,gsed sed,sed) +FP_CANONICALISE_WIN_PATH([SedCmd]) dnl ** check for tar dnl if GNU tar is named gtar, look for it first. AC_PATH_PROGS(TarCmd,gnutar gtar tar,tar) +FP_CANONICALISE_WIN_PATH([TarCmd]) dnl ** check for autoreconf AC_PATH_PROG(AutoreconfCmd, autoreconf, autoreconf) +FP_CANONICALISE_WIN_PATH([AutoreconfCmd]) dnl ** check for dtrace (currently only implemented for Mac OS X) AC_ARG_ENABLE(dtrace, @@ -822,17 +810,11 @@ fi AC_SUBST(HaveDtrace) AC_PATH_PROG(HSCOLOUR,HsColour) -# HsColour is passed to Cabal, so we need a native path -if test "$HostOS" = "mingw32" && \ - test "${OSTYPE}" != "msys" && \ - test "${HSCOLOUR}" != "" -then - # Canonicalise to <drive>:/path/to/gcc - HSCOLOUR=`cygpath -m ${HSCOLOUR}` -fi +FP_CANONICALISE_WIN_PATH([HSCOLOUR]) dnl ** check for Sphinx toolchain AC_PATH_PROG(SPHINXBUILD,sphinx-build) +FP_CANONICALISE_WIN_PATH([SPHINXBUILD]) AC_CACHE_CHECK([for version of sphinx-build], fp_cv_sphinx_version, changequote(, )dnl [if test -n "$SPHINXBUILD"; then @@ -851,14 +833,19 @@ fi dnl ** check for xelatex AC_PATH_PROG(XELATEX,xelatex) +FP_CANONICALISE_WIN_PATH([XELATEX]) AC_PATH_PROG(MAKEINDEX,makeindex) +FP_CANONICALISE_WIN_PATH([MAKEINDEX]) AC_PATH_PROG(GIT,git) +FP_CANONICALISE_WIN_PATH([GIT]) dnl ** check for makeinfo AC_PATH_PROG(MAKEINFO,makeinfo) +FP_CANONICALISE_WIN_PATH([MAKEINFO]) dnl ** check for cabal AC_PATH_PROG(CABAL,cabal) +FP_CANONICALISE_WIN_PATH([CABAL]) dnl ** check for Python for testsuite driver ===================================== hadrian/src/Base.hs ===================================== @@ -51,9 +51,9 @@ import Data.List.Extra import Data.Maybe import Data.Semigroup #if MIN_VERSION_shake(0,19,0) -import Development.Shake hiding (unit, (&%>), Normal) +import Development.Shake hiding (unit, (&%>), Normal, cmd, cmd_) #else -import Development.Shake hiding (unit, (&%>), (*>), Normal) +import Development.Shake hiding (unit, (&%>), (*>), Normal, cmd, cmd_) #endif import qualified Development.Shake as Shake import Development.Shake.Classes ===================================== hadrian/src/Builder.hs ===================================== @@ -254,38 +254,43 @@ instance H.Builder Builder where msgIn = "[askBuilder] Exactly one input file expected." needBuilders [builder] path <- H.builderPath builder + prog <- exeSpawnPath path -- we do not depend on bare builders. E.g. we won't depend on `clang` -- or `ld` or `ar`. Unless they are provided with fully qualified paths -- this is the job of the person invoking ./configure to pass e.g. -- CC=$(which clang) if they want the fully qualified clang path! when (path /= takeFileName path) $ need [path] - Stdout stdout <- cmd' [path] ["--no-user-package-db", "field", input, "depends"] + Stdout stdout <- cmd' prog ["--no-user-package-db", "field", input, "depends"] return stdout Testsuite GetExtraDeps -> do path <- builderPath builder + prog <- exeSpawnPath path withResources buildResources $ withTempFile $ \temp -> do - () <- cmd' [path] (buildArgs ++ ["--only-report-hadrian-deps", temp]) + () <- cmd' prog (buildArgs ++ ["--only-report-hadrian-deps", temp]) readFile' temp Git ListFiles -> do path <- builderPath builder + prog <- exeSpawnPath path withResources buildResources $ do -- NUL separated list of files -- We need to read this in the filesystem encoding enc <- liftIO getFileSystemEncoding - Stdout stdout <- cmd' BinaryPipes [path] buildArgs + Stdout stdout <- cmd' prog BinaryPipes buildArgs liftIO $ BS.useAsCStringLen stdout $ \fp -> GHC.peekCStringLen enc fp Win32Tarballs ListTarballs -> do path <- builderPath builder + prog <- exeSpawnPath path withResources buildResources $ do - Stdout stdout <- cmd' [path] buildArgs + Stdout stdout <- cmd' prog buildArgs pure stdout _ -> error $ "Builder " ++ show builder ++ " can not be asked!" runBuilderWith :: Builder -> BuildInfo -> Action () runBuilderWith builder BuildInfo {..} = do path <- builderPath builder + prog <- exeSpawnPath path withResources buildResources $ do verbosity <- getVerbosity let input = fromSingleton msgIn buildInputs @@ -294,52 +299,54 @@ instance H.Builder Builder where msgOut = "[runBuilderWith] Exactly one output file expected." -- Capture stdout and write it to the output file. captureStdout = do - Stdout stdout <- cmd' [path] buildArgs buildOptions + Stdout stdout <- cmd' prog buildArgs buildOptions -- see Note [Capture stdout as a ByteString] writeFileChangedBS output stdout case builder of Ar Pack stg -> do useTempFile <- arSupportsAtFile stg - if useTempFile then runAr output path buildArgs buildInputs buildOptions - else runArWithoutTempFile path buildArgs buildInputs buildOptions + if useTempFile then runAr output prog buildArgs buildInputs buildOptions + else runArWithoutTempFile prog buildArgs buildInputs buildOptions - Ar Unpack _ -> cmd' [Cwd output] [path] buildArgs buildOptions + Ar Unpack _ -> cmd' prog [Cwd output] buildArgs buildOptions Autoreconf dir -> do - bash <- bashPath - cmd' [Cwd dir] [bash, path] buildArgs buildOptions + sh <- shPath + shProg <- exeSpawnPath sh + cmd' shProg [Cwd dir] [path] buildArgs buildOptions Configure dir -> do - -- Inject /bin/bash into `libtool`, instead of /bin/sh, + -- Also inject the shell into `libtool` via CONFIG_SHELL, -- otherwise Windows breaks. TODO: Figure out why. - bash <- bashPath - let env = AddEnv "CONFIG_SHELL" bash - cmd' env [Cwd dir] ["sh", path] buildOptions buildArgs + sh <- shPath + shProg <- exeSpawnPath sh + let env = AddEnv "CONFIG_SHELL" sh + cmd' shProg env [Cwd dir] [path] buildOptions buildArgs GenApply {} -> captureStdout GenPrimopCode -> do need [input] - Stdout stdout <- cmd' (FileStdin input) [path] buildArgs buildOptions + Stdout stdout <- cmd' prog (FileStdin input) buildArgs buildOptions -- see Note [Capture stdout as a ByteString] writeFileChangedBS output stdout GhcPkg Copy _ -> do - Stdout pkgDesc <- cmd' [path] + Stdout pkgDesc <- cmd' prog [ "--expand-pkgroot" , "--no-user-package-db" , "describe" , input -- the package name ] - cmd' (Stdin pkgDesc) [path] (buildArgs ++ ["-"]) buildOptions + cmd' prog (Stdin pkgDesc) (buildArgs ++ ["-"]) buildOptions GhcPkg Unregister _ -> do -- unregistering is allowed to fail (e.g. when a package -- isn't already present) - Exit _ <- cmd' [path] (buildArgs ++ [input]) buildOptions + Exit _ <- cmd' prog (buildArgs ++ [input]) buildOptions return () - Haddock BuildPackage -> runHaddock output path buildArgs buildInputs + Haddock BuildPackage -> runHaddock output prog buildArgs buildInputs Ghc _ _ -> -- Use a response file for ghc invocations to avoid issues with command line @@ -349,52 +356,54 @@ instance H.Builder Builder where -- yet due to #26560. withResponseFileIfLongCmd output - (toCmdArgument [path] <> toCmdArgument buildArgs) + prog + (toCmdArgument buildArgs) buildInputs (toCmdArgument buildOptions) HsCpp {} -> captureStdout - Make dir -> cmd' buildOptions path ["-C", dir] buildArgs + Make dir -> cmd' prog buildOptions ["-C", dir] buildArgs Makeinfo -> do - cmd' [path] "--no-split" [ "-o", output] [input] buildOptions + cmd' prog "--no-split" [ "-o", output] [input] buildOptions Xelatex -> -- xelatex produces an incredible amount of output, almost -- all of which is useless. Suppress it unless user -- requests a loud build. if verbosity >= Diagnostic - then cmd' [Cwd output] [path] buildArgs buildOptions - else do (Stdouterr out, Exit code) <- cmd' [Cwd output] [path] buildArgs buildOptions + then cmd' prog [Cwd output] buildArgs buildOptions + else do (Stdouterr out, Exit code) <- cmd' prog [Cwd output] buildArgs buildOptions when (code /= ExitSuccess) $ do liftIO $ BSL.hPutStrLn stderr out putFailure "xelatex failed!" fail "xelatex failed" - Makeindex -> unit $ cmd' [Cwd output] [path] (buildArgs ++ [input]) buildOptions + Makeindex -> unit $ cmd' prog [Cwd output] (buildArgs ++ [input]) buildOptions - Tar _ -> cmd' buildOptions [path] buildArgs + Tar _ -> cmd' prog buildOptions buildArgs -- RunTest produces a very large amount of (colorised) output; -- Don't attempt to capture it. Testsuite RunTest -> do - Exit code <- cmd [path] buildArgs buildOptions + Exit code <- cmd' prog buildArgs buildOptions when (code /= ExitSuccess) $ do fail "tests failed" - _ -> cmd' [path] buildArgs buildOptions + _ -> cmd' prog buildArgs buildOptions -- | 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 -- ^ base name to use for response file - -> FilePath -- ^ path to @haddock@ + -> ExeSpawnPath -- ^ path to @haddock@ -> [String] -> [FilePath] -- ^ input file paths -> Action () runHaddock outputFilePath haddockPath flagArgs fileInputs = withResponseFileIfLongCmd outputFilePath - (toCmdArgument [haddockPath] <> toCmdArgument flagArgs) + haddockPath + (toCmdArgument flagArgs) fileInputs (CmdArgument []) @@ -469,6 +478,12 @@ systemBuilderPath builder = case builder of ++ quote keyname ++ " is not specified" ++ inCfg return "" -- TODO: Use a safe interface. else do + when (windowsHost && isMsysPath path) . error $ + unlines + [ "The path to builder " ++ quote keyname ++ inCfg + , "is an MSYS path: " ++ quote path ++ "." + , "Please re-run ./configure to fix this issue." + ] -- angerman: I find this lookupInPath rather questionable. -- if we specify CC, LD, ... *without* a path, that is intentional -- lookupInPath should be done by the person invoking the configure @@ -478,8 +493,8 @@ systemBuilderPath builder = case builder of fullPath <- lookupInPath path case (windowsHost, hasExtension fullPath) of (False, _ ) -> return path - (True , True ) -> fixAbsolutePathOnWindows fullPath - (True , False) -> fixAbsolutePathOnWindows fullPath <&> (<.> exe) + (True , True ) -> return $ unifyPath fullPath + (True , False) -> return $ unifyPath fullPath <.> exe -- Without this function, on Windows we can observe a bad builder path -- for 'autoreconf'. If the relevant system.config field is set to @@ -545,8 +560,8 @@ isSpecified = fmap (not . null) . systemBuilderPath -- | Wrapper for Shake's 'cmd' -- -- See Note [cmd wrapper] -cmd' :: (Partial, CmdWrap args) => args :-> Action r -cmd' = cmdArgs mempty +cmd' :: (Partial, CmdWrap args) => ExeSpawnPath -> args :-> Action r +cmd' = cmdArgs . toCmdArgument -- See Note [cmd wrapper] ===================================== hadrian/src/Hadrian/Builder.hs ===================================== @@ -61,10 +61,10 @@ class ShakeValue b => Builder b where runBuilderWith builder buildInfo = do let args = buildArgs buildInfo needBuilders [builder] - path <- builderPath builder + prog <- exeSpawnPath =<< builderPath builder let msg = if null args then "" else " (" ++ intercalate ", " args ++ ")" putBuild $ "| Run " ++ show builder ++ msg - quietly $ cmd (buildOptions buildInfo) [path] args + quietly $ cmdExe prog (buildOptions buildInfo) args needBuilders :: Builder b => [b] -> Action () needBuilders bs = do ===================================== hadrian/src/Hadrian/Builder/Ar.hs ===================================== @@ -36,7 +36,7 @@ instance NFData ArMode -- via a response file is not supported by some versions of @ar@, in which -- case you should use 'runArWithoutTempFile' instead. runAr :: FilePath -- ^ base name to use for response files - -> FilePath -- ^ path to @ar@ + -> ExeSpawnPath -- ^ path to @ar@ -> [String] -- ^ other arguments -> [FilePath] -- ^ input file paths -> [CmdOption] -- ^ Additional options @@ -44,17 +44,17 @@ runAr :: FilePath -- ^ base name to use for response files runAr outputFilePath arPath flagArgs fileArgs buildOptions = do rspFile <- responseFilePath outputFilePath writeFileAtomic rspFile $ unwords fileArgs - cmd [arPath] flagArgs ('@' : rspFile) buildOptions + cmdExe arPath flagArgs ('@' : rspFile) buildOptions -- | Invoke @ar@ given a path to it and a list of arguments. Note that @ar@ -- will be called multiple times if the list of files to be archived is too -- long and doesn't fit into the command line length limit. This function is -- typically much slower than 'runAr'. -runArWithoutTempFile :: FilePath -- ^ path to @ar@ +runArWithoutTempFile :: ExeSpawnPath -- ^ path to @ar@ -> [String] -- ^ other arguments -> [FilePath] -- ^ input file paths -> [CmdOption] -- ^ Additional options -> Action () runArWithoutTempFile arPath flagArgs fileArgs buildOptions = forM_ (chunksOfSize cmdLineLengthLimit fileArgs) $ \argsChunk -> - unit (cmd [arPath] (flagArgs ++ argsChunk) buildOptions) + unit (cmdExe arPath (flagArgs ++ argsChunk) buildOptions) ===================================== hadrian/src/Hadrian/Oracles/Path.hs ===================================== @@ -1,17 +1,13 @@ {-# LANGUAGE TypeFamilies #-} module Hadrian.Oracles.Path ( - lookupInPath, fixAbsolutePathOnWindows, fixUnixPathsOnWindows, - pathOracle + lookupInPath, pathOracle ) where import Control.Monad -import Data.Char -import Data.List.Extra import Development.Shake import Development.Shake.Classes import Development.Shake.FilePath import System.Directory -import System.Info.Extra import Hadrian.Utilities @@ -21,54 +17,13 @@ lookupInPath name | name == takeFileName name = askOracle $ LookupInPath name | otherwise = return name --- | Fix an absolute path on Windows: --- * "/c/" => "C:/" --- * "/usr/bin/tar.exe" => "C:/msys/usr/bin/tar.exe" -fixAbsolutePathOnWindows :: FilePath -> Action FilePath -fixAbsolutePathOnWindows path = - if isWindows - then do - let (dir, file) = splitFileName path - winDir <- askOracle $ WindowsPath dir - return $ winDir -/- file - else - return path - --- | Fix a unix path list on Windows: --- * "C:\\foo\\bar;C:\\msys2\\bin" => "/c/foo/bar:/c/msys2/bin" -fixUnixPathsOnWindows :: FilePath -> Action FilePath -fixUnixPathsOnWindows paths = - if isWindows - then askOracle $ UnixPathList paths - else return paths - newtype LookupInPath = LookupInPath String deriving (Binary, Eq, Hashable, NFData, Show) type instance RuleResult LookupInPath = String -newtype WindowsPath = WindowsPath FilePath - deriving (Binary, Eq, Hashable, NFData, Show) -type instance RuleResult WindowsPath = String - -newtype UnixPathList = UnixPathList FilePath - deriving (Binary, Eq, Hashable, NFData, Show) -type instance RuleResult UnixPathList = String - -- | Oracles for looking up paths. These are slow and require caching. pathOracle :: Rules () pathOracle = do - void $ addOracleCache $ \(WindowsPath path) -> do - Stdout out <- quietly $ cmd ["cygpath", "-m", path] - let windowsPath = unifyPath $ dropWhileEnd isSpace out - putVerbose $ "| Windows path mapping: " ++ path ++ " => " ++ windowsPath - return windowsPath - - void $ addOracleCache $ \(UnixPathList paths) -> do - Stdout out <- quietly $ cmd ["cygpath", "-p", "-u", paths] - let unixPaths = unifyPath $ dropWhileEnd isSpace out - putVerbose $ "| Unix path mapping: " ++ paths ++ " => " ++ unixPaths - return unixPaths - void $ addOracleCache $ \(LookupInPath name) -> do path <- liftIO getSearchPath exes <- liftIO (findExecutablesInDirectories path name) ===================================== hadrian/src/Hadrian/Utilities.hs ===================================== @@ -10,6 +10,8 @@ module Hadrian.Utilities ( -- * FilePath manipulation unifyPath, (-/-), makeRelativeNoSysLink, makeAbsolute, + isMsysPath, windowsToMsysPathList, + ExeSpawnPath, exeSpawnPath, cmdExe, -- * Accessing Shake's type-indexed map insertExtra, lookupExtra, userSetting, @@ -52,7 +54,9 @@ import Data.Typeable (TypeRep, typeOf) import Development.Shake hiding (Normal) import qualified Development.Shake as Shake import Development.Shake.Classes -import Development.Shake.Command (CmdArgument (..), IsCmdArgument (toCmdArgument)) +import Control.Exception.Extra (Partial) +import Development.Shake.Command + (CmdArgument (..), CmdArguments (cmdArguments), IsCmdArgument (toCmdArgument)) import Development.Shake.FilePath import GHC.ResponseFile (escapeArgs) import System.Environment (lookupEnv) @@ -144,17 +148,51 @@ zeroOne True = "1" unifyPath :: FilePath -> FilePath unifyPath = toStandard . normaliseEx -{- Note [Absolute paths and MSYS] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When dealing with absolute paths in Hadrian, we opt to always use Unix-style -forward slashes for separating paths. -This is because, on Windows, the MSYS toolchain can reliably handle paths such -as /c/foo, while it occasionally falls over on paths of the form C:\foo. +{- Note [MSYS paths] +~~~~~~~~~~~~~~~~~~~~ +On Windows, GHC is built using an MSYS toolchain, which understands two +different types of paths: + - Windows C:\foo\bar (forward slashes also accepted) + - POSIX /c/foo/bar /usr/baz/quux + +On the other hand, like any other Haskell program that depends on 'filepath', +when compiled on Windows, Hadrian by default only understands Windows file paths. + +Separately, backslashes are a source of tricky bugs, as they require escaping +in most circumstances. + +So, on Windows, we settle on using Windows-style paths with forward slashes. +Hadrian manipulates existing paths using '(-/-)' and 'makeAbsolute', which +maintain this convention. What's left to handle are the paths Hadrian receives, +such as the paths of toolchain programs. Those are converted to the standing +path convention using FP_CANONICALISE_WIN_PATH, which uses 'cygpath'. + +The end result is that Hadrian itself never needs to turn a POSIX path into a +Windows path, and hence never needs to call 'cygpath'. -} +-- | Is this an MSYS path, e.g. @\/usr\/bin\/tar@ or @\/c\/foo@, rather than a +-- Windows one? +-- +-- See Note [MSYS paths]. +isMsysPath :: FilePath -> Bool +isMsysPath ('/' : _) = True +isMsysPath _ = False + +-- | Rewrite a Windows path list, e.g. @C:\\foo;C:\\msys64\\usr\\share@, into +-- the MSYS syntax @\/c\/foo:\/c\/msys64\/usr\/share@ that MSYS tools expect. +-- +-- See Note [MSYS paths]. +windowsToMsysPathList :: String -> String +windowsToMsysPathList = intercalate ":" . map toMsysPath . splitOn ";" + where + toMsysPath path = case replaceEq '\\' '/' path of + drive : ':' : rest | isAlpha drive -> '/' : toLower drive : rest + msysPath -> msysPath + -- | Combine paths with a forward slash regardless of platform. -- --- See Note [Absolute paths and MSYS]. +-- See Note [MSYS paths]. (-/-) :: FilePath -> FilePath -> FilePath _ -/- b | isAbsolute b @@ -170,13 +208,83 @@ infixr 6 -/- -- | Like 'System.Directory.makeAbsolute' from @directory@, but always -- using forward slashes. -- --- See Note [Absolute paths and MSYS]. +-- See Note [MSYS paths]. makeAbsolute :: FilePath -> IO FilePath makeAbsolute fp = do cwd <- IO.getCurrentDirectory let fp' = cwd -/- fp return $ Posix.normalise fp' +{- Note [NeedCurrentDirectoryForExePath] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The Windows API specifies some rather convoluted rules for whether the current +directory is included in the search when looking for an executable (e.g. for +CreateProcess). The documentation states: + + https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processen… + + NeedCurrentDirectoryForExePathA function + Determines whether the current directory should be included in the search path + for the specified executable. + + If CreateProcess is called with a relative executable name, it will + automatically search for the executable, calling this function to determine + the search path. + + The value of the NoDefaultCurrentDirectoryInExePath environment variable + determines the value this function returns. + If the value of the ExeName parameter contains a backslash (\), this function + will always return TRUE. If it does not contain a backslash, the existence of + the NoDefaultCurrentDirectoryInExePath environment variable is checked, and + not its value. + +In practice, this means that when we create a process with the executable being +specified using a relative path, whether the lookup succeeds depends on +minutiae of the path. Assuming that NoDefaultCurrentDirectoryInExePath is set, +the behaviour is as follows: + + bin\target.exe -- SUCCEEDS: contains backslash + bin/target.exe -- FAILS + ./bin/target.exe -- SUCCEEDS: ./ specifically means "in CWD" + +To avoid process spawning behaviour depending on the value of the +NoDefaultCurrentDirectoryInExePath environment variable, we have a few choices +for how to specify executable paths when creating a process: + + 1. Always use absolute paths. + 2. Always use backslashes. + 3. Add "./" to the front of relative paths. + +We choose to implement (1), see 'exeSpawnPath'. It's the most robust option, as +it pins down the exact executable path (no search needed); (2) would go against +Note [MSYS paths]. +-} + +-- | An executable path suitable for 'createProcess'. +-- +-- See Note [NeedCurrentDirectoryForExePath]. +newtype ExeSpawnPath = ExeSpawnPath FilePath + +instance IsCmdArgument ExeSpawnPath where + toCmdArgument (ExeSpawnPath path) = toCmdArgument [path] + +-- | Resolve the path of a program into an 'ExeSpawnPath' suitable for a +-- 'createProcess' invocation. +-- +-- See Note [NeedCurrentDirectoryForExePath]. +exeSpawnPath :: FilePath -> Action ExeSpawnPath +exeSpawnPath path + -- Don't touch a bare program name (e.g. "clang"), as that resolves from PATH. + | path == takeFileName path = return $ ExeSpawnPath path + | otherwise = ExeSpawnPath <$> liftIO (makeAbsolute path) + +-- | Like Shake's 'cmd', except that the program to run must be given as an +-- 'ExeSpawnPath'. Prefer this over 'cmd', which would accept any 'String'. +-- +-- See Note [NeedCurrentDirectoryForExePath]. +cmdExe :: (Partial, CmdArguments args) => ExeSpawnPath -> args +cmdExe = cmdArguments . toCmdArgument + -- | This is like Posix makeRelative, but assumes no sys links in the input -- paths. This allows the result to start with possibly many "../"s. Input -- paths must both be relative, or be on the same drive @@ -329,23 +437,25 @@ isGeneratedSource file = buildRoot <&> (`isPrefixOf` file) -- response file arguments are placed into a response file and escaped with @GHC.ResponseFile.escapeArgs@. withResponseFileIfLongCmd :: CmdResult c - => FilePath -- ^ Response base name. The reponse file is placed in @_build/rsp/\<Response base name\>@. - -> CmdArgument -- ^ Command and arguments before the response file arguments. - -> [String] -- ^ Response file aruguments. - -> CmdArgument -- ^ Command arguments after the response file arguments. + => FilePath -- ^ Response base name. The reponse file is placed in @_build/rsp/\<Response base name\>@. + -> ExeSpawnPath -- ^ The program to run. + -> CmdArgument -- ^ Command arguments before the response file arguments. + -> [String] -- ^ Response file aruguments. + -> CmdArgument -- ^ Command arguments after the response file arguments. -> Action c -withResponseFileIfLongCmd outputFilePath argsPre argsResp argsPost = do +withResponseFileIfLongCmd outputFilePath prog argsPre argsResp argsPost = do let cmdLineLengh = sum [ 1 + length arg -- add one to account for space inbetween arguments - | let CmdArgument args = argsPre <> toCmdArgument argsResp <> argsPost + | let CmdArgument args = + toCmdArgument prog <> argsPre <> toCmdArgument argsResp <> argsPost , Right arg <- args ] if cmdLineLengh < cmdLineLengthLimit - then cmd argsPre argsResp argsPost + then cmdExe prog argsPre argsResp argsPost else do rspFile <- responseFilePath outputFilePath writeFileAtomic rspFile (escapeArgs argsResp) - cmd argsPre ['@' : rspFile] argsPost + cmdExe prog argsPre ['@' : rspFile] argsPost -- | Convert a command's output file path to a response file path to be used for that command. -- Response files are placed in a dedicated @rps@ directory under the build directory. This avoids @@ -431,14 +541,16 @@ fixFile file f = do makeExecutable :: FilePath -> Action () makeExecutable file = do putProgressInfo $ "| Make " ++ quote file ++ " executable." - quietly $ cmd "chmod +x " [file] + chmodProg <- exeSpawnPath "chmod" + quietly $ cmdExe chmodProg ["+x", file] -- | Move a file. Note that we cannot track the source, because it is moved. moveFile :: FilePath -> FilePath -> Action () moveFile source target = do putProgressInfo =<< renderAction "Move file" source target - quietly $ cmd ["mv", source, target] + mvProg <- exeSpawnPath "mv" + quietly $ cmdExe mvProg [source, target] -- | Remove a file that doesn't necessarily exist. removeFile :: FilePath -> Action () @@ -456,13 +568,15 @@ createDirectory dir = do copyDirectory :: FilePath -> FilePath -> Action () copyDirectory source target = do putProgressInfo =<< renderAction "Copy directory" source target - quietly $ cmd ["cp", "-r", source, target] + cpProg <- exeSpawnPath "cp" + quietly $ cmdExe cpProg ["-r", source, target] -- | Move a directory. The contents of the source directory is untracked. moveDirectory :: FilePath -> FilePath -> Action () moveDirectory source target = do putProgressInfo =<< renderAction "Move directory" source target - quietly $ cmd ["mv", source, target] + mvProg <- exeSpawnPath "mv" + quietly $ cmdExe mvProg [source, target] -- | Remove a directory that doesn't necessarily exist. removeDirectory :: FilePath -> Action () ===================================== hadrian/src/Oracles/Setting.hs ===================================== @@ -6,7 +6,7 @@ module Oracles.Setting ( -- * Helpers ghcCanonVersion, cmdLineLengthLimit, targetSupportsRPaths, topDirectory, - libsuf, ghcVersionStage, bashPath, targetStage, crossStage, queryTarget, queryTargetTarget, + libsuf, ghcVersionStage, shPath, targetStage, crossStage, queryTarget, queryTargetTarget, isHostStage, -- ** Target platform things @@ -20,7 +20,6 @@ import System.Directory import System.Info.Extra import Hadrian.Expression import Hadrian.Oracles.TextFile -import Hadrian.Oracles.Path import Control.Monad.Trans (lift) import Control.Monad.Trans.Maybe (runMaybeT) @@ -133,9 +132,9 @@ buildSetting key stage = tgtConfig stage $ case key of getSetting :: ProjectSetting -> Expr c b String getSetting = expr . setting --- | The path to a Bourne shell interpreter. -bashPath :: Action FilePath -bashPath = setting BourneShell +-- | The path to a Bourne shell interpreter (@sh@). +shPath :: Action FilePath +shPath = setting BourneShell isWinHost :: Action Bool isWinHost = anyHostOs [OSMinGW32] @@ -203,11 +202,12 @@ ghcCanonVersion = do -- | Absolute path to the GHC source tree. topDirectory :: Action FilePath topDirectory = do - x <- fixAbsolutePathOnWindows =<< setting GhcSourcePath - canonicalize x - where - -- We must canonicalize as the source directory may be accessed via a symlink. See #22451. - canonicalize = if isWindows then return else liftIO . canonicalizePath + ghcSourcePath <- setting GhcSourcePath + if isWindows + -- On Windows: enforce the path convention of Note [MSYS paths]. + then return $ unifyPath ghcSourcePath + -- Otherwise: canonicalise to handle symlinks; see #22451. + else liftIO $ canonicalizePath ghcSourcePath ghcVersionStage :: Stage -> Action String ghcVersionStage (Stage0 {}) = setting GhcVersion ===================================== hadrian/src/Oracles/TestSettings.hs ===================================== @@ -13,7 +13,6 @@ import Hadrian.Oracles.TextFile import Oracles.Setting (topDirectory, setting, ProjectSetting(..), crossStage) import Packages import Settings.Program (programContext) -import Hadrian.Oracles.Path testConfigFile :: Action FilePath testConfigFile = buildRoot <&> (-/- "test/ghcconfig") @@ -156,8 +155,5 @@ getTestExePath testGhc pkg = do cross <- getBooleanSetting TestCrossCompiling let cross_prefix = if cross then dropWhileEnd ((/=) '-') (takeFileName compiler_path) else "" -- get relative path for the given program in the given stage - let make_absolute rel_path = do - abs_path <- liftIO (makeAbsolute rel_path) - fixAbsolutePathOnWindows abs_path - make_absolute (bindir </> (cross_prefix ++ programBasename pkg) <.> exe) + liftIO $ makeAbsolute (bindir </> (cross_prefix ++ programBasename pkg) <.> exe) -- get relative path for the given program in the given stage ===================================== hadrian/src/Rules/BinaryDist.hs ===================================== @@ -6,7 +6,6 @@ import Context import Data.Either import qualified Data.Set as Set import Expression -import Hadrian.Oracles.Path (fixUnixPathsOnWindows) import Oracles.Flavour import Oracles.Setting import Packages @@ -248,7 +247,9 @@ buildBinDistDir root conf@BindistConfig{..} = do -- Not going to work for cross ghcPkgName <- programName (vanillaContext Stage1 ghcPkg) - cmd_ (bindistFilesDir -/- "bin" -/- ghcPkgName) ["recache", "--package-db", bindistFilesDir -/- "lib" -/- "package.conf.d" ] + ghcPkgProg <- exeSpawnPath (bindistFilesDir -/- "bin" -/- ghcPkgName) + cmdExe ghcPkgProg ["recache", "--package-db", bindistFilesDir -/- "lib" -/- "package.conf.d" ] + :: Action () need ["docs"] @@ -364,8 +365,8 @@ bindistRules = do let ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform -- Finally, we create the archive <root>/bindist/ghc-X.Y.Z-platform.tar.xz - tarPath <- builderPath (Tar Create) - cmd [Cwd $ root -/- bindist_folder] tarPath + tarProg <- exeSpawnPath =<< builderPath (Tar Create) + cmdExe tarProg [Cwd $ root -/- bindist_folder] [ "-c", compressorTarFlag compressor, "-f" , ghcVersionPretty <.> "tar" <.> compressorExtension compressor , ghcVersionPretty ] @@ -393,16 +394,11 @@ bindistRules = do -- style paths. This happens because MSYS2 automatically converts env variables to -- Windows-style paths. To fix this, we convert ACLOCAL_PATH back to Unix style. -- This is done both in the boot Python script and here when building a bindist. + -- See Note [MSYS paths]. win_host <- isWinHost - env <- if not win_host - then pure [] - else do - aclocalPathMay <- getEnv "ACLOCAL_PATH" - case aclocalPathMay of - Nothing -> pure [] - Just aclocalPath -> do - unixAclocalPath <- fixUnixPathsOnWindows aclocalPath - pure [AddEnv "ACLOCAL_PATH" unixAclocalPath] + aclocalPathMay <- if win_host then getEnv "ACLOCAL_PATH" else pure Nothing + let env = [ AddEnv "ACLOCAL_PATH" (windowsToMsysPathList aclocalPath) + | Just aclocalPath <- [aclocalPathMay] ] buildWithCmdOptions env $ target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] [] @@ -568,7 +564,8 @@ createVersionWrapper executable_stage pkg versioned_exe install_path = do | pkg == ghciWrapper = (1 :: Int) | otherwise = 0 - cmd ghcPath (["-no-hs-main", "-o", install_path, "-I"++version_wrapper_dir + ghcProg <- exeSpawnPath ghcPath + cmdExe ghcProg (["-no-hs-main", "-o", install_path, "-I"++version_wrapper_dir , "-optc-DEXE_PATH=\"" ++ versioned_exe ++ "\"" , "-optc-DINTERACTIVE_PROCESS=" ++ show interactive ] ++ wrapper_files) ===================================== hadrian/src/Rules/Changelog.hs ===================================== @@ -42,8 +42,9 @@ changelogRules = do top <- topDirectory let outFile = top -/- "docs" -/- "users_guide" -/- version ++ "-notes.rst" - quietly $ cmd (FileStdout outFile) - [progPath] [top -/- "changelog.d/", "--version", version] + prog <- exeSpawnPath progPath + quietly $ cmdExe prog (FileStdout outFile) + [top -/- "changelog.d/", "--version", version] :: Action () putSuccess $ "| Generated release notes: " ++ outFile ===================================== hadrian/src/Rules/Codes.hs ===================================== @@ -34,4 +34,5 @@ codes usage = do cmdLine = unwords ( codesProgram : args ) putBuild $ "| Computing " ++ describeUsage usage ++ " diagnostic codes." putBuild $ "| " <> cmdLine - cmd_ cmdLine + codesProg <- exeSpawnPath codesProgram + cmdExe codesProg args ===================================== hadrian/src/Rules/Lint.hs ===================================== @@ -19,11 +19,17 @@ lintRules = do "libraries" -/- "base" -/- "include" -/- "HsBaseConfig.h" %> \_ -> -- ./configure is called here manually because we need to generate -- HsBaseConfig.h, which is created from HsBaseConfig.h.in. ./configure - cmd_ (Cwd "libraries/base") "./configure" + runConfigure "libraries/base" "rts" -/- "include" -/- "ghcautoconf.h" %> \_ -> - cmd_ (Cwd "rts") "./configure" + runConfigure "rts" "rts" -/- "include" -/- "ghcplatform.h" %> \_ -> - cmd_ (Cwd "rts") "./configure" + runConfigure "rts" + +-- | Run a package's @configure@ script, from that package's directory. +runConfigure :: FilePath -> Action () +runConfigure dir = do + configureProg <- exeSpawnPath (dir -/- "configure") + cmdExe configureProg [Cwd dir] lint :: Action () -> Action () lint lintAction = do @@ -46,9 +52,8 @@ runHLint includeDirs defines dir = do hostArch <- (<> "_HOST_ARCH") <$> queryHostTarget queryArch let hlintYaml = dir </> ".hlint.yaml" defines' = hostArch : defines - cmdLine = unwords $ - [ "hlint" - , "--colour=never" + hlintArgs = + [ "--colour=never" , "-j" <> show threads ] ++ map ("--cpp-define=" <>) defines' ++ @@ -56,8 +61,10 @@ runHLint includeDirs defines dir = do [ "-h" <> hlintYaml , dir ] + cmdLine = unwords ("hlint" : hlintArgs) putBuild $ "| " <> cmdLine - cmd_ cmdLine + hlintProg <- exeSpawnPath "hlint" + cmdExe hlintProg hlintArgs base :: Action () base = do ===================================== hadrian/src/Rules/Nofib.hs ===================================== @@ -39,9 +39,10 @@ nofibRules = do -- the GHC to benchmark and perl to -- nofib's makefiles. let nofibArgs = ["WithNofibHc=" ++ (top -/- ghcPath)] - unit $ cmd (Cwd "nofib") [makePath] ["clean"] - unit $ cmd (Cwd "nofib") [makePath] (nofibArgs ++ ["boot"]) - (Exit e, Stdouterr log) <- cmd (Cwd "nofib") [makePath] nofibArgs + makeProg <- exeSpawnPath makePath + unit $ cmdExe makeProg (Cwd "nofib") ["clean"] + unit $ cmdExe makeProg (Cwd "nofib") (nofibArgs ++ ["boot"]) + (Exit e, Stdouterr log) <- cmdExe makeProg (Cwd "nofib") nofibArgs writeFileAtomic fp log if e == ExitSuccess then putVerbose $ "nofib log available at " ++ fp ===================================== hadrian/src/Rules/Test.hs ===================================== @@ -20,7 +20,6 @@ import qualified System.Directory as IO import GHC.Toolchain as Toolchain import GHC.Toolchain.Program as Toolchain -import Hadrian.Oracles.Path checkPprProgPath, checkPprSourcePath :: FilePath checkPprProgPath = "test/bin/check-ppr" <.> exe @@ -160,7 +159,8 @@ testRules = do bindir <- getBinaryDirectory testGhc test_args <- outOfTreeCompilerArgs let dynPrograms = hasDynamic test_args - cmd [bindir </> "ghc" <.> exe] $ + ghcProg <- exeSpawnPath (bindir </> "ghc" <.> exe) + cmdExe ghcProg $ concatMap (\p -> ["-package", pkgName p]) depsPkgs ++ ["-o", top -/- path, top -/- sourcePath] ++ mextra ++ @@ -177,7 +177,8 @@ testRules = do ghcConfigProgPath <- programPath =<< programContext stage0InTree ghcConfig cwd <- liftIO $ IO.getCurrentDirectory need [makeRelative cwd ghcPath, ghcConfigProgPath] - cmd [FileStdout $ root -/- ghcConfigPath] ghcConfigProgPath [ghcPath] + ghcConfigProg <- exeSpawnPath ghcConfigProgPath + cmdExe ghcConfigProg [FileStdout $ root -/- ghcConfigPath] [ghcPath] root -/- timeoutPath %> \_ -> timeoutProgBuilder @@ -292,11 +293,7 @@ relativePathStage s p = programPath =<< programContext s p absolutePathStage :: Stage -> Package -> Action FilePath absolutePathStage s p = - relativePathStage s p >>= make_absolute - where - make_absolute rel_path = do - abs_path <- liftIO (makeAbsolute rel_path) - fixAbsolutePathOnWindows abs_path + liftIO . makeAbsolute =<< relativePathStage s p -- | Given a test compiler and a hadrian dependency (target), check if we -- can build the target with the compiler ===================================== m4/find_python.m4 ===================================== @@ -37,12 +37,7 @@ AC_DEFUN([FIND_PYTHON],[ AC_MSG_WARN([Python 3.7 or later is required, but $PYTHON reports $PythonVersion]) ]) - dnl Canonicalise path for Windows - if test "$HostOS" = "mingw32" - then - PythonCmd=$(cygpath -m "$PYTHON") - else - PythonCmd="$PYTHON" - fi + PythonCmd="$PYTHON" + FP_CANONICALISE_WIN_PATH([PythonCmd]) AC_SUBST([PythonCmd]) ]) ===================================== m4/fp_canonicalise_win_path.m4 ===================================== @@ -0,0 +1,11 @@ +# FP_CANONICALISE_WIN_PATH(VARIABLE) +# ---------------------------------- +# On Windows, rewrite the value of the path VARIABLE to the mixed form: +# C:/foo/bar +# +# See Note [MSYS paths] in hadrian/src/Hadrian/Utilities.hs. +# +# Requires FPTOOLS_SET_PLATFORMS_VARS to have been run, for $windows. +AC_DEFUN([FP_CANONICALISE_WIN_PATH], +[AS_IF([test "$windows" = "YES" && test -n "$$1"], + [$1=`cygpath -m "$$1"`])])# FP_CANONICALISE_WIN_PATH ===================================== m4/fp_find_nm.m4 ===================================== @@ -9,12 +9,11 @@ AC_DEFUN([FP_FIND_NM], AC_MSG_ERROR([cannot find nm in your PATH]) fi fi + NmCmd="$NM" + FP_CANONICALISE_WIN_PATH([NmCmd]) if test "$HostOS" = "mingw32" then - NmCmd=$(cygpath -m "$NM") NM_STAGE0=$NmCmd - else - NmCmd="$NM" fi AC_SUBST([NmCmd]) if test "$HostOS" != "mingw32"; then ===================================== m4/fp_find_root.m4 ===================================== @@ -4,15 +4,8 @@ AC_DEFUN([FP_FIND_ROOT],[ AC_MSG_CHECKING(for path to top of build tree) - if test "$windows" = YES - then - dnl Make sure this is a c:/foo/bar (mixed) style path. Some parts of - dnl the build system might depend on it (such as the sed expression - dnl `"s|$(TOP)/||i"` in addCFileDeps in rules/build-dependencies.mk). - hardtop=$(cygpath -m "$(pwd)") - else - hardtop=$(pwd) - fi + hardtop=$(pwd) + FP_CANONICALISE_WIN_PATH([hardtop]) dnl Remove common automounter nonsense hardtop=`echo $hardtop | sed 's|^/tmp_mnt.*\(/local/.*\)$|\1|' | sed 's|^/tmp_mnt/|/|'` ===================================== m4/fp_prog_ar.m4 ===================================== @@ -10,9 +10,7 @@ if test -z "$fp_prog_ar"; then if test "$HostOS" = "mingw32" then AC_PATH_PROG([fp_prog_ar], [ar]) - if test -n "$fp_prog_ar"; then - fp_prog_ar=$(cygpath -m $fp_prog_ar) - fi + FP_CANONICALISE_WIN_PATH([fp_prog_ar]) else AC_CHECK_TARGET_TOOL([AR], [ar]) fp_prog_ar="$AR" ===================================== m4/fp_prog_ar_args.m4 ===================================== @@ -30,12 +30,8 @@ else fi fi]) fp_prog_ar_args=$fp_cv_prog_ar_args -if test "$HostOS" = "mingw32" -then - ArCmd=$(cygpath -m "$fp_prog_ar") -else - ArCmd="$fp_prog_ar" -fi +ArCmd="$fp_prog_ar" +FP_CANONICALISE_WIN_PATH([ArCmd]) AC_SUBST([ArCmd]) AC_SUBST([ArArgs], ["$fp_prog_ar_args"]) ===================================== m4/fp_prog_sh.m4 ===================================== @@ -6,10 +6,6 @@ AC_DEFUN([FP_PROG_SH], AC_REQUIRE([FPTOOLS_SET_PLATFORMS_VARS]) dnl for $windows AC_ARG_VAR(SH,[Use as the full path to a Bourne shell. [default=autodetect]]) AC_PATH_PROGS([SH], [sh bash]) - if test "$windows" = "YES"; then - dnl use mixed (-m) mode to get C:/mingw64/... with forward slashes. - dnl windows (-w) mode will give us C:\... and mess with escaping. - SH=`cygpath -m "$SH"` - fi + FP_CANONICALISE_WIN_PATH([SH]) AC_SUBST([SH])[]dnl ])# FP_PROG_SH ===================================== m4/fptools_alex.m4 ===================================== @@ -10,7 +10,9 @@ dnl https://gitlab.haskell.org/ghc/ghc/wikis/building/preparation/tools dnl AC_DEFUN([FPTOOLS_ALEX], [AC_PATH_PROG(ALEX,[alex],) -AC_SUBST(AlexCmd,$ALEX) +AlexCmd="$ALEX" +FP_CANONICALISE_WIN_PATH([AlexCmd]) +AC_SUBST(AlexCmd) AC_CACHE_CHECK([for version of alex], fptools_cv_alex_version, changequote(, )dnl [if test x"$AlexCmd" != x; then ===================================== m4/fptools_happy.m4 ===================================== @@ -10,7 +10,9 @@ dnl https://gitlab.haskell.org/ghc/ghc/wikis/building/preparation/tools dnl AC_DEFUN([FPTOOLS_HAPPY], [AC_PATH_PROG(HAPPY,[happy],) -AC_SUBST(HappyCmd,$HAPPY) +HappyCmd="$HAPPY" +FP_CANONICALISE_WIN_PATH([HappyCmd]) +AC_SUBST(HappyCmd) AC_CACHE_CHECK([for version of happy], fptools_cv_happy_version, changequote(, )dnl [if test x"$HappyCmd" != x; then ===================================== utils/hsc2hs ===================================== @@ -1 +1 @@ -Subproject commit 3b3f18fff306cb95b71acc7c866461f552e0aeaf +Subproject commit 0ac065c152e8fbae6c05e9db424baee66b98797e View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c673ecf057deee858acbbaa7e6c920… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c673ecf057deee858acbbaa7e6c920… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/sjakobi/T24813] X86 NCG: use 32-bit POPCNT for sub-word popcounts
by Simon Jakobi (@sjakobi) 06 Sep '26

06 Sep '26
Simon Jakobi pushed to branch wip/sjakobi/T24813 at Glasgow Haskell Compiler / GHC Commits: 4b7193ab by Simon Jakobi at 2026-09-06T02:26:01+02:00 X86 NCG: use 32-bit POPCNT for sub-word popcounts For MO_PopCnt at W8/W16, use 32-bit POPCNT instead of the 16-bit form. A 32-bit write zero-extends the result to the full register, so the separate zero-extension of the result is no longer needed. Also skip zero-extending the argument when it is visibly already zero-extended, as in popCount on Word8, which calls popCnt8# on word8ToWord# x. For the byte-wise popcount loop from #24813 this shrinks the popcount sequence from 5 instructions to 3. Assisted-by: Claude Fable 5.1 - - - - - 5 changed files: - + changelog.d/ncg-x86-subword-popcnt - compiler/GHC/CmmToAsm/X86/CodeGen.hs - + testsuite/tests/codeGen/should_gen_asm/T24813.asm - + testsuite/tests/codeGen/should_gen_asm/T24813.cmm - testsuite/tests/codeGen/should_gen_asm/all.T Changes: ===================================== changelog.d/ncg-x86-subword-popcnt ===================================== @@ -0,0 +1,10 @@ +section: compiler +synopsis: The x86 native code generator now emits shorter code for ``popCnt8#`` + and ``popCnt16#`` with ``-msse4.2`` +description: + Sub-word popcounts now use the 32-bit ``popcnt`` instruction, which + zero-extends its result for free, and skip zero-extending an argument that + is already zero-extended, as in ``popCount`` on ``Word8`` or ``Word16``. + The popcount sequence shrinks from up to five instructions to one to three. +mrs: !16640 +issues: #24813 ===================================== compiler/GHC/CmmToAsm/X86/CodeGen.hs ===================================== @@ -6739,20 +6739,23 @@ genPopCnt bid width dst src = do True -> do code_src <- getAnyReg src - src_r <- getNewRegNat format + -- Sub-word popcounts use 32-bit POPCNT, whose write zero-extends the + -- result to the full register. + src_r <- getNewRegNat (max II32 format) let dst_r = getRegisterReg platform (CmmLocal dst) + -- A sub-word argument is a full Word# whose upper bits may be + -- dirty, so zero-extend it unless it visibly already is. + zx_src + | CmmMachOp (MO_UU_Conv from _) [_] <- src, from <= width + = nilOL + | otherwise + = unitOL (MOVZxL format (OpReg src_r) (OpReg src_r)) return $ code_src src_r `appOL` - (if width == W8 then - -- The POPCNT instruction doesn't take a r/m8 - unitOL (MOVZxL II8 (OpReg src_r) (OpReg src_r)) `appOL` - unitOL (POPCNT II16 (OpReg src_r) dst_r) - else - unitOL (POPCNT format (OpReg src_r) dst_r)) `appOL` (if width == W8 || width == W16 then - -- We used a 16-bit destination register above, - -- so zero-extend - unitOL (MOVZxL II16 (OpReg dst_r) (OpReg dst_r)) - else nilOL) + zx_src `appOL` + unitOL (POPCNT II32 (OpReg src_r) dst_r) + else + unitOL (POPCNT format (OpReg src_r) dst_r)) False -> -- generate C call to hs_popcntN in ghc-prim ===================================== testsuite/tests/codeGen/should_gen_asm/T24813.asm ===================================== @@ -0,0 +1,10 @@ +popcnt8: + movzbl + popcnt + movq + jmp +popcnt16: + movzwl + popcnt + movq + jmp ===================================== testsuite/tests/codeGen/should_gen_asm/T24813.cmm ===================================== @@ -0,0 +1,16 @@ +#include "Cmm.h" + +// Popcount of a zero-extended sub-word value should be a single +// zero-extending load followed by one POPCNT (#24813). + +popcnt8 (W_ p) { + W_ r; + (r) = prim %popcnt8(%zx64(bits8[p])); + return (r); +} + +popcnt16 (W_ p) { + W_ r; + (r) = prim %popcnt16(%zx64(bits16[p])); + return (r); +} ===================================== testsuite/tests/codeGen/should_gen_asm/all.T ===================================== @@ -27,6 +27,7 @@ test('T25233', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O']) test('T25233b', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, '']) +test('T24813', is_amd64_codegen, compile_cmp_asm, ['cmm', '-msse4.2']) is_aarch64_codegen = [ unless(arch('aarch64'), skip), when(unregisterised(), skip), View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4b7193ab6a22557a55650cdb8efd1cc… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4b7193ab6a22557a55650cdb8efd1cc… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/sjakobi/T24813] 217 commits: CorePrep: Don't speculatively evaluate bindings that we have already discovered to be absent
by Simon Jakobi (@sjakobi) 06 Sep '26

06 Sep '26
Simon Jakobi pushed to branch wip/sjakobi/T24813 at Glasgow Haskell Compiler / GHC Commits: 9b714c4c by Zubin Duggal at 2026-07-05T09:40:36+05:30 CorePrep: Don't speculatively evaluate bindings that we have already discovered to be absent In #25924, we segfault because speculation forces a projection out of a RUBBISH dictionary (which we generated because it absent). Solution: Don't speculate on bindings we already know are absent. Fixes 25924 - - - - - 4a59b3ee by Zubin Duggal at 2026-07-05T09:40:36+05:30 Don't make absent fillers for terminating types In #25924 we discovered that we could speculatively evaluate an absent filler for a dictionary, and project a field (a superclass selector) out of it, resulting in segfaults. Solution: Never make an absent filler or rubbish literal for a terminating type like a dictionary. mkAbsentFiller returns Nothing for isTerminatingType, so worker/wrapper and the specialiser keep the real argument instead. Some small metric decreases because we do a little less work in the simplifier now. Metric Decrease: T9872a T9872b T9872c TcPlugin_RewritePerf - - - - - 383ddcd4 by Alan Zimmerman at 2026-07-06T07:08:16-04:00 EPA: Move the 'where' annotation for PatSynBind This allows us to move it out of the MatchGroup exact print annotation too - - - - - 66d1a5d5 by fendor at 2026-07-07T16:57:56-04:00 Add 'backendInfoTableMapValidity' backend predicate Check whether the backend supports the `-finfo-table-map` flag and ignore it otherwise. Improve by-design documentation of `backendCodeOutput`. `Backend` is **abstract by design**. Make this clearer in `backendCodeOutput` which is incorrectly being used as a proxy for `Backend`. Instead, define the desired property predicates in GHC.Driver.Backend In the process, make `backendCodeOutput` total. - - - - - 74f1071d by fendor at 2026-07-07T16:57:56-04:00 Add failing test for `-finfo-table-map` and bytecode backend If you compile a module using the bytecode backend, with -finfo-table-map, then the info table map doesn't get populated for the module. This is because the -finfo-table-map code path is implemented mostly in the StgToCmm phase which isn't run when creating bytecode. Ticket #27039 - - - - - 28d63bca by mangoiv at 2026-07-07T16:59:16-04:00 ci: don't fail nightly if there have been no changes that night Fixes #27127 - - - - - 4ebfc478 by Rodrigo Mesquita at 2026-07-08T04:47:53-04:00 ttg: Using ShortText over FastString in the AST To make the AST independent of GHC, this commit replaces usages of `FastString` with `HText` in the AST, killing the last edge from Language.Haskell.* to GHC.* modules. Even though we /do/ want to use FastStrings in general -- critically in Names or Ids -- there is no particular reason for the FastStrings that occur in the AST proper to be FastStrings. Strings in the AST are typically unique and don't benefit particularly from being interned FastStrings with Uniques for fast comparison. `HText` is a type synonym for `ShortText` which uses GHC's Modified UTF-8 encoding exclusively. Modified UTF-8 must be used to represent the Haskell AST because the Haskell Report allows surrogate code points. `Data.Text.Text` functions use Standard UTF-8 which replace surrogates with a placeholder value, thus `Data.Text.Text` is unsuitable for AST strings. See the `Language.Haskell.Syntax.Text` module header for more details. Final progress towards #21592 Closes #21628 - - - - - d910b353 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00 Update equality-type documenation in GHC.Builtin.Types.Prim Fix #27466 - - - - - b2530542 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00 Honour -dsuppress-coercions in GHC.Core.TyCo.pprCo Fixes #27467 - - - - - 9a73179a by Facundo Domínguez at 2026-07-08T04:49:26-04:00 Add item to MR checklist asking to squash fixup commits after approval The checklist has an item that reads All commits are either individually buildable or squashed. This item could be checked immediately after sending the merge request though. If reviewers ask for amends later on, and the author amends the merge request, there was no item that would remind the contributors to squash the fixup commits before landing. This commit adds a new item After all approvals and before landing: all fixup commits are squashed with their originating commits. which should be harder to mark as done before approvals have been given. - - - - - ed09895d by Andreas Klebinger at 2026-07-08T16:53:27-04:00 Fix a profiling race condition resulting in segfaults. StgToCmm: Don't assume tagged FUN closures in closureCodeBody. When entering a closure the self/node pointer might not be tagged in some situations when a thunk is evaluated by multiple threads. So we most AND away the tag bits rather than subtracting an expected tag. Apply.cmm: Fix a race condition occuring when a thunk is mutated during GC. In stg_ap_0_fast when might need to run GC before entering a thunk. If this happens another thread or the GC itself might mutate the closure making entering it no longer valid. We now check for this. Add test and changelog for #27123 fixes. - - - - - 67c03eb2 by Cheng Shao at 2026-07-08T16:54:09-04:00 ghc-heap: fix invalid srtlen returned by peekItbl when no-TNTC This patch fixes the no-TNTC code path of `peekItbl` so that it looks at the right memory address when reading the `srt` field from the `StgInfoTable_` struct. Also adds a `T27465` regression test that reproduces the bug on no-TNTC builds before the fix. Fixes #27465. Co-authored-by: Codex <codex(a)openai.com> - - - - - 2ecabb4f by Zubin Duggal at 2026-07-09T09:23:25-04:00 hadrian: binary-dist-dir should not be the default target Revert behaviour to pre 23c9b6c392f52ec9d7a8618b204ff6b885f5fba2 In 23c9b6c392f52ec9d7a8618b204ff6b885f5fba2, we applied the following behaviour change: ``` hadrian: Build stage 2 cross compilers ... * hadrian: Make binary-dist-dir the default build target. This allows us to have the logic in one place about which libraries/stages to build with cross compilers. Fixes #24192 ``` This is a major regression to development experience, a plain hadrian/build --freeze1 now takes ages because we rebuild all docs (which need to go in the binary dist dir). `binary-dist-dir` is the wrong default target for regular GHC development work Fixes #27445 - - - - - e16388e3 by Zubin Duggal at 2026-07-09T09:23:25-04:00 .gitignore: Add the hadrian system.config introduced by commit 23c9b6c392f52ec9d7a8618b204ff6b885f5fba2 Since commit 23c9b6c392f52ec9d7a8618b204ff6b885f5fba2 Author: Matthew Pickering <matthewtpickering(a)gmail.com> Date: Thu Dec 21 16:17:41 2023 +0000 hadrian: Build stage 2 cross compilers ./configure produces /hadrian/cfg/system.config.{host,target} Add these to .gitignore - - - - - 7e8abf41 by Alan Zimmerman at 2026-07-09T09:24:12-04:00 EPA: Replace AnnListItem with simply [TrailingAnn] Remove the unnecessary wrapper around a single field. - - - - - 29032f17 by Zubin Duggal at 2026-07-09T09:24:58-04:00 testsuite: Keep real reason for fragile test failures - - - - - c34e03a7 by Zubin Duggal at 2026-07-09T09:24:58-04:00 testsuite: Fall back to the failure reason for empty JUnit bodies - - - - - 409d40f0 by Zubin Duggal at 2026-07-09T09:24:58-04:00 testsuite: Show output diffs in JUnit output Also refactor compare_outputs to return essentially a `Maybe Diff` (`CompareOutput`) instead of a bool, but more pythonic. This allows us to pass the diff through nice. - - - - - 06fee1ab by Zubin Duggal at 2026-07-09T09:24:58-04:00 perf notes: include stat deviation and acceptance window in notes so they show up in gitlab - - - - - 57c0f32c by mangoiv at 2026-07-10T11:08:38-04:00 driver: enable -finter-module-far-jumps by default this fixes a compatibility bug with certain binutils/gcc versions where we were seeing jump offset overflow errors. This commit can probably reverted if we stop supporting the problematic binutils/gcc verions (2.44 and 14.2, respectively) Reolves #26994 - - - - - 4396a6f2 by Andrea Vezzosi at 2026-07-10T11:09:25-04:00 [Fix #27287] preserve ModBreaks in ModIface - - - - - ed261a7e by Cheng Shao at 2026-07-14T17:59:38-04:00 hadrian: fix HLS support This patch fixes hadrian's HLS support so one can rely on HLS when working on the hadrian codebase. Fixes #27480. Not building/linking shared libraries for hadrian is a severely premature optimization; this top-level setting in `cabal.project` only affects home packages while the dependencies in the cabal store are built with vanilla/dynamic anyway, and even adding dynamic builds to home packages would not be costly due to cabal's usage of `-dynamic-too`. - - - - - eee8ec5b by Cheng Shao at 2026-07-14T18:00:20-04:00 compiler: fix miscompiled %load_relaxed, add missing %store_relaxed This patch fixes the %load_relaxed cmm primop compilation logic to correctly use relaxed memory ordering, and adds the missing %store_relaxed primop. Parsing logic of %load/%store with explicit ordering is covered in the AtomicFetch test case. Fixes #27483. Co-authored-by: Codex <codex(a)openai.com> - - - - - 1718230f by Alan Zimmerman at 2026-07-14T18:01:06-04:00 EPA: Keep binds and sigs together in HsValBindsLR We combine them into a single list for GhcPs, wrapped in the ValBind data type, which is the bind equivalent of ValD, having constructors for binds and sigs. This simplifies exact print processing, especially when using it to update the contents of local binds, as we no longer need AnnSortKey BindTag - - - - - 6bd1ad2a by Andreas Klebinger at 2026-07-14T18:01:49-04:00 Bump nofib submodule to account for MonoLocalBinds. New versions of GHC enable MonoLocalBinds by default. This breaks some of the benchmarks. I've fixed this and this bump pulls in that fix. - - - - - 7eb0f1c9 by Cheng Shao at 2026-07-14T18:02:31-04:00 testsuite: fix bytecodeIPE test under +ipe flavours This patch fixes the bytecodeIPE test under +ipe flavours. It used to fail under +ipe because the RTS is built with IPE info, then stg_AP_info in RTS carries IPE info, so whereFrom wouldn't return Nothing. Now the test checks IPE info of a datacon in the ghci-loaded module which is not affected by whether the RTS is built with IPE info or not. Fixes #27498. Co-authored-by: Codex <codex(a)openai.com> - - - - - ef038aae by cydparser at 2026-07-15T04:35:41-04:00 Reduce bytes allocated for `capabilities` in RTS (fixes #27487) In rts/Capability.c, `capabilities` is an array of pointers, but it was allocated as if it were an array of Capability's. - - - - - d377e83e by Cheng Shao at 2026-07-15T04:36:27-04:00 rts: fix missing UNTAG in stg_readTVarIOzh This patch fixes missing UNTAG on the current value closure read from StgTVar. UNTAG is a no-op when it's stg_TREC_HEADER_info which is word aligned; it may be a tagged closure, and reading info table from the tagged address is an unaligned load which may cause issues on platforms with strict alignment requirements. Co-authored-by: Codex <codex(a)openai.com> - - - - - 8ed03842 by Cheng Shao at 2026-07-15T04:36:27-04:00 rts: fix missing UNTAG in stg_control0zh_ll This patch fixes missing UNTAG on the cont closure returned by captureContinuationAndAbort. In case it's not NULL, captureContinuationAndAbort returns a tagged StgContinuation closure, in which case it must be untagged before accessing the apply_mask_frame field. In the past it worked out of luck: when apply_mask_frame was NULL then mask_frame_offset is also 0 so the control flow didn't diverge to a wrong path. Still, this is horribly wrong and will crash once StgContinuation struct is refactored and fields are shuffled around. Co-authored-by: Codex <codex(a)openai.com> - - - - - 5aa7000a by Cheng Shao at 2026-07-15T04:37:08-04:00 compiler: fix redundant AP thunk codegen when not using -ticky-ap-thunk This patch fixes a double negation confusion in !7525 that results in some redundant AP thunk code generation when not using -ticky-ap-thunk. Now, we use `stgToCmmUseStdApThunk` to indicate whether precomputed AP thunks in the RTS should be used, which defaults to `True`, unless `-ticky-ap-thunk` is passed. `-finfo-table-map` now also implies `-ticky-ap-thunk`, since when doing IPE profiling we want the generated AP thunks to be unique. Fixes #27502. ------------------------- Metric Decrease: T3064 ------------------------- Co-authored-by: Codex <codex(a)openai.com> - - - - - d43a7b7a by Brian McKenna at 2026-07-15T20:10:04+02:00 Strip ticks when desugaring bool guards The special `considerAccessible` pattern was broken when compiling with debug info. Compiling with debug info wraps expressions with `SourceNote` ticks, which broke the internals of the `desugarBoolGuard` function. Ticks are now ignored within this function. Fixes #27360 - - - - - ede4b17b by Ben Gamari at 2026-07-15T22:59:53-04:00 base: Display ExceptionContext in WhileHandling's textual description As originally-implemented the implementation for `WhileHandling(displayExceptionAnnotation)` would display the `ExceptionContext` of the exception which it carries (as this was the behavior of `displayException`, in terms of which `displayExceptionAnnotation` was implemented). However, in 284ffab3 the definition of `SomeException(displayException)` was changed to exclude the `ExceptionContext`. This means that `WhileHandling(displayExceptionAnnotation)` fails to describe the provenance of the exception which it captures, greatly limiting its utility. Return the implementation to its originally-specified behavior by implementing `WhileHandling(displayExceptionAnnotation)` in terms of `displayExceptionWithInfo`. Fixes #27456. - - - - - 0f64f348 by Cheng Shao at 2026-07-16T15:41:08+00:00 ci: add missing docker permission workaround in abi-test job - - - - - 660cb239 by Cheng Shao at 2026-07-16T19:37:48+00:00 bindist: Fix make install -j race condition on macos/freebsd This patch fixes make install -j race condition on macos/freebsd. BSD install fails with EEXIST when multiple install processes concurrently create the same prefix directory. So we add an `install_dirs` prerequisite job that sequentially creates the directories for subsequent jobs to work with. Fixes #27499. Co-authored-by: Codex <codex(a)openai.com> - - - - - 08130257 by Cheng Shao at 2026-07-16T19:37:48+00:00 ci: run bindist make install with -j This patch makes the ci scripts run `make install` with `-j` to reduce wall clock time when installing the bindist, see related issue for benchmark numbers. This only affects ghc ci logic, the user-facing default is up to distributors and is still `-j1`. Closes #27029. - - - - - d5ae6906 by Adam Gundry at 2026-07-17T04:57:43-04:00 Mark various language extension flags as deprecated (see #27329) The following language extensions are now deprecated: - AlternativeLayoutRule - AlternativeLayoutRuleTransitional - ParallelArrays - PolymorphicComponents - Rank2Types In addition, the warning `-Walternative-layout-rule-transitional` has been marked as deprecated, as it is emitted only under the deprecated extension `XAlternativeLayoutRuleTransitional`. - - - - - fe3b059c by Andrew Lelechenko at 2026-07-17T04:58:26-04:00 base: re-export GHC.Environment.getFullArgs from System.Environment CLC proposal https://github.com/haskell/core-libraries-committee/issues/431 - - - - - 722236dd by sheaf at 2026-07-18T08:48:31-04:00 Coercion optimisation: avoid double-Sym for InstCo Ticket #27374 pointed out an issue with GHC.Core.Coercion.Opt.optCoercion's handling of InstCo: it contravened (LC2) in Note [The LiftingContext in optCoercion] because it applied the ambient 'sym' to a coercion that was then added to the lifting context substitution. Fixes #27374 Co-authored-by: Simon Jakobi <simon.jakobi(a)gmail.com> - - - - - ff70fc75 by sheaf at 2026-07-18T08:48:31-04:00 Coercion optimisation: avoid exponential behaviour The change to coercion optimisation of 'InstCo' in the previous commit introduces exponential behaviour to the coercion optimiser. To avoid this, this commit provides a way to push in 'Sym' of an already-optimised coercion: GHC.Core.Coercion.Opt.mkDeepSymCo. See Note [Pushing Sym without re-optimising] in GHC.Core.Coercion.Opt. - - - - - dfef27f0 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Move THREADED_RTS-conditional struct members to end of Capability Accessing members of the Capability struct from CMM code rely on accessor macros. (The macros are generated by deriveConstants). These macros have a single definition. This means that the offsets of all struct members must *not* vary based on THREADED_RTS vs !THREADED_RTS. This requires that any struct members that are conditional on THREADED_RTS must occur after the unconditional struct members. Hence we move all the ones that are conditional on THREADED_RTS to the end. Add a deriveConstants entry for the iomgr member of the Capability struct, which was the motivation for this change. Add warning messages to help our future selves. Debugging this took me a couple hours in gdb! - - - - - c254e022 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Make the IOManager API use CapIOManager rather than Capability This makes the API somewhat more self-contained and more consistent. Now the IOManager API and each of the backends takes just the I/O manager structure. Previously we had a bit of a mixture, depending on whether the function needed access to the Capability or just the CapIOManager. We still need access to the cap, so we introduce a back reference to reach the capability, via iomgr->cap. Convert all uses in select and poll backends, but not win32 ones. Convert callers in the scheduler and elsewhere. Also convert the three CMM primops that call IOManager APIs. They just need to use Capability_iomgr(MyCapability()). - - - - - 4f3d8f31 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Split posix/MIO.c out of posix/Signals.c The MIO I/O manager was secretly living inside the Signals file. Now it gets its own file, like any other self-respecting I/O manager. - - - - - 52ce04a9 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Rationalise some scheduler run queue utilities Move them all to the same place in the file. Make some static that were used only internally. Also remove a redundant assignment after calling truncateRunQueue that is already done within truncateRunQueue. - - - - - 75bbdebc by Duncan Coutts at 2026-07-18T08:49:12-04:00 Rename initIOManager{AfterFork} to {re}startIOManager These are more accurate names, since these actions happen after initialisation and are really about starting (or restarting) background threads. - - - - - 724c0517 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Free per-cap I/O managers during shutdown and forkProcess Historically this was not strictly necessary. The select and win32 legacy I/O managers did not maintain any dynamically allocated resources. The new poll one does (an auxillary table), and so this should be freed. After forkProcess, all threads get deleted. This includes threads waiting on I/O or timers. So as of this patch, resetting the I/O manager is just about tidying things up. For example, for the poll I/O manager this will reset the size of the AIOP table (which otherwise grows but never shrinks). In future however the re-initialising will become neeecessary for functionality, since some I/O managers will need to re-initialise wakeup fds that are set CLOEXEC. - - - - - c007d122 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Add a TODO to the MIO I/O manager The direction of travel is to make I/O managers per-capability and have all their state live in the struct CapIOManager. The MIO I/O manager however still has a number of global variables. It's not obvious how handle these globals however. - - - - - b65ab7b3 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Add a FIXME note in the Poll I/O manager - - - - - daf2bd6f by Duncan Coutts at 2026-07-18T08:49:12-04:00 Add missing updateRemembSetPushClosure in poll I/O manager For the non-moving GC. - - - - - e33ca830 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Minor doc improvement to struct StgAsyncIOOp member outcome Mention the enumeration names, as well as their numeric values. The rest of the code uses the enum names. - - - - - 4edd2579 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Minor doc improvements for StgTSOBlockInfo Clarify that certain union members are used only by certain legacy I/O managers. Hopefully we will be able to remove these at some point. - - - - - 536bedbb by Duncan Coutts at 2026-07-18T08:49:12-04:00 Avoid exporting various win32-specific rts symbols The BeginPrivate.h / EndPrivate.h scheme works perfectly well on Windows, but all of the rts/win32/*.h files were not using it. - - - - - 8139b5ac by Duncan Coutts at 2026-07-18T08:49:12-04:00 Remove wakeupIOManager, ioManagerWakeup and setIOManagerWakeupFd We no longer need wakeupIOManager for the threaded RTS case, so we can remove it and the bits only needed to support it. This includes the pipe/eventfd fd shared between the RTS and the in-library I/O manager used for waking up the I/O manager thread. The pipe/eventfd still exists, but it no longer has to be communicated to the RTS, since the RTS no longer needs to use it. So we remove the RTS API export setIOManagerWakeupFd, and remove uses of it within the I/O managers in ghc-internal. - - - - - 74fe7c66 by Duncan Coutts at 2026-07-18T08:49:12-04:00 Add a new interruptIOManager API for the I/O managers It will be used to interrupt awaitCompletedTimeoutsOrIO. Also update the return type and docs for awaitCompletedTimeoutsOrIO to have it return false when it gets interrupted, and have no useful post condition in that case. - - - - - 38792843 by Duncan Coutts at 2026-07-18T08:49:13-04:00 Add interruptIOManager support for select I/O manager Uses the FdWakup mechanism. - - - - - 2f3b00aa by Duncan Coutts at 2026-07-18T08:49:13-04:00 Add interruptIOManager support for poll I/O manager Uses the FdWakup mechanism. A quirk we have to cope with is that we now need to poll one more fd -- the wakeup_fd_r -- but this fd has no corresponding entry in the aiop_table. This is awkward since we have set up our aiop_poll_table to be an auxilliary table with matching indicies. The solution this patch uses (and described in the comments) is to have two tables: struct pollfd *aiop_poll_table, *full_poll_table; and to have the aiop_poll_table alias the tail of the full_poll_table. The head entry in the full_poll_table is the extra fd. So we poll the full_poll_table, while the aiop_poll_table still has matching indicies with the aiop_table. Hurrah for C aliasing rules. - - - - - cee50131 by Duncan Coutts at 2026-07-18T08:49:13-04:00 Add interruptIOManager support for win32 legacy I/O manager And remove unused related helper resetAbandonRequestWait. It is not called because the event is created in auto-reset mode, so never needs to be reset manually. - - - - - cf453143 by Duncan Coutts at 2026-07-18T08:49:13-04:00 Note lack of interruptIOManager support for WinIO I/O manager Though there's a plausible design, we can't sanely test it at the moment due to related WinIO bugs. Filed as issue #27403. - - - - - 1b74a0ad by Duncan Coutts at 2026-07-18T08:49:13-04:00 Be more explicit about enum IOReadOrWrite values, and type within cmm Belt and braces. - - - - - b388d093 by Brian McKenna at 2026-07-18T17:51:50-04:00 Ignore ticks in the pattern-match term oracle The term-oracle in the pattern-match checker is keyed by a canonical form of the scrutinee, computed by `makeDictsCoherent`. That canonical form was tick-sensitive: two occurrences of an otherwise identical expression that happened to carry different ticks were treated as distinct values, breaking long-distance information. This shows up in practice under `-finfo-table-map`, because the desugarer wraps every record-selector use site in a `SourceNote` carrying that site's span. For example: data Box = Box { unBox :: Maybe Int } f b = case unBox b of Nothing -> 0 Just _ -> let Just x = unBox b in x The two `unBox b` expressionss carry different SourceNote spans, the pattern-match checker sees them as different, the long-distance information from the outer `Just _` branch never reaches the let-pattern, and `Just x = unBox b` is wrongly reported as non-exhaustive. We now strip all ticks in `makeDictsCoherent`. This is documented as Wrinkle (UD1) of Note [Unique dictionaries in the TmOracle CoreMap]. Fixes #27314 - - - - - c23e1acb by Mrjtjmn at 2026-07-18T17:52:45-04:00 Add explanations for unsolved Typeable constraints This commit adds explanations for unsolved 'Typeable' constraints. GHC will now provide additional explanations for an unsolved constraint of the form 'Typeable ty', explain why GHC did not solve Typeable constraint. e.g.: - 'ty' is a polymorphic type (e.g. forall a. a -> a) - 'ty' is a qualified type (e.g. Eq Int => Int) - 'ty' is an unboxed sum type - 'ty' is an unreduced type family application - 'ty' whose kind is not typeable Fixes #26532 - - - - - cbef021e by Artem Pelenitsyn at 2026-07-19T07:49:55-04:00 ghc-internal: Lock.hs: fix typo and indentation - - - - - 42918646 by Duncan Coutts at 2026-07-19T07:50:36-04:00 Fix failing test GcStaticPointers for non-moving GC Minor mistake in asserting something before checking for that same thing. Specifically, Bdescr asserts HEAP_ALLOCED_GC, but Bdescr was being used prior to a guard that checks HEAP_ALLOCED_GC. The solution is just to move the use of Bdescr after the guard. Thanks to Simon Jakobi for identifying the problem. - - - - - c2f6dcd4 by Sasha Bogicevic at 2026-07-20T10:31:56+02:00 Improve error messages for invalid record wildcards Record wildcard hints are now shown in more contexts and include constructor arity; matching with `..` on a fieldless constructor now produces a dedicated error message. Fixes #21101 - - - - - 4c02e76b by Duncan Coutts at 2026-07-21T10:37:21-04:00 Mark test T27105 as fragile, citing issue #27522 Scheduler fairness is fine, except when it isn't. And it isn't on CI machines surprisingly often! See the issue for details. - - - - - 43dd2b15 by Recursion Ninja at 2026-07-21T17:09:53-04:00 Resolving many TTG related orphan type-class instances This is part a technical debt removal effort made possible now that separating out the AST via TTG has come to a close. As the AST in 'L.H.S' has been incrementally separated from the GHC internals, there are many accumulated orphan instance of 'Binary', 'NFData', 'Outputable', and 'Uniquable'. The orphan instance of data-types from within 'L.H.S' have had their orphan instances moved to either: 1. The module which defines the data-type 2. The module which defines the type-class; i.e. moving an orphan 'Binary' instance to 'GHC.Utils.Binary' Orphan instances resolved (37): | Data-type | Resolved instance(s) | Former orphan module(s) | | -------------------- | -------------------------- | ------------------------- | | Role | Binary, NFData, Outputable | GHC.Core.Coercion.Axiom | | SrcStrictness | Binary, NFData, Outputable | GHC.Core.DataCon | | SrcUnpackedness | Binary, NFData, Outputable | GHC.Core.DataCon | | Fixity | Binary, Outputable | GHC.Hs.Basic | | FixityDirection | Binary, Outputable | GHC.Hs.Basic | | LexicalFixity | Outputable | GHC.Hs.Basic | | CCallTarget | NFData | GHC.Hs.Decls.Foreign | | CType | NFData | GHC.Hs.Decls.Foreign | | Header | NFData | GHC.Hs.Decls.Foreign | | OverlapMode | Binary, NFData | GHC.Hs.Decls.Overlap | | WithHsDocIdentifiers | NFData, Outputable | GHC.Hs.Doc | | HsDocString | NFData | GHC.Hs.DocString | | HsDocStringChunk | Binary, Outputable | GHC.Hs.DocString | | HsDocStringDecorator | Binary, Outputable | GHC.Hs.DocString | | NamespaceSpecifier | Outputable | GHC.Hs.ImpExp | | ForAllTyFlag | Binary, NFData, Outputable | GHC.Hs.Specificity | | Specificity | Binary, NFData | GHC.Hs.Specificity | | PromotionFlag | Binary, Outputable | GHC.Types.Basic | | FieldLabelString | Outputable, Uniquable | GHC.Types.FieldLabel | | InlinePragma | Binary | GHC.Types.InlinePragma | ------------------------- Metric Decrease: hard_hole_fits ------------------------- Closes #21262, #27469 - - - - - ab9ab895 by Cheng Shao at 2026-07-21T17:10:53-04:00 rts: always use StgInt to represent cost center id Currently cost center id is modeled as `Int` and it should be `StgInt` uniformly in the RTS, hence this patch. Fixes #27524. - - - - - 94d8f83b by Cheng Shao at 2026-07-22T11:30:40-04:00 hadrian: clean up stale cabal package flags in the tree This patch cleans up stale cabal package flags in the tree and related hadrian/autoconf logic. Closes #27474. Co-authored-by: Codex <codex(a)openai.com> - - - - - 0bf1d8c9 by Sasha Bogicevic at 2026-07-22T11:31:21-04:00 parser: don't suggest ImportQualifiedPost when it is already enabled -Wprepositive-qualified-module unconditionally attached a hint to enable ImportQualifiedPost, even when the extension was already on (as it is by default under GHC2021). Record the extension's state in the PsWarnImportPreQualified diagnostic and drop the hint when it is already enabled. Fixes #27380 - - - - - 700a1dd1 by Simon Jakobi at 2026-07-23T11:21:20-04:00 ci: Reduce lint job setup costs Avoid fetching unnecessary history and submodules for lightweight lint jobs. Run changelog validation without Hadrian. Because the lint-author job is now based on the .lint template directly, we enhance it to allow Git to read from the runner-owned checkouts, In the previously used .lint-params template, this permissions issue was addressed via `chown`. Closes #27521. Assisted-by: gpt-5.6-sol via Codex CLI - - - - - 26a44fb0 by ARATA Mizuki at 2026-07-23T11:22:10-04:00 testsuite: Fix memory issues of doublex2_* and simd010 doublex2_* had reads from uninitialized memory. simd010 had out-of-bounds array access. Fixes #27544 - - - - - 4d798b17 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Eliminate STM_AWOKEN It was used as nullary closure for the block_info.closure in the case of a thread being awoken after an STM transaction. However, while it was written, it was never read, so contributed nothing to the behaviour. Furthermore, in the only place it was set (in tryWakeupThread) the why_blocked was immediately overwritten by the NotBlocked status, and the block_info was updated accordingly (by appendToRunQueue). So it didn't even serve a purpose of clarifying an intermediate state, there really was no such intermediate state. Cleaning this up will allow the BlockedOnSTM case to follow the same pattern as the other why_blocked cases that do not use the block_info, and in turn this reduces the number of different categories. - - - - - e1cece79 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Document that eventlog thread stop code ThreadBlocked is no longer used It has not been used since GHC 7.0.x (2011). In 7.2 all the BlockedOn* codes were added, and these were and are used instead of ThreadBlocked. - - - - - 795db115 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Add a proper mapping to eventlog external thread stop status That is the mapping from rts-internal codes, to the coes used in the status field in the eventlog EVENT_STOP_THREAD event. See issue #9003 for what goes wrong when we mess this up. In that ticket, people note that we should really not require the internal tso->why_blocked codes to leak into the external eventlog thread stop codes. The same principle applies to the StgThreadReturnCode. This change properly separates them, and explicitly maps between them using a pair of (compact, constant) tables. These tables are pretty small (with no alignment constraints) and will soon shrink so it seems a sensible tradeoff. We also introduce and use proper EVENT_STOP_THREAD constants in the event log format header. Previously there was not specification in the code for these (only in the docs): the values were encoded into the conversion code. This will allow us to renumber the internal why_blockd codes without breaking the eventlog output. - - - - - 6f1c8efa by Duncan Coutts at 2026-07-23T17:26:18-04:00 Remove unused tso->block_info.wakeup member Presumably it was used once, but not now. - - - - - 740b88a9 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Document StgTSOBlockInfo to say what cases use what members In principle, tso->why_blocked is the tag for the StgTSOBlockInfo union, so we should be able to say for each union member the why_blocked cases that use that member. - - - - - 5b92eae2 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Add a tso->block_info.mvar member and use it in preference to the generic block_info.closure union member, with casts. The plan is that when we know what case we're in (via tso->why_blocked) then we can always access the correct union member, and so we will only need to access block_info.closure for generic cases where we don't know or don't care. - - - - - d931715f by Duncan Coutts at 2026-07-23T17:26:18-04:00 Add a tso->block_info.unused member and use it in preference to the generic block_info.closure union member, with casts. The plan is that when we know what case we're in (via tso->why_blocked) then we can always access the correct union member, and so we will only need to access block_info.closure for generic cases where we don't know or don't care. - - - - - 47e28ebb by Duncan Coutts at 2026-07-23T17:26:18-04:00 Avoid storing to tso->block_info.closure In one case we can use a specific union member (.prev) instead. In several cases the stores were in fact redundant because of subsequent overwrites. In scavengeTSO we replace setting tso->block_info.closure to a valid closure, with an assertion that the block_info.unused is already set to END_TSO_QUEUE which is a valid (static) closure. - - - - - 96e4749d by Duncan Coutts at 2026-07-23T17:26:18-04:00 Renumber the tso->why_blocked constants We can do this now because we have separated the internal values from the external ones used in the eventlog. This lets us put them back into a deliberate order and consolodate some gaps. More importantly, it is a prepation for a slightly more sophisticated encoding. - - - - - 8f62661c by Duncan Coutts at 2026-07-23T17:26:18-04:00 Define constants for the existing stg_threadStatuszh return codes The stg_threadStatuszh reuses the internal tso->why_blocked codes but also extends them with a couple previously magic values. This is awkward since we need to know what those magic values are so we don't accidentally use those values to mean something else. By pulling a definition up to where the why_blocked codes are defined we will be able to avoid mistakenly assining those codes some meaning (or just changing the BlockedThreadComplete, BlockedThreadKilled code if necessary). - - - - - 42c69ae2 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Extend the tso->why_blocked encoding to indicate block_info closures We use some bit tricks to cheaply and generically test if a tso->why_blocked tag implies that the corresponding tso->block_info will contain a non-trivial valid closure (i.e. not just block_info.unused set to END_TSO_QUEUE). In particular we arrange for most why_blocked values to naturally have a distinguishing bit, but for the BlockedOn{Read,Write,Delay} cases, they can come in either non-closure or closure forms. We allow an additional bit to distinguish these cases. The non-closure forms are only from legacy I/O managers: select and win32-legacy. So this extra bit mechanism will be able to be retired once the legacy I/O managers are themselves retired. This means in a few places we need to untag the why_blocked value before inspecting it, but in most places we do not. - - - - - 7c64632b by Duncan Coutts at 2026-07-23T17:26:18-04:00 Use BlockInfoForceNonClosure in the select I/O manager - - - - - 8fd7104a by Duncan Coutts at 2026-07-23T17:26:18-04:00 Use BlockInfoForceNonClosure in the win32-legacy I/O manager for the BlockedOn{Read,Write} since these use the non-heap allocated StgAsyncIOResult. - - - - - e0da603b by Duncan Coutts at 2026-07-23T17:26:18-04:00 Enforce the why_blocked and block_info rules in checkTSO We now check the cases wher IsBlockInfoClosure should hold, the cases that are supposed to use block_info.unused == END_TSO_QUEUE, and which cases are allowed to use BlockInfoForceNonClosure. This partially enforces the use of why_blocked as a tag for the block_info union. We could be stricter and check for the correct expected info table for the closure cases. - - - - - 1dd0f381 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Use IsBlockInfoClosure to simplify several tests In GC and generic traversal we need to know if we should look at the block_info.closure or not. Now we can do just that using a cheap bit test on the why_blocked tag. This fixes issue 26717, where the problem was that some GC modes did not know when to look at block_info.closure, because the poll I/O manager uses a closure for BlockedOn{Read,Write} while the select I/O manager uses a non-closure. Now this information is in the why_blocked tag itself. - - - - - 7a00ffbc by Duncan Coutts at 2026-07-23T17:26:18-04:00 Remove the now-unused scavengeTSOIOManager The GC no longer has to delegate to the I/O manager, since it can use IsBlockInfoClosure to decide things itself. - - - - - 522a481f by Duncan Coutts at 2026-07-23T17:26:18-04:00 Remove duplicate assertion - - - - - 0874d965 by Duncan Coutts at 2026-07-23T17:26:18-04:00 Follow atomic access rules more consistently for tso->why_blocked The rule is this: store block_info *before* why_blocked store why_blocked using store release load why_blocked using load acquire load block_info *after* why_blocked This is a an atomic store release / load acquire pair and (if the reads are in a separate thread to the writes, and the read receives the value stored) then this guarantees a full "happens before" relationship of these stores and loads. In some cases, we do not need a full load acquire, because we don't read the block_info at all and so do not need any ordering. In this case we just need an atomic relaxed load. This was being followed in most places, but not all. If there's good reason in any case that we don't need atomic access, then we should document that in a comment. In the absence of that I think it's easier to follow the rule everywhere. - - - - - 8f0bdbe1 by Duncan Coutts at 2026-07-23T17:26:19-04:00 Add a changelog entry - - - - - 4fdfe757 by Alan Zimmerman at 2026-07-23T17:27:06-04:00 EPA: Keep decls together in ClassDecl Similar to 1718230f4d3d19d8c49c0e5d496cb0fb6f399528 for HsValBindsLR, this commit updates ClassDecl so that it no longer splits out the assorted `LHsDecl GhcPs` until the renamer. It does this by inserting a type family (separate from the classic TTG one) for this. So data TyClDecl ... | ClassDecl { ... tcdDecls :: XClassDecls pass with type instance XClassDecls GhcPs = [LHsDecl GhcPs] type instance XClassDecls GhcRn = ClassDeclX GhcRn type instance XClassDecls GhcTc = ClassDeclX GhcTc data ClassDeclX pass = ClassDeclX { tcdSigs :: [LSig pass], -- ^ Methods' signatures tcdMeths :: LHsBinds pass, -- ^ Default methods tcdATs :: [LFamilyDecl pass], -- ^ Associated types; tcdATDefs :: [LTyFamDefltDecl pass], -- ^ Associated type defaults tcdDocs :: [LDocDecl pass] -- ^ Haddock docs } - - - - - f586c885 by Simon Jakobi at 2026-07-24T18:05:00-04:00 ci: Use shallow submodule clones by default Limit submodule clones to depth one to reduce CI checkout costs. Keep fetching full submodule history for the submodule lint jobs, which inspect commits across a range. Assisted-by: gpt-5.6-sol via Codex CLI - - - - - 306120d2 by Duncan Coutts at 2026-07-24T18:05:43-04:00 Fix flaky test T3994 on FreeBSD On current FreeBSD versions, calling getpgid on a zombie process fails. In T3994, if we're really unlucky with delays and scheduling then we can end up in exactly that situation. Just catch that specific exception and ignore it. It's rare, and not our fault. - - - - - 7b116a0b by Cheng Shao at 2026-07-24T18:06:24-04:00 ci: add missing workaround for docker permissions in lint jobs Some lint jobs use ci-images with default user `ghc`, and the gitlab ci docker executor requires the `sudo chown` workaround to fix workspace directory permission issue. This patch adds the missing workarounds for the lint jobs. Fixes #27554. Co-authored-by: Codex <codex(a)openai.com> - - - - - 815149f3 by Andrzej Rybczak at 2026-07-25T15:06:43+00:00 Add -Wdefaulted-callstack Adds a new warning, -Wdefaulted-callstack, which warns when an implicit CallStack parameter is defaulted to the empty stack. In particular, this includes call sites where a function with a HasCallStack constraint is called from a definition that does *not* provide one. At such call sites the call stack is cut off and does not include the enclosing definition's callers, which can be a source of surprise if the user wants complete call stacks. Closes #27077. - - - - - f6f2343f by Zubin Duggal at 2026-07-25T17:40:51-04:00 UniqueDFM: alter should preserve insertion order Before it always inserting new elements at the end. This is problematic because instances get inserted into the map with `alterF`, which can change ordering of how instances are printed with `:info` depending on the order in which we consult interfaces I expect `alter id k = id` and `alter (fmap f) k = adjust f k`. Moving keys to the end breaks that (`adjust` already preserves position). Fixes #27532 - - - - - 5d0ab71a by fendor at 2026-07-27T17:31:05-04:00 Introduce global unit database cache As a first step for better sharing of `UnitInfo` across `UnitEnv`, we introduce a new datatype called `ExternalUnitDatabases`. It primarily serves as an in-memory representation of *all* `UnitDatabase`s across `UnitEnv`. This means, if multiple `HomeUnitEnv`s depend on the same database, one way or another, we make sure that we don't parse from disk every time. Instead, we store the in-memory representation in `ExternalUnitDatabases`. `ExternalUnitDatabaseCache` is the equivalent of `ExternalUnitState` in the `UnitEnv`. It is a mutable variable wrapping `ExternalUnitDatabases`. The mutable `ExternalUnitDatabaseCache` is used in `initUnits` to make sure we don't parse the same unit database multiple times. Almost by accident, we change the semantics of `initUnits` to honour modifications to `packageDBFlags`. The inability to change `packageDBFlags` while also reusing the already parsed `UnitDatabase`s was reported in #26423 as a bug. Hence, we think this behaviour change is warranted and acceptable, especially since it comes with a breaking change to the `initUnits` API. Add regression test for #26423 Closes #26423 - - - - - 6cce494a by fendor at 2026-07-27T17:31:05-04:00 Introduce UnitIndex for global external unit caching `UnitInfo`s have been observed to cause a lot of memory usage in #27500. Especially with multiple home units, as the same (external) units are processed from scratch, even though most of the time we end up with exactly the same `UnitInfo`. We introduce a `UnitEnv` global cache that allows us to store external unit information that is used across all `HomeUnitEnv`s. The most important change in this commit is the introduction of the `UnitIndex`. It stores a global mapping of `UnitId` -> `UnitInfo`, and `initUnits` always uses the cached `UnitInfo` entry to populate each `HomeUnitEnv`'s `UnitState`. This allows us to ensure the following property: > Each `UnitInfo` should be alive exactly once in GHC. All `UnitState`s should reference 'UnitInfo's stored in the 'UnitIndex'. This ensured by calling 'initUnits' with the 'UnitIndex'. In addition, the `ExternalUnitDatabases` may also hold a reference to each on-disk representation of `UnitInfo`. This means, we impose an hard upper bound on the number of `UnitInfo`s alive in the GHC session: > The number of alive `UnitInfo`s closure objects must be the > sum of all loaded unit database times two. We add performance regression tests that make sure the number of live `UnitInfo` cannot exceed this threshold. Closes #27500 ------------------------- Metric Decrease: MultiComponentModules MultiComponentModulesRecomp MultiComponentModulesRecomp100 mhu-perf LinkableUsage02 ------------------------- These metrics increases are especially notable, as we are not even sharing anything big but merely the global package database with 50 entries. It shows how careful sharing of `UnitInfo` can improve memory usage. We expect this to be much more notable when the whole cabal package database is shared across multiple home units. `LinkableUsage02` metric decreases on unreg and i386 platform, only. --- Technical details To share the `UnitInfo`s correctly, it is important that we extract the `WireMap` into the `UnitIndex`. At the moment of writing, `WireMap` must be globally the same for all `HomeUnitEnv`s. This is important, as we could otherwise not cache the "fully-resolved" `UnitInfo`, as we don't change the `UnitId` or `unitAbiHash` when resolving wired-in units. Thus, there could be ambiguities, when the `WireMap` is not the same for all `UnitState`s across the `UnitEnv`. We consider a `UnitInfo` fully-resolved, if wired-in units have been updated, the `UnitInfo` has been validated and variables in the unit config, such as `${pkgroot}` have been resolved. Updating the wired-in units requires the `WireMap` to be globally the same. - - - - - f8e3bee9 by Zubin Duggal at 2026-07-27T17:31:49-04:00 testsuite: skip runtime stats tests on debugged compilers Debugged flavours build the boot libraries without optimisation, so the runtime numbers do not match the baselines. - - - - - 1e326770 by Zubin Duggal at 2026-07-27T17:31:50-04:00 testsuite: mark #20706 tests fragile rather than broken Whether the static linux linker issues manifest depends on the host toolchain. - - - - - c0b13cbe by Zubin Duggal at 2026-07-27T17:31:50-04:00 testsuite: exclude libnuma from mostly-static It needs static system libraries (libnuma.a) that many platforms do not ship. Fixes #26914 - - - - - bee1913d by Alan Zimmerman at 2026-07-28T16:42:29-04:00 EPA: ClsInstDecl with decls as [LHsDecl GhcPs] in GhcPs Similar to 4fdfe75731e01dad7d7fa474c2703d0d3965afb1, this commit changes the as-parsed representation of class instance declarations to [LHsDecl GhcPs], and only separates them by type from the renamer onward. This also allows us to remove all the AnnSortKey machinery for exact printing, as it is now no longer needed. - - - - - 72c55eee by Cheng Shao at 2026-07-28T16:43:11-04:00 hadrian: implement and use writeFileAtomic to fix race condition This patch implements `writeFileAtomic` in hadrian and change all invocations of shake non-atomic `writeFile'` to use `writeFileAtomic`, to avoid multiple hadrian concurrent invocations overwriting the same in-tree generated file not in the build root directory. Fixes #27536. Additional notes: - `writeFileChanged`/`writeFileChangedBS` cannot be made atomic since it involves reading the file's older version, so their uses are left alone. It doesn't affect #27536 given their outputs are contained in the build root directory. - It's possible to shrink this patch by only making writes outside the build root directory atomic. But I think it's not worth the effort for fine grained distinction here, and atomic writes within the build root directory should also improve robustness of a hadrian build. - In the longer term we do want to make a ghc build only generate files within the build root directory, though that's a lot of work and outside the scope of this particular bugfix. Co-authored-by: Codex <codex(a)openai.com> - - - - - 46d4f963 by Sylvain Henry at 2026-07-29T06:38:40-04:00 RTS: correctly mark slop bytes when shrinking large arrays (#19048) Correctly mark slop bytes even when profiling is off so that heap census doesn't traverse garbage-collected closures. - - - - - 4762a8bf by Simon Jakobi at 2026-07-29T06:39:23-04:00 Add -XLazyFieldAnnotations (GHC proposal 752) Unbundle the prefix `~` lazy field annotation syntax from StrictData. The new LazyFieldAnnotations extension controls whether `~` is accepted on constructor fields. StrictData (and Strict, transitively) imply the new extension. See https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0752-l…. Closes #24455. Assisted-by: Claude Opus 4.8 - - - - - 0b6dcc84 by Simon Jakobi at 2026-07-29T06:40:04-04:00 testsuite: Relax T24471 residency tolerance T24471 peak residency fluctuates enough on i386 to cause spurious failures. Use the standard residency tolerance while retaining the existing allocation threshold. See https://gitlab.haskell.org/ghc/ghc/-/work_items/24471#note_682303. Assisted-by: gpt-5.6-sol via Codex CLI - - - - - 90e95b34 by Cheng Shao at 2026-07-29T06:40:45-04:00 compiler: fix missing top-level procedure labels in cmm dumps This patch fixes missing top-level procedure labels in some intermediate Cmm pass dumps. Fixes #27553. Co-authored-by: Codex <codex(a)openai.com> - - - - - 360a5946 by sheaf at 2026-07-29T06:41:35-04:00 Add some type-family-heavy performance tests FamAppCachePerf stress-tests the performance of lookups in the type family application cache. T27336 is a minimisation extracted from the reported reproducer. SimplCastPerf is a measure of coercion growth due to the simplifier calling mkTransCo without re-optimising the result. - - - - - 3ec9e2b9 by Mike Pilgrem at 2026-07-31T08:21:33-04:00 GHC Guide: Improve docs on response files - - - - - e5b2a1f7 by sheaf at 2026-07-31T08:22:23-04:00 Disable Core Lint for TcPlugin_RewritePerf This is a compiler performance test, but the test source hard-coded -dcore-lint, defeating the measurement. ------------------------- Metric Decrease: TcPlugin_RewritePerf ------------------------- - - - - - 85b10c00 by Alan Zimmerman at 2026-07-31T22:09:47+01:00 EPA: Remove LocatedP from OverlapMode We have type LocatedP = GenLocated SrcSpanAnnP type SrcSpanAnnP = EpAnn AnnPragma As the first step in removing this in favour of LocatedA which only captures location, comments and trailing annotations, we remove it from OverlapMode We do this by moving the AnnPragma into the TTG extension point instead. - - - - - c9a34a00 by Viktor Dukhovni at 2026-08-02T04:34:17-04:00 Fix note typo - - - - - 4f2a21f7 by Andreas Klebinger at 2026-08-02T22:46:46-04:00 Apply oneShot Monad trick to STG LintM - - - - - 21e4b89d by Andreas Klebinger at 2026-08-02T22:46:46-04:00 stgLint: Use a single reader env for read only arguments. - - - - - d415f38a by Alan Zimmerman at 2026-08-02T22:47:27-04:00 EPA: Remove LocatedP from CType The next step of removing use of LocatedP by moving the AnnPragma for CType into its TTG extension point instead. - - - - - 8fc6f882 by Simon Jakobi at 2026-08-05T14:53:41-04:00 testsuite: Don't crash on non-UTF-8 test output read_stdout, read_stderr_for, read_comp_stderr and read_diff decoded strictly (the first three with UTF-8, read_diff with the locale encoding), so a test emitting invalid UTF-8 (binary output, or a crash truncating a multi-byte character) raised UnicodeDecodeError and was reported as a framework failure instead of its actual result. Decode with errors='replace', like read_no_crs and safe_print. Assisted-by: Claude Fable 5 - - - - - 56534866 by Simon Jakobi at 2026-08-05T14:53:41-04:00 testsuite: Colorize the test summary, also in CI The summary headings were plain, and SUMMARY was colored unconditionally, so the escapes also ended up in the file written by --summary-file. Color is now decided per output sink via term_color.colored_if; see the comments in term_color. CI logs are not a tty, but GitLab's log viewer renders ANSI colors, so add --force-colors and pass it in .gitlab/ci.sh. Assisted-by: Claude Opus 5 - - - - - bceb541a by Simon Jakobi at 2026-08-05T14:53:42-04:00 testsuite: Repeat unexpected failure output in the summary Finding out why a test failed meant scrolling back through a possibly very long log to the point where the test ran. The summary now repeats the captured output of unexpected failures, before the statistics, so the most interesting part is at the end of the log (#16720). Output mismatches report their diff instead of the mismatching stream (see Note [Redundant output in test results]). The repeated output is bounded per stream, and skipped altogether beyond MAX_SUMMARY_OUTPUT_TESTS failure blocks. Tests failing identically in several ways share one block. Test results now report a source-relative directory, stable regardless of where the run was started from. Assisted-by: Claude Fable 5 - - - - - 2ab02c57 by Ben Gamari at 2026-08-05T14:54:24-04:00 base: Don't drop exception context in SomeException(toException) For reasons that are lost to time, the implementation of [CLC #200] that was merged inappropriately dropped `ExceptionContext` in the `toException` implementation given to `SomeException`. Fix this infelicity. [CLC #200]: https://github.com/haskell/core-libraries-committee/issues/200 - - - - - 126ce574 by Vladislav Zavialov at 2026-08-05T14:55:05-04:00 Test case for #20902 Starting with GHC 9.14.1 (the first major release to include 51e3ec83), and from point releases GHC 9.10.2 and GHC 9.12.3 (backports cc4470be68 and b30f25591e), all examples in this ticket are handled as expected. - - - - - b14d8d59 by Alan Zimmerman at 2026-08-05T14:55:46-04:00 EPA: Remove LocatedP, last use in WarningTxt The last step of removing LocatedP, by moving the AnnPragma for WarningTxt into its TTG extension point instead. This also allows us to remove LocatedP and SrcSpanAnnP - - - - - 70b58c8f by Vladislav Zavialov at 2026-08-05T14:56:27-04:00 Test cases for #18725 Starting with GHC 9.4 (the first release to include 268efcc9a4), the program in this ticket no longer panics. A standalone kind signature breaks the recursive loop, so the type constructor can be used in a kind within its own group. T18725a checks that this is accepted with the signature present, while T18725b confirms it is still rejected without it. - - - - - b18c8dd5 by Zubin Duggal at 2026-08-06T15:51:01-04:00 hie files: Dump the type table when dumping with -ddump-hie - - - - - f839d0fb by Zubin Duggal at 2026-08-06T15:51:01-04:00 hie files: Take evidence for quantified constraints into account when saving evidence terms to the hie ast Fixes #25709 - - - - - 5753ebaa by Simon Jakobi at 2026-08-06T15:51:43-04:00 testsuite: fix stale paths for the ghc-config build artifacts ghc-config.hs moved from testsuite/mk/ to testsuite/ghc-config/ in 6c7a49139c, but the .gitignore entry and the clean rule still referred to the old location. As a result the compiled ghc-config binary, which boilerplate.mk rebuilds on every make-driven test run, showed up as an untracked file and was never cleaned. Assisted-by: Claude Opus 5 - - - - - 246d4d72 by Simon Peyton Jones at 2026-08-06T15:52:25-04:00 Documentation only ...driven by my investigation of #27591 - - - - - be69e9df by Alan Zimmerman at 2026-08-06T15:53:05-04:00 EPA: Replace AnnPragma with individual types We introduced AnnPragma as a common type for all pragma usages wrapped in LocatedP / SrcSpanAnnP. Now that those are gone, and the AnnPragma moved into the TTG points for the given items, we can ensure that each carries only the annotations it needs. So we remove AnnPragma, and in its place bring in AnnCType AnnWarningTxt AnnOverlap AnnAnnDecl AnnPragSCC - - - - - 0779e12c by Simon Jakobi at 2026-08-07T12:36:11-04:00 Cmm: print unreachable blocks under -dppr-debug (#27368) Unreachable blocks linger in a CmmGraph's block map for most of the Cmm pipeline, but pprCmmGraph only ever printed the blocks reachable from the entry, so dumps looked consistent while the graph was not. Issues like #27368 were hard to debug due to this. pprCmmGraph now appends the stored-but-unreachable blocks under a "// unreachable blocks:" heading when -dppr-debug is on. See Note [unreachable blocks] in GHC.Cmm.Pipeline. Assisted-by: Claude Opus 5 - - - - - 3a0f9a51 by Simon Peyton Jones at 2026-08-07T12:36:54-04:00 Fix three bugs related to required type args and INLINE pragmas * `GHC.Core.Opt.Arity.mkEtaForAllMCo` got the visibility flags back to front, leading to a Lint error (#27557) * The arity in an InlineSaturation is the VisArity not the Arity; the two can differ when we have "required" type arguments. This made the INLINE pragma argument counting go wrong in `makeCorePair` (#27590). * When a simple binding has a type signature, we take special path in `tcPolyCheck`, leading to an outer `AbsBinds` that has no dictionaries, even when the binding is in fact overloaded. That confused the inline-arity computation in `makeCorePair` (#27589). The latter two are fixed using the new function `GHC.HsToCore.Binds.findSatArity`. That actually simplifies the API of `makeCorePair`, which is nice. The first bug is fixed by swapping the visiblity flags in `GHC.Core.Opt.Arity.mkEtaForAllMCo` Getting the INLINE behaviour right led to some perf changes: * Runtime /halved/ on T7954 due to better specialisation * Compile time increased by 6% in T21839c because a bit more inlining happened, as it always should have done. * For some reason compile-time max-bytes-used dropped by 30% on T27336, but only on one build configuration; and it increased on LinkableUsage02 by 6% on another configuration Geometric mean effect on our compile time benchmarks is +0.1%. Metric Decrease: T27336 T7954 Metric Increase: LinkableUsage02 T21839c - - - - - 4f985108 by Vladislav Zavialov at 2026-08-07T17:49:50-04:00 Discard type arguments in tcPatToExpr (#27440, #27583) The builder expression of an implicitly bidirectional pattern synonym must not mention types written in the RHS: * Invisible type arguments led to a panic (#27440) * Required type arguments failed with out-of-scope variables (#27583) Both are now discarded, following the precedent established by pattern signatures (#9867). Discarding type arguments takes some care: a type pattern cannot be told from a value pattern by syntax alone, as the `type` keyword may be omitted. Consider: data T a b c where MkT :: forall a. forall b c -> a -> T a b c pattern P :: x -> T x y z pattern P x = MkT @a (type b) c x In P's right-hand side, `@a` and `type b` are clearly type arguments, but what about `c` and `x`? We can only tell by matching the patterns against MkT's type. So tcPatToExpr now runs in TcM and matches the arguments against the constructor's TyVarBinders using zipPatsBndrs, which is made public for this purpose. The resulting builder is $bP x = MkT _ _ x. See Note [Discarding types in the builder expression]. Test cases: T27440a T27440b T27440c T27440d T27440e T27583a T27583b T27583c T27583d T27583e T27583f T27583g Metric Increase: LinkableUsage02 Metric Decrease: T27336 Assisted-by: Claude Opus 5 - - - - - eb1dcd4d by sheaf at 2026-08-07T17:50:40-04:00 mkWpFun_FRR: fix ordering of coercion composition When the subsumption machinery generates an eta-expansion, we must perform a representation polymorphism check to ensure the lambda binder it introduces has a fixed runtime representation. This is done in GHC.Tc.Utils.mkWpFun_FRR. This check involves composing quite a few coercions, arising from representation-polymorphism checks on both the actual and expected argument types. These coercions are then chained using HsWrapper composition, <.>. The ordering of composition was incorrect, leading to the Core Lint failure reported in #27639. This commit fixes that. Fixes #27639 - - - - - 3a552476 by Simon Jakobi at 2026-08-09T15:20:06-04:00 Word64Map: add compareSize compareSize m c compares the size of a map to an Int, but unlike compare (size m) c it stops traversing the map once the outcome is determined. Based on https://github.com/haskell/containers/pull/1139 Assisted-by: Claude Opus 5 - - - - - 6e2c99d8 by Simon Jakobi at 2026-08-09T15:20:06-04:00 Use a pigeonhole sort for deterministic UniqDFM iteration Deterministic UniqDFM iteration used a list mergesort, allocating O(n log n) cons cells and contributing significantly to compiler allocations (#27459). Use a pigeonhole sort where appropriate, while retaining the mergesort fallback. See Note [Sorting a UDFM] and Note [Cost of deterministic iteration]. The peak_megabytes_allocated increase for LinkableUsage02 is probably due to GC timing noise. See #27613. ------------------------- Metric Decrease: InstanceMatching InstanceMatching1 ManyAlternatives T12707 T13379 T13719 T24471 T27336 T5321FD T5321Fun T783 Metric Increase 'peak_megabytes_allocated': LinkableUsage02 ------------------------- Assisted-by: gpt-5.6-sol via Codex CLI - - - - - a938ab12 by sheaf at 2026-08-09T15:20:48-04:00 Testsuite: don't measure max residency for T27336 We really care more about total allocations for this test, so this commit removes the maximum residency measurement. - - - - - 7d94bb78 by Alan Zimmerman at 2026-08-09T15:21:29-04:00 EPA: Remove LocatedE, replace with LocatedA This gets rid of one more LocatedXXX occurrence - - - - - 9df24b7e by sheaf at 2026-08-10T14:28:30-04:00 hie.yaml: use a polyglot shell/batch script This commit merges hie-bios and hie-bios.bat into a single polyglot script. This avoids Windows users having to manually update hie.yaml in order to be able to use HLS. - - - - - 7f75c588 by Alan Zimmerman at 2026-08-10T14:29:11-04:00 EPA: Remove type parameter from AnnList This is a step towards cutting AnnList down to its core for formatting lists only - - - - - e8d1a0d6 by Bernhard M. Wiedemann at 2026-08-10T21:31:23-04:00 driver: Link object files in a deterministic order The object files handed to the linker come from the HomePackageTable, which is ordered by the order in which modules finished compiling. With -j1 that is the build plan order, with -jN it is whatever the scheduler produced, so the same sources can link to different (but equivalent) binaries. The order reaches the output: .text and .rodata contributions are concatenated in link order, so e.g. building the hdav executable of the DAV package twice, once with -j1 and once with -j4, yields two binaries that differ in ~100kB of section contents. Sort the home modules by module before collecting their linkables, guarded under `Opt_ObjectDeterminism` . Fixes #27612 Signed-off-by: Bernhard M. Wiedemann <bwiedemann(a)suse.de> - - - - - 556db2f3 by sheaf at 2026-08-10T21:32:06-04:00 Reduce SpecConstr threshold in GHC.Tc.Solver.Rewrite As remarked in #27628, this module currently sits on a knife's edge: if the body of 'simplifyArgsWorker' is made even a tiny bit smaller, then SpecConstr suddenly kicks in and causes disastrous reboxing of the LiftingContext argument. To make this less likely to happen, this commit lowers the SpecConstr threshold. - - - - - c77d88fc by sheaf at 2026-08-13T10:15:22-04:00 Allow rewriting in RuntimeReps for newtype ConPats This commit implements PHASE 2 of the FixedRuntimeRep plan described in Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete for newtype constructor patterns. In short, GHC now accepts programs of the form f (MkN x) = ... in which the argument 'x' of the newtype constructor pattern 'MkN x' has a representation that is not syntactically concrete, e.g. it can be 'Id IntRep' reducing to 'IntRep'. See T20363{,b,c} for examples. There are two main parts to the implementation: 1. Typechecking, in GHC.Tc.Gen.Pat.tcDataConPat. See Note [Typechecking newtype constructor patterns] in GHC.Tc.Gen.Pat. 2. Desugaring. We restructure the code for desugaring pattern matches by allowing the scrutinised match variable to be casted. This allows us to accumulate coercions and avoids creating binders at intermediate types tha don't have a fixed RuntimeRep. See the revamped Note [Match Ids] in GHC.HsToCore.Monad. Fixes #20363 ------------------------- Metric Increase: InstanceMatching ------------------------- - - - - - 6ba9dd41 by Wolfgang Jeltsch at 2026-08-13T10:16:07-04:00 Improve the documentation of `--show-iface` This change in particular gets rid of the claim that `--show-iface` writes *the* contents of the interface file in question. It doesn’t do that; it only writes those parts that are likely of interest to a human reader. - - - - - 4bd193fa by Sylvain Henry at 2026-08-13T10:17:00-04:00 RTS: fix LDV profiler's slop skipping (#27585) processHeapForDead was the one heap scanner not updated for the slop marker encoding introduced in #19048. It still assumed slop is zeroed: while (p < bd->free && !*p) p++; // skip slop so it stopped at the (StgWord)(-1) sentinel and passed it to processHeapClosureForDead. IS_FORWARDING_PTR(-1) holds, hence a garbage size was read out of LDVW and the scan ran off the block, tripping ASSERT(p == bd->free) on a debug RTS and silently corrupting the census otherwise. The loop was hand-copied in four places, so factor it out into skipSlop in ClosureMacros.h and use it in ProfHeap.c, Sanity.c, Printer.c and LdvProfile.c. Co-Authored-By: Claude Opus 5 (1M context) <noreply(a)anthropic.com> - - - - - 1446bb03 by Zubin Duggal at 2026-08-13T10:17:48-04:00 hadrian: Fix links to remaining doc sites to not use the package hash for haddock links In 07267f79d91169f474cacc8bcd38d76a6e97887d we changed hadrian to not include the package hash in the haddock directory. This patch takes care of a few remaining links that were missed in that patch Fixes #27671 - - - - - 257c3ed7 by Simon Jakobi at 2026-08-13T10:18:29-04:00 Testsuite: widen InstanceMatching acceptance window to 5% (#27673) ...in order to unblock CI. Assisted-by: Claude Fable 5 - - - - - e4cfaaa0 by Simon Peyton Jones at 2026-08-14T01:09:32+02:00 Major patch to re-engineer known-key names This big patch implements the New Plan for known-key names, described in #27013. Read the big Note [Overview of known-key names] in GHC.Types.Name Some things had to be reworked slightly to accomodate the new known-keys design. A significant one was the generation of auxiliary KindRep bindings, which was greatly simplified. Note [Grand plan for Typeable] was updated accordingly. Another example: GHC.Internal.CString was merged into GHC.Internal.Types. Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com> The couple hundreds of hours spent here by Rodrigo were sponsored by Well-Typed Metrics: compile_time/bytes allocated ------------------------------------- Baseline Test Metric value New value Change ------------------------------------------------------------------------------------------ MultiComponentModules100(normal) ghc/alloc 24,312,779,672 24,990,470,432 +2.8% BAD MultiComponentModulesRecomp(normal) ghc/alloc 601,924,960 621,884,888 +3.3% BAD MultiComponentModulesRecomp100(normal) ghc/alloc 11,884,065,432 12,531,373,704 +5.4% BAD MultiLayerModules(normal) ghc/alloc 3,861,537,072 3,706,919,512 -4.0% GOOD T13701(normal) ghc/alloc 3,517,246,392 3,237,179,616 -8.0% GOOD T13820(normal) ghc/alloc 28,961,056 29,663,208 +2.4% BAD T14697(normal) ghc/alloc 472,044,184 443,550,048 -6.0% GOOD T18140(normal) ghc/alloc 47,905,664 49,115,808 +2.5% BAD T4801(normal) ghc/alloc 269,339,096 263,432,040 -2.2% GOOD T783(normal) ghc/alloc 341,112,672 333,339,952 -2.3% GOOD hard_hole_fits(normal) ghc/alloc 222,164,728 213,433,808 -3.9% GOOD mhu-perf(normal) ghc/alloc 49,011,440 46,706,280 -4.7% GOOD geo. mean +0.1% minimum -8.0% maximum +5.4% All performance regressions were investigated in depth. The surviving ones: - MultiComponentModules100, MultiComponentModulesRecomp100, MultiComponentModulesRecomp regresses because existing bugs that make an additional implicit edge do too much redundant work: #27053 and #27461 - T13820, T18140, T10547, T13035 regress because we load an additional interface and associated Names for GHC.Essentials. ------------------------- Metric Decrease: MultiLayerModules T13379 T13701 T14697 T26989 T4801 T783 T9961 hard_hole_fits mhu-perf size_hello_artifact size_hello_obj size_hello_unicode Metric Increase: LinkableUsage01 LinkableUsage02 MultiComponentModules100 MultiComponentModulesRecomp MultiComponentModulesRecomp100 T10547 T13035 T13820 T18140 T18698a T18698b T20049 ------------------------- Bumps submodule binary Closes #27013 - - - - - 61665e79 by sheaf at 2026-08-14T01:09:33+02:00 Allow GHC.Essentials to be hidden This commit overhauls several aspects of the known entity handling, in order to allow GHC.Essentials to be hidden without a proliferation of special cases in the compiler. The main contribution is to introduce the 'UnresolvedImport' datatype which cleans up a lot of ad-hoc handling relating to 'ModSummary', fixing #27603. This allows us to reduce duplication, e.g. by having Backpack reuse 'mkUnresolvedImports' instead of replicating the "add implicit imports" logic. It also makes it easier to avoid undesirable edge cases (such as making sure that the Template Haskell 'reifyModule' function does not leak the implicit GHC.Essentials import). In particular, the infamous 'findImportedModuleWithIsBoot' is now simply 'resolveImport', taking a single 'UnresolvedImport' and resolving it to a 'FindResult' (usually a 'Module'). Other changes: - Cache the result of looking up GHC.Essentials (in TcM and DsM environments) to avoid redundant work. This reduces allocations on LinkableUsage01 and hard_hole_fits. - Properly look up known entities for StaticPointers like we do for other known entities everywhere else. This allows e.g. modules in ghc-internal to use -XStaticPointers. - When using multiple home units, we are now careful to handle the situation in which we may have multiple GHC.Essentials modules around. See the new tests under 'driver/multipleHomeUnits'. - - - - - b19fcc1c by Vladislav Zavialov at 2026-08-14T06:26:11-04:00 Increase test coverage of diagnostics, batch 2 Add test cases for the previously untested diagnostics: [GHC-26133] TcRnForeignImportPrimSafeAnn [GHC-68444] SumAltArityExceeded [GHC-63966] IllegalSumAlt [GHC-23882] IllegalDeclaration [GHC-60220] InvalidCCallImpent [GHC-18816] RecGadtNoCons [GHC-38140] GadtNoCons [GHC-37056] InvalidTypeInstanceHeader [GHC-78486] InvalidTyFamInstLHS [GHC-39639] DefaultDataInstDecl [GHC-78822] AssocDefaultNotAssoc [GHC-43510] NotSimpleUnliftedType [GHC-41843] IOResultExpected [GHC-07641] AtLeastOneArgExpected [GHC-52886] InvalidTopDecl Remove unused error constructors: [GHC-92057] ImportLookupAmbiguous - - - - - 7b27f25a by Simon Jakobi at 2026-08-14T06:26:54-04:00 testsuite: Drop peak_megabytes_allocated from LinkableUsage tests LinkableUsage01/02 collected all metrics with a 2% tolerance. For peak_megabytes_allocated, whose granularity is 1 MB, that window is under 0.7 MB at this test's ~34 MB peak, so any 1 MB step failed the test (#27613, #27489). Drop that metric: max_bytes_used guards the Linkable-retention property with byte granularity, at a tolerance that still comfortably exceeds the noise observed in CI. Assisted-by: Claude Fable 5 - - - - - e5de423b by Simon Jakobi at 2026-08-14T06:26:54-04:00 testsuite: Don't truncate fractional baselines when computing bounds RelativeMetricAcceptanceWindow.get_bounds truncated the baseline with int() before applying the tolerance. Baselines can be fractional (they are averaged over several measurements), so this skewed the acceptance window downwards: in #27613, a baseline of 33.67 at 2% tolerance yielded bounds (32, 34) instead of (32, 35), rejecting a measurement that was within tolerance. Assisted-by: Claude Fable 5 - - - - - db959f83 by Simon Jakobi at 2026-08-14T15:16:44-04:00 testsuite: Expect length001 failure in nonmoving_thr_sanity length001 relies on an optimization rule to avoid excessive stack use. The nonmoving_thr_sanity way does not enable optimization, so classify its stack overflow as an expected failure, as is already done for the other unoptimized nonmoving ways. Assisted-by: gpt-5.6-sol via Codex CLI - - - - - 4f2b7d90 by Simon Jakobi at 2026-08-14T15:16:44-04:00 testsuite: Omit T22859 in nonmoving threaded ways T22859 checks allocation-limit handlers with output that depends on precise allocation behaviour. The nonmoving threaded ways change where these limits are reached, just as the already-omitted LLVM ways do. Omit these ways instead of treating their incidental output differences as test failures. Assisted-by: gpt-5.6-sol via Codex CLI - - - - - c4abddcb by Simon Jakobi at 2026-08-14T15:16:44-04:00 rts/js: Implement eq_thread, and test Eq/Ord ThreadId (#16761) Since d1f3c63701, Eq ThreadId is implemented via the RTS function eq_thread, but the JS RTS never provided it, so comparing ThreadIds for equality on the JS backend crashed with ReferenceError: h$eq_thread is not defined Like the C implementation, h$eq_thread uses pointer equality: The JS RTS has exactly one thread object per thread. Since previously no test exercised eq_thread directly, this commit adds a test covering equality, its stability across GC, and agreement with Ord. Assisted-by: Claude Fable 5 - - - - - 4a7defa1 by Simon Jakobi at 2026-08-14T15:16:44-04:00 testsuite: Make listThreads1 insensitive to the RTS's own threads listThreads1 expected `listThreads` to return exactly [ThreadId 1]. That holds only under a non-threaded RTS. Under a threaded RTS however there are more threads present, so we change the test to simply check that `myThreadId` is present in the list. Assisted-by: Claude Opus 5 - - - - - b757727a by Vladislav Zavialov at 2026-08-14T15:17:27-04:00 Fix tcLookupId panic with RequiredTypeArguments and PatternSynonyms (#27586) The arguments declared on the left-hand side of a pattern synonym are looked up as term variables bound by its right-hand side. Prior to this patch, that lookup panicked with RequiredTypeArguments: data T a where MkT :: forall a -> T a pattern P :: Int -> T Int pattern P x = MkT x On the RHS, `x` looks like a term argument, so the renamer binds it in the term namespace. Only during type checking does it turn out to be a type variable, so the lookup on the LHS finds an ATyVar rather than an ATcId. As the lookup was done with tcLookupId, it resulted in a panic. Now the arguments are looked up with tcLookupPatSynArg, which reports an illegal term-level use of `x`, just as an ordinary function definition `f (MkT x) = x` does. Test cases: T27586a T27586b T27586c Assisted-by: Claude Opus 5 - - - - - c130188d by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00 loopImports: Don't dup ms_uid in summary imports We were writing the ms_unitid of the mod summary with every single import of that module That complicated the code (as though the UnitId in that list could ever be something else) and also allocates unnecessarily per every mod import. Very slight allocation decrease measured locally in a few tests: (MultiComponentModulesRecomp: -0.06%; MultiComponentModulesRecomp100: -0.05%) Purely a clean up. - - - - - c71166a8 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00 downsweep: make control flow simpler and cache correct This refactor extracts the control flow of downsweep into a single function `dfsBuild`, which takes care of iteratively expanding and traversing all nodes of the in-construction module graph necessary to build a full `ModuleGraph`. There are three levels of caching going on, all of which are necessary to make sure we don't do repeated work (notably, NEVER summarise the same module twice). 1. `dfsBuild` accumulates the final module graph and never revisits the same node of the module graph. Cache is keyed by the final `ModuleGraph`s `NodeKey`s. 2. For Module A in home-unit u1, each import in the list of imports needs to be *found* (call to `findImportedModuleWithIsBoot`): at this point, we only have the `ModuleName` of the import, not the `Module`. This *finding* is somewhat expensive, so we cache it as well (`ImportsCache`). The cache key is the home-unit to which the module belongs~[1], the import package qualifier, and the ModuleName. [1] Different home-units will have different package flags, which means potentially different `Module` resolution for the same `ModuleName`. 3. The most expensive operation we want to avoid is summarising a `Module` into a `ModSummary`, which notably involves parsing the module header from scratch. The third cache, in essence, maps a `Module` to its `ModSummary` (named `ModSummaryCache`). This cache upholds the invariant: we NEVER summarise the same module twice. In practice, the cache key is the Module's UnitId and the Source path; the reason is we need to distinguish between `.hs` and `.hs-boot` files, as their summaries will differ. Note that (2) can't guarantee this alone: Two ModuleName imports in separate units can (and likely do) map to the same `Module`. Note that the previous implementation failed to achieve the no-duplicate-work summarisation invariant, and we ended up doing a quadratic amount of processing in scenarios like test `MultiComponentModules100`. See also Note [Downsweep Control Flow and Caching] Fixes #27461 Perf changes: MultiComponentModules(normal) ghc/alloc 2,097,389,264 1,992,186,736 -5.0% GOOD MultiComponentModules100(normal) ghc/alloc 24,310,173,770 21,293,867,360 -12.4% GOOD MultiComponentModulesRecomp(normal) ghc/alloc 602,761,394 498,543,984 -17.3% GOOD MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,968,240 8,895,404,864 -25.2% GOOD ------------------------- Metric Decrease: MultiComponentModules MultiComponentModules100 MultiComponentModulesRecomp MultiComponentModulesRecomp100 ------------------------- - - - - - ebc4047b by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00 implicitRequirementsShallow can never reach HoleUnit findImportedModule will never return `HoleUnit` for a `ModuleName` (a `HoleUnit` can only be found as a signature instantiation, never as a directly *imported* thing) Therefore, we can drop `[ModuleName]` returned by `implicitRequirementsShallow`, which makes many things dead code. Namely, the call to `implicitRequirementsShallow` from GHC.Driver.Downsweep which was a performance bottleneck (for doing lots of duplicate work in findImportedModule) is now entirely gone. Fixes #27053 In an MR with this patch and the downsweep refactor (previous commit), CI says: MultiComponentModules(normal) ghc/alloc 2,097,396,728 1,943,662,304 -7.3% GOOD MultiComponentModules100(normal) ghc/alloc 24,310,182,136 17,227,574,440 -29.1% GOOD MultiComponentModulesRecomp(normal) ghc/alloc 602,769,518 449,973,656 -25.3% GOOD MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,976,408 4,828,894,160 -59.4% GOOD ------------------------- Metric Decrease: MultiComponentModules MultiComponentModules100 MultiComponentModulesRecomp MultiComponentModulesRecomp100 ------------------------- - - - - - 85a6ab01 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00 downsweep: Cache negative results When traversing a module graph structure, a uniquely identified node should always expand to the same thing. I don't see how visiting the same node which failed to be expanded a first time would ever successfully expand the second time we try to expand it (eg. when coming from a different edge to it -- it is still the same node!). The node expansion is local, based just based on the node itself, not on the path to get there. Therefore, this patch removes the weird behavior and commentary of `dfsBuild` wrt to `Nothing` not being cached and being potentially expanded a second time around to something different, which was misleading and, ultimately, incorrect. Now, we have a `MGRes`, which is more explicit about a node being Skipped just being a node that is ignored whenever it is found (and that skip is cached) -- and we may want to do this due to failures or due to just trying nodes which might not work on purpose, like hs-boots. We uniformly cache positive and negative results and remove the assumption that there might be an ordering in which the same node visited at a later time might be expanded differently. This makes it possible to traverse the module nodes in parallel without a change in behavior, since there's no longer a hidden ordering requirement. - - - - - 56747c3f by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00 Organize and clean-up GHC.Driver.Downsweep Simply some cosmetic changes, moving definitions around to structure the module better into its relevant sections (In go (ns ++ ss), it's not a problem to use ++ because it's a good producer and we won't have to append fully before processing the next item in go) - - - - - 12f64118 by Wolfgang Jeltsch at 2026-08-15T06:31:12-04:00 Add support for textual output of bytecode file content - - - - - a737df91 by Brandon Chinn at 2026-08-15T12:40:25-04:00 Add law in qualified strings doc - - - - - e3188581 by Zubin Duggal at 2026-08-15T12:41:06-04:00 DmdAnal: Fix maxDmdType We need to eta expand the smaller DmdType using defaultArgDmd, like in lubDmdType. Introduce zipDmdType as a common combinator to implement both maxDmdType and lubDmdType uniformly. fixes #27626 - - - - - ca9b0b22 by mangoiv at 2026-08-15T12:41:47-04:00 hadrian: set the executable bit for hie-bios.bat - - - - - 1aac7095 by sheaf at 2026-08-16T04:37:16-04:00 Avoid wasteful allocations in mkTyConAppCo The idiom "traverse isReflCo_maybe" followed by "map fst" used in 'GHC.Core.Coercion.mkTyConAppCo' was allocating a lot of waste. This commit uses 'GHC.Data.Unboxed.traverseMaybeUB' to avoid all these unnecessary intermediate allocations. In a quick microbenchmark for 'mkTyConAppCo', this change resulted in: - refl case (all argument coercions are reflexive): - -60% runtime - -80% allocations - non-refl case: - from 0% to -12% runtime (depending on which argument is non-refl) - from 0% to -70% allocations ( -- '' -- ) Fixes #27648 ------------------------- Metric Decrease: FamAppCachePerf SimplCastPerf T12425 T15703 T26426 T3064 T9872a T9872b T9872b_defer T9872c T9872d T5321Fun T9020 T9630 TcPlugin_RewritePerf Metric Increase: LinkableUsage02 ------------------------- - - - - - 3915e982 by Alan Zimmerman at 2026-08-16T04:37:58-04:00 EPA: Remove al_trailing from AnnList It was not being used - - - - - fed942ac by Andreas Klebinger at 2026-08-17T12:11:57-04:00 testsuite: Use sigkill in process009. SIGHUB might have been blocked by a (grand)*parent of the test. In such cases the test would fail as the python process would simply exist gracefully instead of committing to a premature end. By using SIGKILL we can rely on the signal not being blocked, fixing #27578 in the process. - - - - - 574c875f by Andreas Klebinger at 2026-08-17T12:12:39-04:00 Simplify comparison in DFM.hs Fixes #27669 - - - - - d8f1a2a3 by Alan Zimmerman at 2026-08-17T12:13:18-04:00 TTG: Add extension points to BooleanFormula They are currently unused, but will be used for exact print annotations next, allowing us to get rid of LocatedBF / SrcSpanAnnBF - - - - - 93a2b20f by Andreas Klebinger at 2026-08-18T04:31:04-04:00 Fix a number of incorrect module references: Fix module reference in Note [DataCon wrappers are conlike]. Fix module reference in Note [Detailed InertCans Invariants]. Fix module reference in Note [GHC's data format representations]. Fix module reference in Note [Grand plan for static forms]. Fix module reference in Note [How tuples work]. Fix module reference in Note [Solved dictionaries]. Fix module reference in Note [Stacktraces from Info Table Provenance Entries (IPE based stack unwinding)]. Fix module reference in Note [The VarBndr type and its uses]. Found the incorrect references with a llm. - - - - - eb0dfb01 by Simon Jakobi at 2026-08-18T04:31:44-04:00 ci: Run stack-hadrian-build only in full-ci pipelines The job exists to catch changes that break hadrian/build-stack (#18726), but nothing in the pipeline depends on it, and it can only break when hadrian's dependencies change. Restricting it to full-ci (like hadrian-multi) still covers marge-bot merge batches, so such breakage cannot reach master unnoticed, while ordinary validate pipelines skip the job. Assisted-by: Claude Fable 5 - - - - - b9160962 by Simon Jakobi at 2026-08-20T14:57:52-04:00 testsuite: Show baseline sample count and range in perf failures A perf baseline is the mean of all samples recorded for a commit, and it prints as a single number, hiding how far the samples spread. When the spread is wide, this can indicate an unstable metric that isn't actually useful as a signal for the perf tests. For example, in #27602, T27336's peak_megabytes_allocated baseline showed as 757 when the underlying samples were 605 and 909. When the baseline is averaged from more than one sample, say so in the failure output: the one-line stat-failure reason shows the sample range, and the detail block lists the raw samples. Single-sample baselines print exactly as before. Context: #27602 Assisted-by: Claude Fable 5 - - - - - a4979877 by Simon Jakobi at 2026-08-20T14:57:52-04:00 testsuite: Fold Baseline into CommitMetric A Baseline was just a CommitMetric plus the commit it came from, built by copying fields across. Since get_commit_metric already knows that commit, record it on CommitMetric itself and drop Baseline. This also collapses both branches of find_baseline into plain returns. Assisted-by: Claude Fable 5 - - - - - 99fb8d68 by Simon Jakobi at 2026-08-20T14:57:52-04:00 ci: Clarify comment on pushing perf notes after failures Context: #27602 Assisted-by: Claude Fable 5 - - - - - 2ca87972 by Alan Zimmerman at 2026-08-20T14:58:36-04:00 EPA: Remove LocatedBC / SrcSpanBF The custom annotations are now in the BooleanFormula TTG extension points, so LBooleanFormula can now use the standard LocatedA. - - - - - d2bc32aa by Simon Peyton Jones at 2026-08-21T12:59:26-04:00 Better handling of serialisation of wired-in names Fixes #27501 - - - - - d2795ffc by Alan Zimmerman at 2026-08-21T13:00:05-04:00 EPA: Remove NoEpTok/NoEpUniTok, using an unhelpful SrcSpan instead Also introduce helper functions noEpTok and noEpUniTok to serve as simple replacements in code inserting an token annotation without location information. - - - - - b5d29ab8 by Brandon Chinn at 2026-08-25T18:42:08-04:00 Add Data.RealFloat and Infinity/NegInfinity/NaN pattern synonyms (#26961) - - - - - e60eb3bc by Andreas Klebinger at 2026-08-25T18:42:59-04:00 rts linker: Fix pointer arithmetic issue in flushInstructionCacheRISCV64 We accidentally operated over `uint64_t*` when we should use `uint8_t`. Fixes #27569 - - - - - e9bbe8f9 by Andreas Klebinger at 2026-08-26T15:09:23-04:00 cmm dumps: Add machop width info with -dppr-debug for infix ops. - - - - - 86e3a9d8 by Andreas Klebinger at 2026-08-26T15:09:24-04:00 CmmLint: Check for unsupported MachOp widths machOpArgReps now maps MachOp + Width to a list of supported argument widths or Nothing if the given operation is not supported at the given width. This allows us to check for nonsensical combinations like FloatToInt at Word16. Similarly we now check that every address is actually wordwidth. - - - - - 13781cca by Andreas Klebinger at 2026-08-26T15:09:24-04:00 arm64 ncg: The big subword truncation fix. A set of slightly related fixes to arm subword handling: Bitmask immediates: Don't produce overflowing assembly literals. There is still another bug here that causes us to miss some valid literals but we will fix that later. Improve subword truncation handling: We now use a small set of helpers to truncate `Register` values rather than truncating immediate `Reg` values which greatly simplifies the code structure. This fixes a great many bugs to do with sign/zero extending subwords or the lack thereof. We now establish the invariant that subword values are zero-extended at every site at which they come into "scope" of the ncg, and rely on the invariant throughout rather than pessimistically inserting redundant extensions in a hodgepodge manner at the use sites of these values. This fixes at least the bugs described in issues #27533, #27430 #27537, #27538, #27539, and #27550. But likely more bugs yet not found. Subword ffi results: Apply truncations when calling functions returning subword values. genCondJump: Don't sign extend signed values in the input register as it might map to a local variable, corrupting the value stored within. Fix subword store/load instructions.: We used to read those at 32bit width even for smaller values possibly resulting in invalid memory access. Now we construct the suffix for subword variants based on the instruction format for these. - - - - - d8fa5d7c by Andreas Klebinger at 2026-08-26T15:09:24-04:00 arm64 ncg: Fix MO_V_Broadcast for non-literals. We now use OpReg instead of OpScalarAsVec as required since we broadcast a gp register. Also adds a test. Fixes #27565. - - - - - 94822c95 by Andreas Klebinger at 2026-08-26T15:09:24-04:00 Add some test cases covering bugs in the arm ncg. * Test for #27430 (subword ffi results) * #27537 - subword conversions * #27538 - subwords used in conditional * #27533 - single byte read - - - - - dd1ba88a by Andreas Klebinger at 2026-08-26T15:09:24-04:00 cmmLint: Lint against MO_FS_Truncate subword use. - - - - - fd22f71e by Zubin Duggal at 2026-08-26T15:10:20-04:00 ghc-internal: annotateSTM should use catchSTM# rather than catch# A catch# frame inside a transaction breaks retry and async exception delivery. Fixes #27657 - - - - - bb324171 by Rodrigo Mesquita at 2026-08-26T15:10:59-04:00 rts: refactor to reduce THREADED_RTS in MSG_UPD_TSO_FLAGS - No behavior change in this commit (well, a small optimization here makes us do less work if the target TSO owned by the curr. capability) - Move all THREADED_RTS CPP needed into `updThreadFlag` - Merge MSG_SET_TSO_FLAGS and MSG_UNSET_TSO_FLAGS into MSG_UPD_TSO_FLAGS plus a `set` bool field in the MessageUpdTSOFlag struct Towards #27729 - - - - - ed99b7b7 by Rodrigo Mesquita at 2026-08-26T15:10:59-04:00 rts: Fix race condition in MSG_UPD_TSO_FLAGS execution The code for processing the MSG_UPD_TSO_FLAGS message was not taking into consideration that the TSO's owner might have moved in between that capability receiving the message (since it was its previous owner) and starting to process its inbox (a point at which it was no longer the owner) Added Note [TSO owner may change in between Msg being sent and received] to explain this race and the pattern used to fix this, where we just forward the message to the new owner. Fixes #27729 - - - - - cd653714 by Alan Zimmerman at 2026-08-26T15:11:49-04:00 EPA: Uses Parsers.parseModule for exactprint tests Parsers.parseModule is the advertised way to parse for use for exact printing in the ghc-exactprint library. This commit updates the GHC exact print testing to use it. This requires moving the comment balancing that was occurring only in the test path into the advertising parser path, so it moves from Transforms.hs to Utils.hs. Also update the comment adding to honour trailing annotations - - - - - d1d01fa5 by Wolfgang Jeltsch at 2026-08-27T13:17:59+03:00 Add `rethrowSTM` and improve STM-related documentation Adding `rethrowSTM` resolves #26758. The implementation of `rethrowSTM` is completely analogous to the one of `rethrowIO`. The following is established for the documentation of `throwSTM` and `catchSTM`: * Both operations are directly described as analogs of their `IO` counterparts. * There is no reference to `throw` in the documentation of `throwSTM`, because, although such a reference is great in the documentation of `throwIO`, it is somewhat out of place in the documentation of `throwSTM`. * Instead of repeating part of `throwIO`’s documentation, the documentation of `throwSTM` just recommends using `throwSTM` instead of `throw` and references the corresponding arguments in the documentation of `throwIO`. - - - - - 06fde293 by fendor at 2026-08-28T06:06:44-04:00 GHCi: Fix order of `PackageDBFlag`s for interactive home unit `PackageDBFlag`s are stored in reverse order of cli specification. When sorting the `PackageDBFlag`s by longest common prefix, we need thus to reverse the package db stacks before calculating the prefix. We make sure to reverse the package db stack for the interactive home unit to uphold that later specified package dbs overwrite earlier ones. Resolved and adds regression test for #27640 - - - - - 024c4d04 by fendor at 2026-08-28T06:07:23-04:00 Reuse the UnitIndexCache after initialising multiple home units - - - - - 55326fa0 by Alan Zimmerman at 2026-08-28T06:08:03-04:00 EPA: Some Haddock processing tweaks These changes to the Haddock postprocessing should not change behaviour, but just bring it more closely in line with the original, changed at 44309cd377f And add some haddock exactprint tests to show they work. - - - - - b3ddee95 by Andreas Klebinger at 2026-08-28T13:57:46-04:00 hadrian: Deprecate quickest flavour. It was more of a trap for new users than actually beneficial so we deprecate it and suggest quick+no_dynamic_libs to users instead. - - - - - a1d81390 by Andreas Klebinger at 2026-08-28T13:58:37-04:00 cmm: Always favour entry block during block deduplication. We now always keep the first block in the CmmGraph. This way we avoid the need to update the entry info table. Failing to do so caused #27722. Fixes #27722. - - - - - 5bd65f00 by Andreas Klebinger at 2026-08-28T13:59:16-04:00 test: FamAppCachePerf - Only collect bytes allocated. Fixes 27747 - - - - - ced53ce6 by mangoiv at 2026-08-29T07:15:24-04:00 nightlies: output yaml to file only Previously we would just output the metadata to stdout which risks that it's clobbered by incidental debugt output. We now output to file only. Fixes #27511 - - - - - 578bd185 by Andreas Klebinger at 2026-08-29T07:16:05-04:00 Specialise: Stop looping on recursive dictionaries in interestingDict interestingDict now doesn't look through loopbreaker unfoldings. Doing so would cause infinite loops on certain dictionaries. Fixes #27705. - - - - - 7bf546fc by Simon Peyton Jones at 2026-08-31T23:48:53-04:00 Never make an absent filler for a constraint type mkAbsentFiller used isTerminatingType to decide, but that is not enough. Consider class Eq a => UC a where {} let u :: UC Int -- UC Int is a "non-terminating type" u = error "Absent" let e :: Eq Int -- Eq Int is a "terminating type" e = $p1UC u We clearly must not make a filler for `e`, because we speculatively evaluate it. But speculatively evaluating `e` forces `u`, so we must not make one for `u` either. Asking isDictTy instead is not enough either, because it does not catch a constraint hidden behind an unreduced type family application: type family F a :: Constraint type instance F W = TC W a :: F W => Int -> Int -- (F W) argument is absent Oops! Entered absent arg Arg: irred Type: F W So play safe and use isPredTy: never make an absent filler for any constraint-kinded type. Fixes #27627 - - - - - 5f474953 by Zubin Duggal at 2026-08-31T23:48:53-04:00 Add tests for absent fillers at dictionary types T27627 a unary class whose superclass is a non-unary class T27627a ...whose superclass is a Constraint-kinded type family T27627b ...whose superclass is a quantified constraint T27627c a unary class applied to itself, (UC (UC (TC a))) T27627e a (forall b. P b) dictionary that loops - - - - - cd5c6bcc by Zubin Duggal at 2026-08-31T23:48:53-04:00 An abstract TyCon may hide a unary class A class declared in an hs-boot file is an AbstractTyCon inside the module loop, and compiling the real declaration may reveal it to be a UnaryClassTyCon. - isTerminatingType returned True for such AbstractTyCons - IfaceToCore set the unary flag to False in the DFunId So we could end up speculating bottom dictionaries because inside a module loop we see an UnaryClassTyCon as an AbstractTyCon Use isTerminatingTyCon, which returns False for an abstract TyCon. The Bool in DFunId is now a cache for isTerminatingTyCon, set in mkDFunIdDetails. Fixes #27704 - - - - - abfc224a by Zubin Duggal at 2026-08-31T23:48:53-04:00 Specialise: don't replace dead args with absent fillers specHeader decides an argument is dead by calling isDeadBinder on a binder of the /optimised RHS/, then applies the filler to the /stable unfolding/ template instead. The two may differ, so the argument can be dead in the RHS and not in the template. The specialised function's unfolding then has an absent filler, and any call site that inlines it evaluates the error thunk. Dropping dead args in the specialiser is rarely worth it, to quote Simon, "The later worker/wrapper pass will pick up the dead arg later if it is really dead. Keeps the specialiser simpler." So instead of trying to check if the arg really is dead in the stable unfolding, just drop the logic for dropping dead args in the specialiser altogeher. Fixes #27703 - - - - - 1557fd1c by Zubin Duggal at 2026-08-31T23:48:53-04:00 CorePrep: don't speculate a call across an hs-boot edge We take care not to evaluate things that might be bottom, like a looping dictionary group, but our analysis is defeated by boot files. We only track recursion within a module, so two dictionaries that depend on each other across a module loop each look non-recursive, and we might speculate them. Any recursion we cannot see must cross an hs-boot edge, so refuse to speculate calls that cross one. Fixes #27717 - - - - - 4117e5ae by Wolfgang Jeltsch at 2026-08-31T23:49:35-04:00 Incorporate the `rethrowSTM` reexport into the `stm` submodule - - - - - 4bfbf5c8 by ARATA Mizuki at 2026-09-01T18:55:08-04:00 testsuite: Fix out-of-bounds access in T3586 unsafeRead and unsafeWrite use 0-based index. Looking at #3586, the expected output seems to be 2.8e8. Addresses #27596 - - - - - 3f9db6d4 by ARATA Mizuki at 2026-09-01T18:55:08-04:00 testsuite: Fix out-of-bounds access in T21305 writeInt64Array# takes an index measured in units of Int64 elements. Fixes #27596 - - - - - 44d7788f by Simon Peyton Jones at 2026-09-01T18:55:53-04:00 Fix buglet in INLINE-arity calculation for pattern synonyms This fixes #27744. The buglet was accidentally introduced by commit 3a0f9a51c1dacc474c7fd128082edd8bf4081256 Author: Simon Peyton Jones <simon.peytonjones(a)gmail.com> Date: Sat Aug 1 00:13:02 2026 +0100 Fix three bugs related to required type args and INLINE pragmas I failed to find all the calls to `addInlinePragArity`! - - - - - df058f1d by Simon Jakobi at 2026-09-02T07:18:06-04:00 testsuite: Migrate perf tests off collect_compiler_stats('all') The 'all' metric argument applies a single tolerance to bytes allocated, max_bytes_used and peak_megabytes_allocated, although their noise profiles are incompatible (#27653): allocations are nearly deterministic, residency needs 10-20%, and peak is quantized to 1 MB. Any single tolerance is too tight for one metric or too slack for another. This migrates the remaining users of 'all' (and of the 'all' default) to explicit per-metric collection, ahead of removing 'all' from the driver. peak_megabytes_allocated is dropped everywhere: its 1 MB granularity makes tight relative windows meaningless (#27613), and it is sensitive to GC timing. In #27489 it drifted by -5.3% while max_bytes_used moved by less than 0.1%. Where a test guards a memory property, max_bytes_used covers it at byte granularity. Where the motivating ticket was about compile-time memory (T11545, T15304, T26425), residency remains gated via max_bytes_used, now with a residency-appropriate tolerance. max_bytes_used is dropped where residency was only ever an accident of 'all': * T15630, T15630a, T20261: the underlying tickets (#15630, #20261) contain no memory data at all. One is a simplifier-ticks blowup and the other is stated entirely in allocation numbers, so the 20% window never had teeth. * T21839c: #21839's measurements show residency essentially flat (+0.16%) while allocations moved +7%, so allocations are the discriminating metric. They are already gated at 1% via collect_compiler_runtime. The ghc/max gate had previously broken CI spuriously (9fd11585eb widened it from 1% to 10% for that reason). Allocation tolerances are tightened to the testsuite's conventional 2% where 'all' previously left them at 10-20%. Assisted-by: Claude Fable 5 - - - - - 72dd2432 by Simon Jakobi at 2026-09-02T07:18:06-04:00 testsuite: Remove the 'all' metric argument of collect_stats 'all' gated bytes allocated, max_bytes_used and peak_megabytes_allocated at a single tolerance, although their noise profiles are incompatible, making such tests either flaky or toothless (#27653). Closes #27653. Assisted-by: Claude Fable 5 - - - - - 2228cb30 by Simon Jakobi at 2026-09-02T07:18:06-04:00 testsuite: Make the deviation argument of collect_stats mandatory Almost every caller passes an explicit tolerance matched to the metric's noise profile, and the silent 20% default is far slacker than 'bytes allocated' merits. Only two tests relied on it. They now state their tolerance explicitly: large-project gets 10%, in line with other large compile-time tests. T9848 gets 2%: its metric is byte-for-byte deterministic across CI jobs and platforms of a given test_env, has drifted only about 2.5% since 2015, and the fusion failure it guards against would show up as a roughly +30000% jump. Assisted-by: Claude Fable 5 - - - - - 56291fc5 by Cheng Shao at 2026-09-02T07:18:45-04:00 autoconf/ghc-toolchain: bump llvm upper bound to support llvm 23 This commit bumps llvm upper bound to support llvm 23. - - - - - 20eb3f41 by Cheng Shao at 2026-09-02T07:18:45-04:00 rts: fix compilation issues with clang 23 clang 23 has broadened `-Wall`/`-Wextra` ranges, exposing some minor issues in the rts when building with validate flavours: - Unused locals - `#pragma GCC diagnostic pop` mismatch This commit fixes those. - - - - - 9e7739ab by Simon Jakobi at 2026-09-03T13:45:43-04:00 Add -Wimplicit-field-strictness (#16836) This opt-in warning fires when a data constructor field lacks an explicit strictness annotation (`!` or `~`). It complements the LazyFieldAnnotations extension (4762a8bf30f) from GHC proposal 752, which makes `~` annotations available for this purpose. Deciding which fields to report requires their levity, so the check runs after typechecking. To keep the noise down, the diagnostic is emitted once per data declaration, grouped by constructor. Closes #16836. Assisted-by: Claude Fable 5 - - - - - 6a44d591 by mangoiv at 2026-09-03T13:46:22-04:00 simplifier: remove a bogus `assert` in `rebuild_app'` in `GHC.CoreToStg.Prep.cpeApp`. Prior to this commit commit 08bc245be70d95801bc1138804ed1de9474fbdc0 Author: sheaf <sam.derbyshire(a)gmail.com> Date: Sat Feb 28 16:30:43 2026 +0100 Clean up join points, casts & ticks This commit shores up the logic dealing with casts and ticks occurring in between a join point binding and a jump any `PlaceRuntime` ticks we observed were profiling ticks, even though that isn't necessary. The more liberal rules in the above commit allow e.g. breakpoint ticks (which are valid PlaceRuntime ticks) to legitimately appear in an argument position. Fixes #27556 - - - - - eaa95a6f by Andrei Borzenkov at 2026-09-04T08:08:40-04:00 Parentheses in prefix GADT constructors (#27423) Updated `splitLHsGadtTy` to allow looking through the parentheses for inner binders. General example of a code pattern that's allowed now: data S a where MkS :: (forall a. S a) That should work now with any combination of nested foralls and parentheses. We don't perform parenthesis unwrapping for record GADT constructors in accordance with GHC Proposal #402. To this end `con_inner_bndrs` no longer stores plain forall telescopes: `[HsForAllTelescope pass]` is replaced with `[LHsGadtTelescope pass]`, a new `HsArg`-style type whose `HsGadtForAll` holds an inner telescope and whose `HsGadtPar` holds a pair of parentheses. The parentheses carry no meaning for renaming or type checking; the only reason to record them is exact-printing. Updated `pprConDecl` to improve the `parse == parse . ppr . parse` property of GADT pretty-printing. The pretty printer can now output code that's similar to this: data T a where MkT1 :: (forall a. T a) MkT2 :: forall . forall a. T a These are special cases of inner forall binders for prefix GADT constructors, when we have either implicit or zero explicit outer binders. - - - - - 639456a8 by Evgeny Malyshev at 2026-09-04T08:09:25-04:00 HsPat: Add spacing to unary tuple patterns Use hsep when printing unary boxed TuplePat applications so that the MkSolo constructor is separated from its argument. The old hcat rendered wildcard and parenthesized arguments as MkSolo_ and MkSolo(). Add T27034 to exercise the HsPat splice-dump path with wildcard and variable arguments, and update existing affected golden output. Fixes #27034 Assisted-By: OpenAI Codex - - - - - 2908ab36 by Simon Jakobi at 2026-09-05T07:22:17-04:00 X86 NCG: use btr/bts/btc for single-bit operations Previously the Cmm patterns x & ~(1 << i) x | (1 << i) x ^ (1 << i) compiled to mov/shl/not/and-style sequences of 3-4 instructions. Now they compile to a single btr, bts or btc, matching what C compilers produce. When the bit index is a literal, constant folding has already collapsed these patterns into ones with a literal mask, such as x & 0xfffffeffffffffff for x & ~(1 << 40). Such masks are now also compiled to a bit-test instruction when they don't fit in an imm32 and would otherwise have to be loaded into a register first. For a variable bit index, this applies only when the shift is unchecked (uncheckedShiftL#, Data.Bits.unsafeShiftL): the bounds-checked shiftL used by e.g. the default clearBit/setBit/complementBit implementations wraps the shift in a bounds mask that this optimisation does not see through. With a literal index, the bounds mask is constant-folded away, so the checked operations benefit too. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Fixes #25233. Assisted-by: Claude Fable 5 - - - - - c673ecf0 by Simon Peyton Jones at 2026-09-05T07:22:59-04:00 Move HsStatic free-var test to typechecker A `static` form should have no free *term* variables, but it can have free *type* variables. Alas, the renamer does not really know what is a term variable and what is a type variable, because of required type arguments. This patch moves the test to the typechecker, which does know. Addresses #27664 - - - - - b6ca93c6 by Simon Jakobi at 2026-09-06T02:20:42+02:00 X86 NCG: use 32-bit POPCNT for sub-word popcounts For MO_PopCnt at W8/W16, use 32-bit POPCNT instead of the 16-bit form. A 32-bit write zero-extends the result to the full register, so the separate zero-extension of the result is no longer needed. Also skip zero-extending the argument when it is visibly already zero-extended, as in popCount on Word8, which calls popCnt8# on word8ToWord# x. For the byte-wise popcount loop from #24813 this shrinks the popcount sequence from 5 instructions to 3. Assisted-by: Claude Fable 5.1 - - - - - 1575 changed files: - .gitignore - .gitlab-ci.yml - .gitlab/ci.sh - .gitlab/merge_request_templates/Default.md - .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py - + changelog.d/21101 - + changelog.d/27380 - + changelog.d/27532 - + changelog.d/27556 - + changelog.d/27626 - + changelog.d/27627 - + changelog.d/27703 - + changelog.d/27704 - + changelog.d/27717 - + changelog.d/T20363 - + changelog.d/T21628 - + changelog.d/T26423 - + changelog.d/T26532 - + changelog.d/T26716 - + changelog.d/T27123.md - changelog.d/T27202 - + changelog.d/T27314.md - + changelog.d/T27329 - + changelog.d/T27360 - + changelog.d/T27368-ppr-unreachable-cmm-blocks.md - + changelog.d/T27374 - + changelog.d/T27440 - + changelog.d/T27455 - + changelog.d/T27456 - + changelog.d/T27557 - + changelog.d/T27583 - + changelog.d/T27586 - + changelog.d/T27589 - + changelog.d/T27639 - + changelog.d/T27657 - + changelog.d/T27705 - + changelog.d/T27722-cbe-entry-block.md - + changelog.d/T27744 - + changelog.d/T27764 - + changelog.d/allow-gadt-prefix-con-parens - + changelog.d/arm_ncg_fixes_T27430 - + changelog.d/downsweep-refactor - + changelog.d/fix-absent-dict-projection - + changelog.d/fix-cmm-atomic-load-store - + changelog.d/fix-cmm-dump-labels - + changelog.d/fix-heap-census-large-arrays-19048 - + changelog.d/fix-make-install-j - + changelog.d/fix-peekitbl-no-tntc - + changelog.d/fix-use-std-ap-thunk - + changelog.d/implicit-field-strictness-warning - + changelog.d/inter-module-far-jumps-aarch64-default - + changelog.d/lazy-field-annotations - + changelog.d/link-deterministic-order - + changelog.d/llvm-23 - + changelog.d/ncg-x86-bit-test-instructions - + changelog.d/refactor-known-names - + changelog.d/rethrow-stm - + changelog.d/show-byte-code - + changelog.d/unit-index - + changelog.d/warn-defaulted-callstack - compiler/GHC.hs - + compiler/GHC/Builtin.hs - + compiler/GHC/Builtin/KnownKeys.hs - + compiler/GHC/Builtin/KnownOccs.hs - + compiler/GHC/Builtin/Modules.hs - − compiler/GHC/Builtin/Names.hs - − compiler/GHC/Builtin/Names/TH.hs - compiler/GHC/Builtin/PrimOps.hs - compiler/GHC/Builtin/PrimOps/Casts.hs - compiler/GHC/Builtin/PrimOps/Ids.hs - + compiler/GHC/Builtin/TH.hs - compiler/GHC/Builtin/Uniques.hs - compiler/GHC/Builtin/Uniques.hs-boot - − compiler/GHC/Builtin/Utils.hs - + compiler/GHC/Builtin/WiredIn/Ids.hs - compiler/GHC/Builtin/Types/Prim.hs → compiler/GHC/Builtin/WiredIn/Prim.hs - compiler/GHC/Builtin/Types/Literals.hs → compiler/GHC/Builtin/WiredIn/TypeLits.hs - compiler/GHC/Builtin/Types.hs → compiler/GHC/Builtin/WiredIn/Types.hs - compiler/GHC/Builtin/Types.hs-boot → compiler/GHC/Builtin/WiredIn/Types.hs-boot - compiler/GHC/ByteCode/Asm.hs - compiler/GHC/ByteCode/Breakpoints.hs - compiler/GHC/ByteCode/Serialize.hs - + compiler/GHC/ByteCode/Show.hs - compiler/GHC/ByteCode/Types.hs - compiler/GHC/Cmm.hs - compiler/GHC/Cmm/CLabel.hs - compiler/GHC/Cmm/CommonBlockElim.hs - compiler/GHC/Cmm/Expr.hs - compiler/GHC/Cmm/Lint.hs - compiler/GHC/Cmm/MachOp.hs - compiler/GHC/Cmm/Parser.y - compiler/GHC/Cmm/Pipeline.hs - compiler/GHC/CmmToAsm/AArch64/CodeGen.hs - compiler/GHC/CmmToAsm/AArch64/Instr.hs - compiler/GHC/CmmToAsm/AArch64/Ppr.hs - compiler/GHC/CmmToAsm/Format.hs - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToAsm/X86/Ppr.hs - compiler/GHC/Core.hs - compiler/GHC/Core/Class.hs - compiler/GHC/Core/Coercion.hs - compiler/GHC/Core/Coercion/Axiom.hs - compiler/GHC/Core/Coercion/Opt.hs - compiler/GHC/Core/DataCon.hs - compiler/GHC/Core/FVs.hs - compiler/GHC/Core/FamInstEnv.hs - compiler/GHC/Core/Lint.hs - compiler/GHC/Core/Make.hs - compiler/GHC/Core/Multiplicity.hs - compiler/GHC/Core/Opt/Arity.hs - compiler/GHC/Core/Opt/ConstantFold.hs - compiler/GHC/Core/Opt/CprAnal.hs - compiler/GHC/Core/Opt/DmdAnal.hs - compiler/GHC/Core/Opt/LiberateCase.hs - compiler/GHC/Core/Opt/OccurAnal.hs - compiler/GHC/Core/Opt/SetLevels.hs - compiler/GHC/Core/Opt/Simplify/Env.hs - compiler/GHC/Core/Opt/Simplify/Iteration.hs - compiler/GHC/Core/Opt/SpecConstr.hs - compiler/GHC/Core/Opt/Specialise.hs - compiler/GHC/Core/Opt/WorkWrap.hs - compiler/GHC/Core/Opt/WorkWrap/Utils.hs - compiler/GHC/Core/Ppr.hs - compiler/GHC/Core/Predicate.hs - compiler/GHC/Core/Rules.hs - compiler/GHC/Core/SimpleOpt.hs - compiler/GHC/Core/Subst.hs - compiler/GHC/Core/TyCo/FVs.hs - compiler/GHC/Core/TyCo/Ppr.hs - compiler/GHC/Core/TyCo/Rep.hs - compiler/GHC/Core/TyCon.hs - compiler/GHC/Core/Type.hs - compiler/GHC/Core/Unfold.hs - compiler/GHC/Core/Unify.hs - compiler/GHC/Core/Utils.hs - compiler/GHC/CoreToIface.hs - compiler/GHC/CoreToStg.hs - compiler/GHC/CoreToStg/Prep.hs - compiler/GHC/Data/BooleanFormula.hs - compiler/GHC/Data/FastString.hs - compiler/GHC/Data/StringBuffer.hs - compiler/GHC/Data/Unboxed.hs - compiler/GHC/Data/Word64Map/Internal.hs - compiler/GHC/Data/Word64Map/Lazy.hs - compiler/GHC/Data/Word64Map/Strict.hs - compiler/GHC/Data/Word64Map/Strict/Internal.hs - compiler/GHC/Driver/Backend.hs - compiler/GHC/Driver/Backpack.hs - compiler/GHC/Driver/CodeOutput.hs - compiler/GHC/Driver/Config/StgToCmm.hs - compiler/GHC/Driver/Config/Tidy.hs - compiler/GHC/Driver/Downsweep.hs - compiler/GHC/Driver/DynFlags.hs - compiler/GHC/Driver/Env.hs - compiler/GHC/Driver/Env/KnotVars.hs - compiler/GHC/Driver/Env/Types.hs - compiler/GHC/Driver/Errors/Ppr.hs - compiler/GHC/Driver/Flags.hs - compiler/GHC/Driver/GenerateCgIPEStub.hs - compiler/GHC/Driver/Main/Compile.hs - compiler/GHC/Driver/Main/Hsc.hs - compiler/GHC/Driver/Main/Interactive.hs - compiler/GHC/Driver/Main/Passes.hs - compiler/GHC/Driver/Make.hs - compiler/GHC/Driver/MakeFile.hs - compiler/GHC/Driver/Pipeline.hs - compiler/GHC/Driver/Pipeline/Execute.hs - compiler/GHC/Driver/Plugins.hs - compiler/GHC/Driver/Session.hs - compiler/GHC/Driver/Session/Units.hs - compiler/GHC/Hs.hs - compiler/GHC/Hs/Basic.hs - compiler/GHC/Hs/Binds.hs - compiler/GHC/Hs/Decls.hs - compiler/GHC/Hs/Decls/Overlap.hs - compiler/GHC/Hs/Doc.hs - compiler/GHC/Hs/DocString.hs - compiler/GHC/Hs/Dump.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/Hs/ImpExp.hs - compiler/GHC/Hs/Instances.hs - compiler/GHC/Hs/Lit.hs - compiler/GHC/Hs/Pat.hs - − compiler/GHC/Hs/Specificity.hs - compiler/GHC/Hs/Stats.hs - compiler/GHC/Hs/Syn/Type.hs - compiler/GHC/Hs/Type.hs - compiler/GHC/Hs/Utils.hs - compiler/GHC/HsToCore.hs - compiler/GHC/HsToCore/Arrows.hs - compiler/GHC/HsToCore/Binds.hs - compiler/GHC/HsToCore/Breakpoints.hs - + compiler/GHC/HsToCore/Breakpoints/Types.hs - compiler/GHC/HsToCore/Docs.hs - compiler/GHC/HsToCore/Errors/Types.hs - compiler/GHC/HsToCore/Expr.hs - compiler/GHC/HsToCore/Foreign/C.hs - compiler/GHC/HsToCore/Foreign/Call.hs - compiler/GHC/HsToCore/Foreign/JavaScript.hs - compiler/GHC/HsToCore/Foreign/Utils.hs - compiler/GHC/HsToCore/Foreign/Wasm.hs - compiler/GHC/HsToCore/ListComp.hs - compiler/GHC/HsToCore/Match.hs - compiler/GHC/HsToCore/Match.hs-boot - compiler/GHC/HsToCore/Match/Constructor.hs - compiler/GHC/HsToCore/Match/Literal.hs - compiler/GHC/HsToCore/Monad.hs - compiler/GHC/HsToCore/Pmc/Check.hs - compiler/GHC/HsToCore/Pmc/Desugar.hs - compiler/GHC/HsToCore/Pmc/Ppr.hs - compiler/GHC/HsToCore/Pmc/Solver.hs - compiler/GHC/HsToCore/Pmc/Solver/Types.hs - compiler/GHC/HsToCore/Quote.hs - compiler/GHC/HsToCore/Ticks.hs - compiler/GHC/HsToCore/Types.hs - compiler/GHC/HsToCore/Usage.hs - compiler/GHC/HsToCore/Utils.hs - compiler/GHC/Iface/Binary.hs - compiler/GHC/Iface/Env.hs - − compiler/GHC/Iface/Env.hs-boot - compiler/GHC/Iface/Errors/Ppr.hs - compiler/GHC/Iface/Errors/Types.hs - compiler/GHC/Iface/Ext/Ast.hs - compiler/GHC/Iface/Ext/Types.hs - compiler/GHC/Iface/Load.hs - compiler/GHC/Iface/Make.hs - compiler/GHC/Iface/Recomp.hs - compiler/GHC/Iface/Syntax.hs - compiler/GHC/Iface/Tidy.hs - compiler/GHC/Iface/Tidy/StaticPtrTable.hs - compiler/GHC/Iface/Type.hs - compiler/GHC/Iface/Warnings.hs - compiler/GHC/IfaceToCore.hs - compiler/GHC/Parser.y - compiler/GHC/Parser/Annotation.hs - compiler/GHC/Parser/Errors/Ppr.hs - compiler/GHC/Parser/Errors/Types.hs - compiler/GHC/Parser/HaddockLex.x - compiler/GHC/Parser/Header.hs - compiler/GHC/Parser/Lexer.x - compiler/GHC/Parser/PostProcess.hs - compiler/GHC/Parser/PostProcess/Haddock.hs - compiler/GHC/Platform/Ways.hs - compiler/GHC/Plugins.hs - compiler/GHC/Rename/Bind.hs - compiler/GHC/Rename/Env.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/Splice.hs - compiler/GHC/Rename/Unbound.hs - compiler/GHC/Rename/Utils.hs - compiler/GHC/Runtime/Context.hs - compiler/GHC/Runtime/Debugger.hs - compiler/GHC/Runtime/Eval.hs - compiler/GHC/Runtime/Heap/Inspect.hs - compiler/GHC/Runtime/Interpreter.hs - compiler/GHC/Runtime/Loader.hs - compiler/GHC/Stg/BcPrep.hs - compiler/GHC/Stg/Lint.hs - compiler/GHC/Stg/Unarise.hs - compiler/GHC/StgToByteCode.hs - compiler/GHC/StgToCmm/Bind.hs - compiler/GHC/StgToCmm/Config.hs - compiler/GHC/StgToCmm/DataCon.hs - compiler/GHC/StgToCmm/Env.hs - compiler/GHC/StgToCmm/Foreign.hs - compiler/GHC/StgToCmm/Lit.hs - compiler/GHC/StgToCmm/Prim.hs - compiler/GHC/StgToCmm/Ticky.hs - compiler/GHC/StgToJS/Apply.hs - compiler/GHC/StgToJS/Arg.hs - compiler/GHC/StgToJS/Expr.hs - compiler/GHC/StgToJS/FFI.hs - compiler/GHC/StgToJS/Linker/Utils.hs - compiler/GHC/StgToJS/Utils.hs - compiler/GHC/Tc/Deriv.hs - compiler/GHC/Tc/Deriv/Functor.hs - compiler/GHC/Tc/Deriv/Generate.hs - compiler/GHC/Tc/Deriv/Generics.hs - compiler/GHC/Tc/Deriv/Infer.hs - compiler/GHC/Tc/Deriv/Utils.hs - compiler/GHC/Tc/Errors.hs - compiler/GHC/Tc/Errors/Hole.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Errors/Types.hs - compiler/GHC/Tc/Gen/App.hs - compiler/GHC/Tc/Gen/Arrow.hs - compiler/GHC/Tc/Gen/Bind.hs - compiler/GHC/Tc/Gen/Default.hs - compiler/GHC/Tc/Gen/Export.hs - compiler/GHC/Tc/Gen/Expr.hs - compiler/GHC/Tc/Gen/Foreign.hs - compiler/GHC/Tc/Gen/Head.hs - compiler/GHC/Tc/Gen/HsType.hs - compiler/GHC/Tc/Gen/Match.hs - compiler/GHC/Tc/Gen/Pat.hs - compiler/GHC/Tc/Gen/Sig.hs - compiler/GHC/Tc/Gen/Splice.hs - compiler/GHC/Tc/Instance/Class.hs - compiler/GHC/Tc/Instance/FunDeps.hs - compiler/GHC/Tc/Instance/Typeable.hs - compiler/GHC/Tc/Module.hs - compiler/GHC/Tc/Plugin.hs - compiler/GHC/Tc/Solver.hs - compiler/GHC/Tc/Solver/Default.hs - compiler/GHC/Tc/Solver/Dict.hs - compiler/GHC/Tc/Solver/FunDeps.hs - compiler/GHC/Tc/Solver/InertSet.hs - compiler/GHC/Tc/Solver/Monad.hs - compiler/GHC/Tc/Solver/Rewrite.hs - compiler/GHC/Tc/TyCl.hs - compiler/GHC/Tc/TyCl/Build.hs - compiler/GHC/Tc/TyCl/Class.hs - compiler/GHC/Tc/TyCl/Instance.hs - compiler/GHC/Tc/TyCl/PatSyn.hs - compiler/GHC/Tc/TyCl/Utils.hs - compiler/GHC/Tc/Types.hs - compiler/GHC/Tc/Types/Constraint.hs - compiler/GHC/Tc/Types/Evidence.hs - compiler/GHC/Tc/Types/LclEnv.hs - compiler/GHC/Tc/Types/Origin.hs - compiler/GHC/Tc/Types/Rank.hs - compiler/GHC/Tc/Utils/Backpack.hs - compiler/GHC/Tc/Utils/Concrete.hs - compiler/GHC/Tc/Utils/Env.hs - compiler/GHC/Tc/Utils/Instantiate.hs - compiler/GHC/Tc/Utils/Monad.hs - compiler/GHC/Tc/Utils/TcMType.hs - compiler/GHC/Tc/Utils/TcType.hs - compiler/GHC/Tc/Utils/Unify.hs - compiler/GHC/Tc/Validity.hs - compiler/GHC/Tc/Zonk/Type.hs - compiler/GHC/ThToHs.hs - compiler/GHC/Types/Arity.hs - compiler/GHC/Types/Basic.hs - compiler/GHC/Types/DefaultEnv.hs - compiler/GHC/Types/Demand.hs - compiler/GHC/Types/Error.hs - compiler/GHC/Types/Error/Codes.hs - compiler/GHC/Types/FieldLabel.hs - compiler/GHC/Types/Fixity.hs - compiler/GHC/Types/ForeignCall.hs - compiler/GHC/Types/GREInfo.hs - compiler/GHC/Types/Hint.hs - compiler/GHC/Types/Hint/Ppr.hs - compiler/GHC/Types/Id/Info.hs - compiler/GHC/Types/Id/Make.hs - compiler/GHC/Types/InlinePragma.hs - compiler/GHC/Types/Literal.hs - compiler/GHC/Types/Name.hs - compiler/GHC/Types/Name/Cache.hs - compiler/GHC/Types/Name/Ppr.hs - compiler/GHC/Types/Name/Reader.hs - compiler/GHC/Types/RepType.hs - compiler/GHC/Types/Tickish.hs - compiler/GHC/Types/TyThing.hs - compiler/GHC/Types/Unique.hs - compiler/GHC/Types/Unique/DFM.hs - compiler/GHC/Types/Unique/FM.hs - + compiler/GHC/Types/UnresolvedImport.hs - compiler/GHC/Types/Var.hs - compiler/GHC/Unit.hs - compiler/GHC/Unit/Env.hs - compiler/GHC/Unit/External.hs - + compiler/GHC/Unit/External/Database.hs - + compiler/GHC/Unit/External/Index.hs - + compiler/GHC/Unit/External/ModuleOrigin.hs - + compiler/GHC/Unit/External/Providers.hs - + compiler/GHC/Unit/External/Query.hs - + compiler/GHC/Unit/External/Substitution.hs - + compiler/GHC/Unit/External/Validate.hs - + compiler/GHC/Unit/External/Visibility.hs - + compiler/GHC/Unit/External/Wired.hs - compiler/GHC/Unit/Finder.hs - compiler/GHC/Unit/Finder/Types.hs - compiler/GHC/Unit/Home/Graph.hs - compiler/GHC/Unit/Info.hs - compiler/GHC/Unit/Module/Deps.hs - compiler/GHC/Unit/Module/ModGuts.hs - compiler/GHC/Unit/Module/ModIface.hs - compiler/GHC/Unit/Module/ModSummary.hs - compiler/GHC/Unit/Module/Warnings.hs - compiler/GHC/Unit/Module/WholeCoreBindings.hs - compiler/GHC/Unit/State.hs - compiler/GHC/Unit/State.hs-boot - compiler/GHC/Unit/Types.hs - compiler/GHC/Utils/Binary.hs - − compiler/GHC/Utils/Binary/Typeable.hs - compiler/GHC/Utils/Outputable.hs - compiler/Language/Haskell/Syntax/Basic.hs - compiler/Language/Haskell/Syntax/Binds.hs - compiler/Language/Haskell/Syntax/BooleanFormula.hs - compiler/Language/Haskell/Syntax/Decls.hs - compiler/Language/Haskell/Syntax/Decls/Foreign.hs - compiler/Language/Haskell/Syntax/Doc.hs - compiler/Language/Haskell/Syntax/Expr.hs - compiler/Language/Haskell/Syntax/Extension.hs - compiler/Language/Haskell/Syntax/ImpExp.hs - compiler/Language/Haskell/Syntax/Lit.hs - compiler/Language/Haskell/Syntax/Module/Name.hs - compiler/Language/Haskell/Syntax/Specificity.hs - + compiler/Language/Haskell/Syntax/Text.hs - compiler/Language/Haskell/Syntax/Type.hs - compiler/ghc.cabal.in - configure.ac - distrib/configure.ac.in - docs/index.html.in - docs/users_guide/debugging.rst - docs/users_guide/eventlog-formats.rst - docs/users_guide/expected-undocumented-flags.txt - docs/users_guide/exts/gadt_syntax.rst - docs/users_guide/exts/qualified_strings.rst - docs/users_guide/exts/rank_polymorphism.rst - docs/users_guide/exts/static_pointers.rst - docs/users_guide/exts/strict.rst - docs/users_guide/ghc_config.py.in - docs/users_guide/separate_compilation.rst - docs/users_guide/using-optimisation.rst - docs/users_guide/using-warnings.rst - docs/users_guide/using.rst - ghc/GHC/Driver/Session/Mode.hs - ghc/GHCi/UI.hs - ghc/GHCi/UI/Monad.hs - ghc/Main.hs - hadrian/README.md - hadrian/bindist/Makefile - hadrian/cabal.project - hadrian/cfg/system.config.host.in - hadrian/cfg/system.config.target.in - hadrian/doc/cross-compile.md - hadrian/doc/flavours.md - hadrian/doc/make.md - hadrian/doc/windows.md - hadrian/hadrian.cabal - − hadrian/hie-bios - hadrian/hie-bios.bat - hadrian/src/CommandLine.hs - hadrian/src/Flavour.hs - hadrian/src/Hadrian/Builder/Ar.hs - hadrian/src/Hadrian/Utilities.hs - hadrian/src/Oracles/Flag.hs - hadrian/src/Rules.hs - hadrian/src/Rules/BinaryDist.hs - hadrian/src/Rules/CabalReinstall.hs - hadrian/src/Rules/Documentation.hs - hadrian/src/Rules/Generate.hs - hadrian/src/Rules/Library.hs - hadrian/src/Rules/Nofib.hs - hadrian/src/Rules/Program.hs - hadrian/src/Rules/Register.hs - hadrian/src/Rules/Rts.hs - hadrian/src/Rules/SourceDist.hs - hadrian/src/Rules/Test.hs - hadrian/src/Rules/ToolArgs.hs - hadrian/src/Settings.hs - − hadrian/src/Settings/Flavours/Quickest.hs - hadrian/src/Settings/Packages.hs - hie.yaml - libraries/base/base.cabal.in - libraries/base/changelog.md - libraries/base/src/Control/Applicative.hs - libraries/base/src/Control/Concurrent.hs - libraries/base/src/Control/Concurrent/Chan.hs - libraries/base/src/Control/Concurrent/QSem.hs - libraries/base/src/Control/Concurrent/QSemN.hs - libraries/base/src/Data/Array/Byte.hs - libraries/base/src/Data/Bifoldable.hs - libraries/base/src/Data/Bifoldable1.hs - libraries/base/src/Data/Bifunctor.hs - libraries/base/src/Data/Bitraversable.hs - libraries/base/src/Data/Bool.hs - libraries/base/src/Data/Complex.hs - libraries/base/src/Data/Data.hs - libraries/base/src/Data/Enum.hs - libraries/base/src/Data/Fixed.hs - libraries/base/src/Data/Foldable1.hs - libraries/base/src/Data/Functor/Classes.hs - libraries/base/src/Data/Functor/Compose.hs - libraries/base/src/Data/Functor/Contravariant.hs - libraries/base/src/Data/Functor/Product.hs - libraries/base/src/Data/Functor/Sum.hs - libraries/base/src/Data/List.hs - libraries/base/src/Data/List/NonEmpty.hs - libraries/base/src/Data/List/NubOrdSet.hs - + libraries/base/src/Data/RealFloat.hs - libraries/base/src/Data/Semigroup.hs - libraries/base/src/Data/Version.hs - libraries/base/src/GHC/Base.hs - libraries/base/src/GHC/ByteOrder.hs - libraries/base/src/GHC/Conc.hs - + libraries/base/src/GHC/Essentials.hs - libraries/base/src/GHC/Exts.hs - libraries/base/src/GHC/Fingerprint.hs - libraries/base/src/GHC/RTS/Flags.hs - libraries/base/src/GHC/ResponseFile.hs - libraries/base/src/GHC/Stack.hs - libraries/base/src/GHC/Stats.hs - libraries/base/src/GHC/Weak/Finalize.hs - libraries/base/src/Numeric.hs - libraries/base/src/Prelude.hs - libraries/base/src/System/CPUTime/Posix/ClockGetTime.hsc - libraries/base/src/System/CPUTime/Posix/RUsage.hsc - libraries/base/src/System/CPUTime/Posix/Times.hsc - libraries/base/src/System/CPUTime/Unsupported.hs - libraries/base/src/System/Console/GetOpt.hs - libraries/base/src/System/Environment.hs - libraries/base/src/System/Exit.hs - libraries/base/src/System/IO.hs - libraries/base/src/System/IO/OS.hs - libraries/base/src/System/IO/Unsafe.hs - libraries/base/src/System/Info.hs - libraries/base/src/System/Timeout.hs - libraries/base/src/Text/Printf.hs - libraries/base/src/Text/Read.hs - libraries/base/src/Text/Show/Functions.hs - libraries/base/tests/T15349.stderr - libraries/base/tests/all.T - libraries/base/tests/listThreads1.hs - libraries/base/tests/listThreads1.stdout - libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr - libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr - libraries/binary - libraries/ghc-boot/GHC/Data/ShortText.hs - libraries/ghc-experimental/src/Data/Sum/Experimental.hs - libraries/ghc-experimental/src/Data/Tuple/Experimental.hs - libraries/ghc-experimental/src/GHC/Profiling/Eras.hs - libraries/ghc-experimental/src/Prelude/Experimental.hs - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc - libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc - + libraries/ghc-heap/tests/T27465.hs - + libraries/ghc-heap/tests/T27465.stdout - libraries/ghc-heap/tests/all.T - libraries/ghc-internal/codepages/MakeTable.hs - libraries/ghc-internal/ghc-internal.cabal.in - libraries/ghc-internal/include/RtsIfaceSymbols.h - libraries/ghc-internal/src/GHC/Internal/AllocationLimitHandler.hs - libraries/ghc-internal/src/GHC/Internal/Arr.hs - libraries/ghc-internal/src/GHC/Internal/ArrayArray.hs - libraries/ghc-internal/src/GHC/Internal/Base.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/GMP.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/BigNat.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/BigNat.hs-boot - libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs-boot - libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs-boot - libraries/ghc-internal/src/GHC/Internal/Bignum/Primitives.hs - libraries/ghc-internal/src/GHC/Internal/Bignum/WordArray.hs - libraries/ghc-internal/src/GHC/Internal/Bits.hs - libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs - libraries/ghc-internal/src/GHC/Internal/CString.hs - libraries/ghc-internal/src/GHC/Internal/Char.hs - libraries/ghc-internal/src/GHC/Internal/Classes.hs - libraries/ghc-internal/src/GHC/Internal/Classes/IP.hs - libraries/ghc-internal/src/GHC/Internal/Clock.hsc - libraries/ghc-internal/src/GHC/Internal/ClosureTypes.hs - libraries/ghc-internal/src/GHC/Internal/Conc/Bound.hs - libraries/ghc-internal/src/GHC/Internal/Conc/IO.hs - libraries/ghc-internal/src/GHC/Internal/Conc/POSIX.hs - libraries/ghc-internal/src/GHC/Internal/Conc/POSIX/Const.hsc - libraries/ghc-internal/src/GHC/Internal/Conc/Signal.hs - libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs - libraries/ghc-internal/src/GHC/Internal/ConsoleHandler.hsc - libraries/ghc-internal/src/GHC/Internal/Control/Arrow.hs - libraries/ghc-internal/src/GHC/Internal/Control/Category.hs - libraries/ghc-internal/src/GHC/Internal/Control/Concurrent/MVar.hs - libraries/ghc-internal/src/GHC/Internal/Control/Exception.hs - libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fail.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fix.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/IO/Class.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Imp.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy/Imp.hs - libraries/ghc-internal/src/GHC/Internal/Control/Monad/Zip.hs - libraries/ghc-internal/src/GHC/Internal/Data/Bits.hs - libraries/ghc-internal/src/GHC/Internal/Data/Coerce.hs - libraries/ghc-internal/src/GHC/Internal/Data/Data.hs - libraries/ghc-internal/src/GHC/Internal/Data/Dynamic.hs - libraries/ghc-internal/src/GHC/Internal/Data/Either.hs - libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs - libraries/ghc-internal/src/GHC/Internal/Data/Function.hs - libraries/ghc-internal/src/GHC/Internal/Data/Functor.hs - libraries/ghc-internal/src/GHC/Internal/Data/Functor/Const.hs - libraries/ghc-internal/src/GHC/Internal/Data/Functor/Identity.hs - libraries/ghc-internal/src/GHC/Internal/Data/Functor/Utils.hs - libraries/ghc-internal/src/GHC/Internal/Data/IORef.hs - libraries/ghc-internal/src/GHC/Internal/Data/List.hs - libraries/ghc-internal/src/GHC/Internal/Data/List/NonEmpty.hs - libraries/ghc-internal/src/GHC/Internal/Data/Maybe.hs - libraries/ghc-internal/src/GHC/Internal/Data/Monoid.hs - libraries/ghc-internal/src/GHC/Internal/Data/NonEmpty.hs - libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs - libraries/ghc-internal/src/GHC/Internal/Data/Ord.hs - libraries/ghc-internal/src/GHC/Internal/Data/Proxy.hs - libraries/ghc-internal/src/GHC/Internal/Data/STRef.hs - libraries/ghc-internal/src/GHC/Internal/Data/Semigroup/Internal.hs - libraries/ghc-internal/src/GHC/Internal/Data/String.hs - libraries/ghc-internal/src/GHC/Internal/Data/Traversable.hs - libraries/ghc-internal/src/GHC/Internal/Data/Tuple.hs - libraries/ghc-internal/src/GHC/Internal/Data/Type/Bool.hs - libraries/ghc-internal/src/GHC/Internal/Data/Type/Coercion.hs - libraries/ghc-internal/src/GHC/Internal/Data/Type/Equality.hs - libraries/ghc-internal/src/GHC/Internal/Data/Type/Ord.hs - libraries/ghc-internal/src/GHC/Internal/Data/Typeable.hs - libraries/ghc-internal/src/GHC/Internal/Data/Typeable/Internal.hs - libraries/ghc-internal/src/GHC/Internal/Data/Unique.hs - libraries/ghc-internal/src/GHC/Internal/Data/Version.hs - libraries/ghc-internal/src/GHC/Internal/Data/Void.hs - libraries/ghc-internal/src/GHC/Internal/Debug/Trace.hs - libraries/ghc-internal/src/GHC/Internal/Desugar.hs - libraries/ghc-internal/src/GHC/Internal/Encoding/UTF8.hs - libraries/ghc-internal/src/GHC/Internal/Enum.hs - libraries/ghc-internal/src/GHC/Internal/Enum.hs-boot - libraries/ghc-internal/src/GHC/Internal/Environment.hs - libraries/ghc-internal/src/GHC/Internal/Err.hs - libraries/ghc-internal/src/GHC/Internal/Event/Arr.hs - libraries/ghc-internal/src/GHC/Internal/Event/Array.hs - libraries/ghc-internal/src/GHC/Internal/Event/Control.hs - libraries/ghc-internal/src/GHC/Internal/Event/EPoll.hsc - libraries/ghc-internal/src/GHC/Internal/Event/IntTable.hs - libraries/ghc-internal/src/GHC/Internal/Event/IntVar.hs - libraries/ghc-internal/src/GHC/Internal/Event/Internal.hs - libraries/ghc-internal/src/GHC/Internal/Event/Internal/Types.hs - libraries/ghc-internal/src/GHC/Internal/Event/KQueue.hsc - libraries/ghc-internal/src/GHC/Internal/Event/Manager.hs - libraries/ghc-internal/src/GHC/Internal/Event/PSQ.hs - libraries/ghc-internal/src/GHC/Internal/Event/Poll.hsc - libraries/ghc-internal/src/GHC/Internal/Event/Thread.hs - libraries/ghc-internal/src/GHC/Internal/Event/TimeOut.hs - libraries/ghc-internal/src/GHC/Internal/Event/TimerManager.hs - libraries/ghc-internal/src/GHC/Internal/Event/Unique.hs - libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc - libraries/ghc-internal/src/GHC/Internal/Event/Windows/Clock.hs - libraries/ghc-internal/src/GHC/Internal/Event/Windows/ConsoleEvent.hsc - libraries/ghc-internal/src/GHC/Internal/Event/Windows/FFI.hsc - libraries/ghc-internal/src/GHC/Internal/Event/Windows/ManagedThreadPool.hs - libraries/ghc-internal/src/GHC/Internal/Event/Windows/Thread.hs - libraries/ghc-internal/src/GHC/Internal/Exception.hs - libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs - libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs-boot - libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs - libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs-boot - libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs - libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs-boot - libraries/ghc-internal/src/GHC/Internal/ExecutionStack.hs - libraries/ghc-internal/src/GHC/Internal/ExecutionStack/Internal.hsc - libraries/ghc-internal/src/GHC/Internal/Exts.hs - libraries/ghc-internal/src/GHC/Internal/Fingerprint.hs - libraries/ghc-internal/src/GHC/Internal/Fingerprint/Type.hs - libraries/ghc-internal/src/GHC/Internal/Float.hs - libraries/ghc-internal/src/GHC/Internal/Float/ConversionUtils.hs - libraries/ghc-internal/src/GHC/Internal/Float/RealFracMethods.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/C/ConstPtr.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/C/Error.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/C/String.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/C/String/Encoding.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/C/Types.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/ForeignPtr/Imp.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Alloc.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Array.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Error.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Pool.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Utils.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Ptr.hs - libraries/ghc-internal/src/GHC/Internal/Foreign/Storable.hs - libraries/ghc-internal/src/GHC/Internal/ForeignPtr.hs - libraries/ghc-internal/src/GHC/Internal/ForeignSrcLang.hs - libraries/ghc-internal/src/GHC/Internal/Functor/ZipList.hs - libraries/ghc-internal/src/GHC/Internal/GHCi.hs - libraries/ghc-internal/src/GHC/Internal/GHCi/Helpers.hs - libraries/ghc-internal/src/GHC/Internal/Generics.hs - libraries/ghc-internal/src/GHC/Internal/Heap/Closures.hs - libraries/ghc-internal/src/GHC/Internal/Heap/Constants.hsc - libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable.hsc - libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable/Types.hsc - libraries/ghc-internal/src/GHC/Internal/Heap/InfoTableProf.hsc - libraries/ghc-internal/src/GHC/Internal/Heap/ProfInfo/Types.hs - libraries/ghc-internal/src/GHC/Internal/IO.hs - libraries/ghc-internal/src/GHC/Internal/IO.hs-boot - libraries/ghc-internal/src/GHC/Internal/IO/Buffer.hs - libraries/ghc-internal/src/GHC/Internal/IO/BufferedIO.hs - libraries/ghc-internal/src/GHC/Internal/IO/Device.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage/API.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage/Table.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Failure.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Iconv.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Latin1.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Types.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF16.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF32.hs - libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF8.hs - libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs - libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs-boot - libraries/ghc-internal/src/GHC/Internal/IO/FD.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/FD.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Internals.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Common.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Flock.hsc - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/LinuxOFD.hsc - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/NoOp.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Windows.hsc - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs-boot - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Windows.hs - libraries/ghc-internal/src/GHC/Internal/IO/IOMode.hs - libraries/ghc-internal/src/GHC/Internal/IO/SubSystem.hs - libraries/ghc-internal/src/GHC/Internal/IO/Unsafe.hs - libraries/ghc-internal/src/GHC/Internal/IO/Windows/Encoding.hs - libraries/ghc-internal/src/GHC/Internal/IO/Windows/Handle.hsc - libraries/ghc-internal/src/GHC/Internal/IOArray.hs - libraries/ghc-internal/src/GHC/Internal/IORef.hs - libraries/ghc-internal/src/GHC/Internal/InfoProv.hs - libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc - libraries/ghc-internal/src/GHC/Internal/Int.hs - libraries/ghc-internal/src/GHC/Internal/IsList.hs - libraries/ghc-internal/src/GHC/Internal/Ix.hs - libraries/ghc-internal/src/GHC/Internal/JS/Foreign/Callback.hs - libraries/ghc-internal/src/GHC/Internal/JS/Prim.hs - libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs - libraries/ghc-internal/src/GHC/Internal/Lexeme.hs - libraries/ghc-internal/src/GHC/Internal/List.hs - libraries/ghc-internal/src/GHC/Internal/MVar.hs - libraries/ghc-internal/src/GHC/Internal/Magic.hs - libraries/ghc-internal/src/GHC/Internal/Magic/Dict.hs - libraries/ghc-internal/src/GHC/Internal/Maybe.hs - libraries/ghc-internal/src/GHC/Internal/Num.hs - libraries/ghc-internal/src/GHC/Internal/Num.hs-boot - libraries/ghc-internal/src/GHC/Internal/Numeric.hs - libraries/ghc-internal/src/GHC/Internal/OverloadedLabels.hs - libraries/ghc-internal/src/GHC/Internal/Pack.hs - libraries/ghc-internal/src/GHC/Internal/Prim/Exception.hs - libraries/ghc-internal/src/GHC/Internal/Prim/Ext.hs - libraries/ghc-internal/src/GHC/Internal/Prim/Panic.hs - libraries/ghc-internal/src/GHC/Internal/Prim/PtrEq.hs - libraries/ghc-internal/src/GHC/Internal/Profiling.hs - libraries/ghc-internal/src/GHC/Internal/Ptr.hs - libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc - libraries/ghc-internal/src/GHC/Internal/RTS/Flags/Test.hsc - libraries/ghc-internal/src/GHC/Internal/Read.hs - libraries/ghc-internal/src/GHC/Internal/Real.hs - libraries/ghc-internal/src/GHC/Internal/Real.hs-boot - libraries/ghc-internal/src/GHC/Internal/Records.hs - libraries/ghc-internal/src/GHC/Internal/ST.hs - libraries/ghc-internal/src/GHC/Internal/STM.hs - libraries/ghc-internal/src/GHC/Internal/STRef.hs - libraries/ghc-internal/src/GHC/Internal/Show.hs - libraries/ghc-internal/src/GHC/Internal/Stable.hs - libraries/ghc-internal/src/GHC/Internal/StableName.hs - libraries/ghc-internal/src/GHC/Internal/Stack.hs - libraries/ghc-internal/src/GHC/Internal/Stack.hs-boot - libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs - libraries/ghc-internal/src/GHC/Internal/Stack/CCS.hsc - libraries/ghc-internal/src/GHC/Internal/Stack/CloneStack.hs - libraries/ghc-internal/src/GHC/Internal/Stack/Constants.hsc - libraries/ghc-internal/src/GHC/Internal/Stack/ConstantsProf.hsc - libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs - libraries/ghc-internal/src/GHC/Internal/Stack/Types.hs - libraries/ghc-internal/src/GHC/Internal/StaticPtr.hs - libraries/ghc-internal/src/GHC/Internal/StaticPtr/Internal.hs - libraries/ghc-internal/src/GHC/Internal/Stats.hsc - libraries/ghc-internal/src/GHC/Internal/Storable.hs - libraries/ghc-internal/src/GHC/Internal/System/Environment.hs - libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc - libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc - libraries/ghc-internal/src/GHC/Internal/System/IO/Error.hs - libraries/ghc-internal/src/GHC/Internal/System/Mem.hs - libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs - libraries/ghc-internal/src/GHC/Internal/System/Posix/Types.hs - libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs - libraries/ghc-internal/src/GHC/Internal/TH/Lift.hs - libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs - libraries/ghc-internal/src/GHC/Internal/TH/Syntax.hs - libraries/ghc-internal/src/GHC/Internal/Text/ParserCombinators/ReadP.hs - libraries/ghc-internal/src/GHC/Internal/Text/ParserCombinators/ReadPrec.hs - libraries/ghc-internal/src/GHC/Internal/Text/Read/Lex.hs - libraries/ghc-internal/src/GHC/Internal/TopHandler.hs - libraries/ghc-internal/src/GHC/Internal/Tuple.hs - libraries/ghc-internal/src/GHC/Internal/Type/Reflection.hs - libraries/ghc-internal/src/GHC/Internal/Type/Reflection/Unsafe.hs - libraries/ghc-internal/src/GHC/Internal/TypeError.hs - libraries/ghc-internal/src/GHC/Internal/TypeLits.hs - libraries/ghc-internal/src/GHC/Internal/TypeLits/Internal.hs - libraries/ghc-internal/src/GHC/Internal/TypeNats.hs - libraries/ghc-internal/src/GHC/Internal/TypeNats/Internal.hs - libraries/ghc-internal/src/GHC/Internal/Types.hs - libraries/ghc-internal/src/GHC/Internal/Unicode.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Bits.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Char/DerivedCoreProperties.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/GeneralCategory.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleLowerCaseMapping.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleTitleCaseMapping.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleUpperCaseMapping.hs - libraries/ghc-internal/src/GHC/Internal/Unicode/Version.hs - libraries/ghc-internal/src/GHC/Internal/Unsafe/Coerce.hs - libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Conc.hs - libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Conc/Internal.hs - libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Exports.hs - libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Imports.hs - libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs - libraries/ghc-internal/src/GHC/Internal/Weak.hs - libraries/ghc-internal/src/GHC/Internal/Weak/Finalize.hs - libraries/ghc-internal/src/GHC/Internal/Windows.hs - libraries/ghc-internal/src/GHC/Internal/Word.hs - libraries/ghc-internal/tests/backtraces/T14532b.stdout - libraries/ghc-internal/tools/ucd2haskell/exe/UCD2Haskell/ModuleGenerators.hs - libraries/ghc-prim/Dummy.hs - libraries/ghc-prim/ghc-prim.cabal - libraries/stm - libraries/template-haskell/Language/Haskell/TH/Lib.hs - linters/lint-codes/LintCodes/Static.hs - m4/fp_check_pthreads.m4 - nofib - rts/Apply.cmm - rts/Capability.c - rts/Capability.h - rts/CloneStack.c - rts/ContinuationOps.cmm - rts/IOManager.c - rts/IOManager.h - rts/IOManagerInternals.h - rts/Interpreter.c - rts/LdvProfile.c - rts/ZeroSlop.c → rts/MarkSlop.c - rts/Messages.c - rts/PrimOps.cmm - rts/Printer.c - rts/ProfHeap.c - rts/Profiling.c - rts/RaiseAsync.c - rts/RaiseAsync.h - rts/RtsFlags.c - rts/RtsStartup.c - rts/RtsSymbols.c - rts/STM.c - rts/Schedule.c - rts/Schedule.h - rts/StgMiscClosures.cmm - rts/ThreadPaused.c - rts/Threads.c - rts/Threads.h - rts/Trace.c - rts/Trace.h - rts/TraverseHeap.c - rts/eventlog/EventLog.c - rts/eventlog/EventLog.h - rts/include/Cmm.h - rts/include/rts/Constants.h - rts/include/rts/EventLogFormat.h - rts/include/rts/IOInterface.h - rts/include/rts/RtsToHsIface.h - rts/include/rts/storage/ClosureMacros.h - rts/include/rts/storage/Closures.h - rts/include/rts/storage/TSO.h - rts/include/stg/MiscClosures.h - rts/js/thread.js - rts/linker/elf_reloc_riscv64.c - rts/posix/FdWakeup.h - + rts/posix/MIO.c - + rts/posix/MIO.h - rts/posix/Poll.c - rts/posix/Poll.h - rts/posix/Select.c - rts/posix/Select.h - rts/posix/Signals.c - rts/posix/Signals.h - rts/posix/Timeout.c - rts/posix/Timeout.h - rts/prim/atomic.c - rts/rts.cabal - rts/sm/Compact.c - rts/sm/NonMovingMark.c - rts/sm/Sanity.c - rts/sm/Scav.c - rts/sm/Storage.c - rts/win32/AsyncMIO.c - rts/win32/AsyncMIO.h - rts/win32/AsyncWinIO.h - rts/win32/AwaitEvent.c - rts/win32/AwaitEvent.h - rts/win32/ConsoleHandler.h - rts/win32/MIOManager.h - rts/win32/ThrIOManager.h - rts/win32/WorkQueue.h - rts/win32/veh_excn.h - testsuite/.gitignore - testsuite/Makefile - testsuite/driver/README.md - testsuite/driver/junit.py - testsuite/driver/perf_notes.py - testsuite/driver/runtests.py - testsuite/driver/term_color.py - testsuite/driver/testglobals.py - testsuite/driver/testlib.py - testsuite/driver/testutil.py - testsuite/tests/ado/T13242a.stderr - testsuite/tests/annotations/should_fail/annfail10.stderr - testsuite/tests/backpack/cabal/bkpcabal07/Makefile - testsuite/tests/backpack/should_compile/T13149.bkp - testsuite/tests/backpack/should_compile/T20396.stderr - testsuite/tests/backpack/should_fail/bkpfail17.stderr - testsuite/tests/bytecode/TLinkable/all.T - testsuite/tests/cabal/T12485/Makefile - + testsuite/tests/cabal/T27013a/Makefile - + testsuite/tests/cabal/T27013a/Setup.hs - + testsuite/tests/cabal/T27013a/all.T - + testsuite/tests/cabal/T27013a/composition.cabal - + testsuite/tests/cabal/T27013a/src/Data/Composition.hs - + testsuite/tests/cabal/T27013d/Composition.hs - + testsuite/tests/cabal/T27013d/Makefile - + testsuite/tests/cabal/T27013d/T27013d.stdout - + testsuite/tests/cabal/T27013d/all.T - testsuite/tests/callarity/unittest/CallArity1.hs - + testsuite/tests/cmm/should_compile/T27368-ppr-debug.cmm - + testsuite/tests/cmm/should_compile/T27368-ppr-debug.stderr - testsuite/tests/cmm/should_compile/all.T - testsuite/tests/cmm/should_run/AtomicFetch.hs - testsuite/tests/cmm/should_run/AtomicFetch_cmm.cmm - testsuite/tests/codeGen/should_compile/T25177.stderr - + testsuite/tests/codeGen/should_gen_asm/T24813.asm - + testsuite/tests/codeGen/should_gen_asm/T24813.cmm - + testsuite/tests/codeGen/should_gen_asm/T25233.asm - + testsuite/tests/codeGen/should_gen_asm/T25233.hs - + testsuite/tests/codeGen/should_gen_asm/T25233b.asm - + testsuite/tests/codeGen/should_gen_asm/T25233b.cmm - testsuite/tests/codeGen/should_gen_asm/all.T - + testsuite/tests/codeGen/should_run/T27430.hs - + testsuite/tests/codeGen/should_run/T27430.stdout - + testsuite/tests/codeGen/should_run/T27430_c.c - + testsuite/tests/codeGen/should_run/T27533.hs - + testsuite/tests/codeGen/should_run/T27533.stdout - + testsuite/tests/codeGen/should_run/T27533_cmm.cmm - + testsuite/tests/codeGen/should_run/T27537.hs - + testsuite/tests/codeGen/should_run/T27537.stdout - + testsuite/tests/codeGen/should_run/T27538.hs - + testsuite/tests/codeGen/should_run/T27538.stdout - testsuite/tests/codeGen/should_run/all.T - testsuite/tests/codeGen/should_run/cgrun025.stderr - + testsuite/tests/concurrent/should_run/T16761.hs - + testsuite/tests/concurrent/should_run/T16761.stdout - testsuite/tests/concurrent/should_run/T27105.hs - + testsuite/tests/concurrent/should_run/T27657a.hs - + testsuite/tests/concurrent/should_run/T27657a.stdout - + testsuite/tests/concurrent/should_run/T27657b.hs - + testsuite/tests/concurrent/should_run/T27657b.stdout - testsuite/tests/concurrent/should_run/all.T - + testsuite/tests/core-to-stg/T25924/B.hs - + testsuite/tests/core-to-stg/T25924/Main.hs - + testsuite/tests/core-to-stg/T25924/all.T - + testsuite/tests/core-to-stg/T25924a.hs - + testsuite/tests/core-to-stg/T25924a.stdout - + testsuite/tests/core-to-stg/T27627/Callee.hs - + testsuite/tests/core-to-stg/T27627/Caller.hs - + testsuite/tests/core-to-stg/T27627/Main.hs - + testsuite/tests/core-to-stg/T27627/T27627.stdout - + testsuite/tests/core-to-stg/T27627/all.T - + testsuite/tests/core-to-stg/T27627a/Callee.hs - + testsuite/tests/core-to-stg/T27627a/Caller.hs - + testsuite/tests/core-to-stg/T27627a/Main.hs - + testsuite/tests/core-to-stg/T27627a/T27627a.stdout - + testsuite/tests/core-to-stg/T27627a/all.T - + testsuite/tests/core-to-stg/T27627b/Callee.hs - + testsuite/tests/core-to-stg/T27627b/Caller.hs - + testsuite/tests/core-to-stg/T27627b/Main.hs - + testsuite/tests/core-to-stg/T27627b/T27627b.stdout - + testsuite/tests/core-to-stg/T27627b/all.T - + testsuite/tests/core-to-stg/T27627c/Callee.hs - + testsuite/tests/core-to-stg/T27627c/Caller.hs - + testsuite/tests/core-to-stg/T27627c/Main.hs - + testsuite/tests/core-to-stg/T27627c/T27627c.stdout - + testsuite/tests/core-to-stg/T27627c/all.T - + testsuite/tests/core-to-stg/T27627e.hs - + testsuite/tests/core-to-stg/T27627e.stdout - + testsuite/tests/core-to-stg/T27627f/Callee.hs - + testsuite/tests/core-to-stg/T27627f/Caller.hs - + testsuite/tests/core-to-stg/T27627f/Inst.hs - + testsuite/tests/core-to-stg/T27627f/Main.hs - + testsuite/tests/core-to-stg/T27627f/T27627f.stdout - + testsuite/tests/core-to-stg/T27627f/all.T - + testsuite/tests/core-to-stg/T27704/Callee.hs - + testsuite/tests/core-to-stg/T27704/Callee.hs-boot - + testsuite/tests/core-to-stg/T27704/Main.hs - + testsuite/tests/core-to-stg/T27704/Mid.hs - + testsuite/tests/core-to-stg/T27704/T27704.stdout - + testsuite/tests/core-to-stg/T27704/all.T - + testsuite/tests/core-to-stg/T27704a/Callee.hs - + testsuite/tests/core-to-stg/T27704a/Callee.hs-boot - + testsuite/tests/core-to-stg/T27704a/Main.hs - + testsuite/tests/core-to-stg/T27704a/Mid.hs - + testsuite/tests/core-to-stg/T27704a/T27704a.stdout - + testsuite/tests/core-to-stg/T27704a/all.T - + testsuite/tests/core-to-stg/T27717/Callee.hs - + testsuite/tests/core-to-stg/T27717/Callee.hs-boot - + testsuite/tests/core-to-stg/T27717/Main.hs - + testsuite/tests/core-to-stg/T27717/Mid.hs - + testsuite/tests/core-to-stg/T27717/T27717.stdout - + testsuite/tests/core-to-stg/T27717/Ty.hs - + testsuite/tests/core-to-stg/T27717/all.T - testsuite/tests/core-to-stg/all.T - testsuite/tests/corelint/LintEtaExpand.hs - testsuite/tests/corelint/T21115b.stderr - + testsuite/tests/corelint/T27374.hs - testsuite/tests/corelint/all.T - testsuite/tests/count-deps/CountDepsAst.stdout - testsuite/tests/count-deps/CountDepsParser.stdout - testsuite/tests/deSugar/should_compile/T13208.stdout - testsuite/tests/deSugar/should_compile/T16615.stderr - testsuite/tests/deSugar/should_compile/T2431.stderr - testsuite/tests/deSugar/should_fail/all.T - + testsuite/tests/deSugar/should_run/LazyFieldAnnotationsSemantics.hs - + testsuite/tests/deSugar/should_run/LazyFieldAnnotationsSemantics.stdout - testsuite/tests/deSugar/should_run/all.T - testsuite/tests/default/DefaultImportFail01.stderr - testsuite/tests/default/DefaultImportFail02.stderr - testsuite/tests/default/DefaultImportFail03.stderr - testsuite/tests/default/DefaultImportFail04.stderr - testsuite/tests/default/DefaultImportFail05.stderr - testsuite/tests/default/DefaultImportFail07.stderr - testsuite/tests/default/T25775.stderr - testsuite/tests/deriving/should_compile/T14682.stderr - testsuite/tests/deriving/should_compile/T20496.stderr - testsuite/tests/determinism/determ017/A.hs - testsuite/tests/diagnostic-codes/codes.stdout - testsuite/tests/dmdanal/should_compile/T18982.stderr - testsuite/tests/dmdanal/should_compile/T23398.stderr - + testsuite/tests/dmdanal/should_run/M2.hs - + testsuite/tests/dmdanal/should_run/T27626.hs - + testsuite/tests/dmdanal/should_run/T27626.stdout - testsuite/tests/dmdanal/should_run/all.T - + testsuite/tests/driver/T26423/Hello.hs - + testsuite/tests/driver/T26423/Makefile - + testsuite/tests/driver/T26423/T26423.hs - + testsuite/tests/driver/T26423/T26423.stderr - + testsuite/tests/driver/T26423/T26423.stdout - + testsuite/tests/driver/T26423/all.T - + testsuite/tests/driver/T26423/test/Test.hs - + testsuite/tests/driver/T26423/test/test.pkg - + testsuite/tests/driver/T27013b/Makefile - + testsuite/tests/driver/T27013b/T27013b.stdout - + testsuite/tests/driver/T27013b/X.hs - + testsuite/tests/driver/T27013b/all.T - + testsuite/tests/driver/T27013c/Makefile - + testsuite/tests/driver/T27013c/T27013c.stdout - + testsuite/tests/driver/T27013c/X.hs - + testsuite/tests/driver/T27013c/all.T - + testsuite/tests/driver/T27013e/T27013e.hs - + testsuite/tests/driver/T27013e/T27013e.stderr - + testsuite/tests/driver/T27013e/all.T - + testsuite/tests/driver/T27013f/T27013f.hs - + testsuite/tests/driver/T27013f/T27013f.stderr - + testsuite/tests/driver/T27013f/all.T - + testsuite/tests/driver/T27013g/T27013g.hs - + testsuite/tests/driver/T27013g/all.T - + testsuite/tests/driver/T27013h/GHC/Essentials.hs - + testsuite/tests/driver/T27013h/T27013h.stderr - + testsuite/tests/driver/T27013h/all.T - + testsuite/tests/driver/T27013h/unitT27013h - + testsuite/tests/driver/T27013i/T27013i.hs - + testsuite/tests/driver/T27013i/T27013i.stderr - + testsuite/tests/driver/T27013i/all.T - + testsuite/tests/driver/T27461/Main1.hs - + testsuite/tests/driver/T27461/Main2.hs - + testsuite/tests/driver/T27461/Makefile - + testsuite/tests/driver/T27461/T27461a.stderr - + testsuite/tests/driver/T27461/T27461b.script - + testsuite/tests/driver/T27461/T27461b.stderr - + testsuite/tests/driver/T27461/T27461b.stdout - + testsuite/tests/driver/T27461/all.T - + testsuite/tests/driver/T27461/src/Bar.hs - testsuite/tests/driver/T3007/A/Internal.hs - testsuite/tests/driver/T3007/Makefile - testsuite/tests/driver/T4437.hs - + testsuite/tests/driver/TUnitInfo/Foo.hs - + testsuite/tests/driver/TUnitInfo/Makefile - + testsuite/tests/driver/TUnitInfo/all.T - + testsuite/tests/driver/TUnitInfo/genMhu.sh - + testsuite/tests/driver/TUnitInfo/generic-unit-info-space-mhu.stdout - + testsuite/tests/driver/TUnitInfo/generic-unit-info-space-single.stdout - + testsuite/tests/driver/TUnitInfo/generic-unit-info-space.hs - + testsuite/tests/driver/TUnitInfo/generic-unit-info-space.stdout - testsuite/tests/driver/all.T - testsuite/tests/driver/make-prim/Makefile - testsuite/tests/driver/mostly-static/Makefile - testsuite/tests/driver/multipleHomeUnits/Makefile - testsuite/tests/driver/multipleHomeUnits/all.T - + testsuite/tests/driver/multipleHomeUnits/essentials-home/GHC/Essentials.hs - + testsuite/tests/driver/multipleHomeUnits/essentials-order-base/B.hs - + testsuite/tests/driver/multipleHomeUnits/essentials-order-user/U.hs - + testsuite/tests/driver/multipleHomeUnits/essentials-user/M.hs - testsuite/tests/driver/multipleHomeUnits/multipleHomeUnitsModuleVisibility.stderr - + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials.stdout - + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials_order.stderr - + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials_recomp.stdout - + testsuite/tests/driver/multipleHomeUnits/unitEssentialsHome - + testsuite/tests/driver/multipleHomeUnits/unitEssentialsHomeHidden - + testsuite/tests/driver/multipleHomeUnits/unitEssentialsOrderBase - + testsuite/tests/driver/multipleHomeUnits/unitEssentialsOrderUser - + testsuite/tests/driver/multipleHomeUnits/unitEssentialsUser - + testsuite/tests/driver/multipleHomeUnits/unitEssentialsUserHidden - testsuite/tests/driver/recomp24656/Makefile - testsuite/tests/driver/recomp24656/recomp24656.stdout - testsuite/tests/exceptions/T26759.stderr - testsuite/tests/ffi/should_fail/all.T - + testsuite/tests/ffi/should_fail/ccfail006.hs - + testsuite/tests/ffi/should_fail/ccfail006.stderr - + testsuite/tests/ffi/should_fail/ccfail007.hs - + testsuite/tests/ffi/should_fail/ccfail007.stderr - + testsuite/tests/ffi/should_fail/ccfail008.hs - + testsuite/tests/ffi/should_fail/ccfail008.stderr - + testsuite/tests/ffi/should_fail/ccfail009.hs - + testsuite/tests/ffi/should_fail/ccfail009.stderr - testsuite/tests/ffi/should_run/T21305.hs - − testsuite/tests/gadt/T14320.stderr - testsuite/tests/gadt/T18191.hs - testsuite/tests/gadt/T18191.stderr - + testsuite/tests/gadt/T27423a.hs - + testsuite/tests/gadt/T27423b.hs - + testsuite/tests/gadt/T27423b.stderr - testsuite/tests/gadt/all.T - + testsuite/tests/ghc-api/EssentialsCoverage.hs - testsuite/tests/ghc-api/T25121_status.stdout - testsuite/tests/ghc-api/T8628.hs - testsuite/tests/ghc-api/all.T - testsuite/tests/ghc-api/annotations-literals/parsed.hs - testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs - testsuite/tests/ghc-api/exactprint/T22919.stderr - testsuite/tests/ghc-api/exactprint/Test20239.stderr - testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr - testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs - testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs - testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs - testsuite/tests/ghc-e/should_fail/T18441fail7.stderr - testsuite/tests/ghc-e/should_run/ghc-e005.stderr - testsuite/tests/ghci.debugger/scripts/break006.stderr - testsuite/tests/ghci.debugger/scripts/print019.stderr - testsuite/tests/ghci/T13786/all.T - testsuite/tests/ghci/T16793/T16793.stdout - testsuite/tests/ghci/T18060/T18060.stdout - + testsuite/tests/ghci/T27532/Makefile - + testsuite/tests/ghci/T27532/T27532.stdout - + testsuite/tests/ghci/T27532/T27532j4.stdout - + testsuite/tests/ghci/T27532/a.script - + testsuite/tests/ghci/T27532/all.T - + testsuite/tests/ghci/T27532/b.script - + testsuite/tests/ghci/T27532/genT27532Modules - testsuite/tests/ghci/linking/all.T - testsuite/tests/ghci/linking/dyn/all.T - + testsuite/tests/ghci/prog-mhu007/Makefile - + testsuite/tests/ghci/prog-mhu007/a/A.hs - + testsuite/tests/ghci/prog-mhu007/all.T - + testsuite/tests/ghci/prog-mhu007/b/B.hs - + testsuite/tests/ghci/prog-mhu007/prog-mhu007.script - + testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout - + testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs - + testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg - + testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs - + testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg - + testsuite/tests/ghci/prog-mhu007/unitA - + testsuite/tests/ghci/prog-mhu007/unitB - testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout - testsuite/tests/ghci/scripts/T12005.script - testsuite/tests/ghci/scripts/T4175.stdout - testsuite/tests/ghci/scripts/T8469.stdout - testsuite/tests/ghci/scripts/T8535.stdout - testsuite/tests/ghci/scripts/T9881.stdout - testsuite/tests/ghci/scripts/all.T - + testsuite/tests/ghci/scripts/bytecodeIPE.hs - + testsuite/tests/ghci/scripts/bytecodeIPE.script - + testsuite/tests/ghci/scripts/bytecodeIPE.stdout - testsuite/tests/ghci/scripts/ghci020.stdout - testsuite/tests/ghci/scripts/ghci064.stdout - testsuite/tests/ghci/should_run/Makefile - testsuite/tests/ghci/should_run/T10145.stdout - testsuite/tests/ghci/should_run/T18594.stdout - + testsuite/tests/ghci/should_run/T27287.hs - + testsuite/tests/ghci/should_run/T27287.stdout - testsuite/tests/ghci/should_run/all.T - testsuite/tests/haddock/haddock_examples/haddock.Test.stderr - testsuite/tests/haddock/perf/Fold.hs - testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr - testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr - testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr - testsuite/tests/hiefile/should_compile/T24493.stderr - testsuite/tests/hiefile/should_run/T23120.stdout - + testsuite/tests/hiefile/should_run/T25709.hs - + testsuite/tests/hiefile/should_run/T25709.stdout - testsuite/tests/hiefile/should_run/all.T - testsuite/tests/iface/IfaceSharingIfaceType.hs - testsuite/tests/iface/IfaceSharingName.hs - testsuite/tests/indexed-types/should_fail/T12522a.stderr - testsuite/tests/indexed-types/should_fail/T7354.hs - testsuite/tests/interface-stability/base-exports.stdout - testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs - testsuite/tests/interface-stability/base-exports.stdout-mingw32 - testsuite/tests/interface-stability/ghc-experimental-exports.stdout - testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32 - testsuite/tests/interface-stability/ghc-prim-exports.stdout - testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32 - testsuite/tests/interface-stability/template-haskell-exports.stdout - testsuite/tests/javascript/Makefile - testsuite/tests/javascript/T24495.hs - testsuite/tests/layout/layout001.stdout - testsuite/tests/layout/layout002.stdout - testsuite/tests/layout/layout003.stdout - testsuite/tests/layout/layout004.stdout - testsuite/tests/layout/layout005.stdout - testsuite/tests/layout/layout006.stdout - testsuite/tests/layout/layout007.stdout - testsuite/tests/layout/layout008.stdout - testsuite/tests/layout/layout009.stdout - testsuite/tests/linear/should_compile/T1735Min.hs - testsuite/tests/mdo/should_fail/mdofail006.stderr - + testsuite/tests/module/T27380.hs - + testsuite/tests/module/T27380.stderr - testsuite/tests/module/all.T - testsuite/tests/module/mod184.stderr - testsuite/tests/module/mod185.stderr - testsuite/tests/numeric/should_compile/T14170.stdout - testsuite/tests/numeric/should_compile/T14465.stdout - testsuite/tests/numeric/should_compile/T15547.stderr - testsuite/tests/numeric/should_compile/T23907.stderr - testsuite/tests/numeric/should_compile/T7116.stdout - testsuite/tests/overloadedlists/should_fail/overloadedlistsfail01.stderr - testsuite/tests/package/T20010/all.T - testsuite/tests/package/all.T - testsuite/tests/parser/should_compile/DumpParsedAst.stderr - testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr - testsuite/tests/parser/should_compile/DumpRenamedAst.stderr - testsuite/tests/parser/should_compile/DumpSemis.stderr - testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr - testsuite/tests/parser/should_compile/KindSigs.stderr - + testsuite/tests/parser/should_compile/T13087.stderr - testsuite/tests/parser/should_compile/T14189.stderr - testsuite/tests/parser/should_compile/T15279.stderr - testsuite/tests/parser/should_compile/T15323.stderr - testsuite/tests/parser/should_compile/T20452.stderr - testsuite/tests/parser/should_compile/T20718.stderr - testsuite/tests/parser/should_compile/T20718b.stderr - testsuite/tests/parser/should_compile/T20846.stderr - testsuite/tests/parser/should_compile/T23315/T23315.stderr - testsuite/tests/parser/should_fail/RecordDotSyntaxFail10.stderr - testsuite/tests/parser/should_fail/RecordDotSyntaxFail11.stderr - testsuite/tests/parser/should_fail/RecordDotSyntaxFail13.stderr - testsuite/tests/parser/should_fail/RecordDotSyntaxFail8.stderr - testsuite/tests/parser/should_fail/T16270h.hs - testsuite/tests/parser/should_fail/T8431.stderr - testsuite/tests/parser/should_fail/readFail038.stderr - + testsuite/tests/parser/should_run/StringStartsWithNull.hs - + testsuite/tests/parser/should_run/StringStartsWithNull.stdout - testsuite/tests/parser/should_run/all.T - testsuite/tests/partial-sigs/should_compile/ExtraConstraints3.stderr - testsuite/tests/partial-sigs/should_fail/NamedWildcardsNotInMonotype.stderr - + testsuite/tests/patsyn/should_compile/T27440a.hs - + testsuite/tests/patsyn/should_compile/T27440b.hs - + testsuite/tests/patsyn/should_compile/T27440c.hs - + testsuite/tests/patsyn/should_compile/T27744.hs - testsuite/tests/patsyn/should_compile/all.T - testsuite/tests/patsyn/should_fail/T26465.stderr - + testsuite/tests/patsyn/should_fail/T27440d.hs - + testsuite/tests/patsyn/should_fail/T27440d.stderr - testsuite/tests/patsyn/should_fail/all.T - + testsuite/tests/perf/compiler/FamAppCachePerf.hs - + testsuite/tests/perf/compiler/SimplCastPerf.hs - + testsuite/tests/perf/compiler/T27336.hs - testsuite/tests/perf/compiler/T3064.hs - testsuite/tests/perf/compiler/all.T - testsuite/tests/perf/compiler/hard_hole_fits.stderr - testsuite/tests/perf/compiler/large-project/all.T - testsuite/tests/perf/should_run/ByteCodeAsm.hs - testsuite/tests/perf/should_run/T3586.hs - testsuite/tests/perf/should_run/T3586.stdout - testsuite/tests/perf/space_leaks/all.T - testsuite/tests/plugins/all.T - testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs - testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs - testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs - testsuite/tests/plugins/plugins09.stdout - testsuite/tests/plugins/plugins10.stdout - testsuite/tests/plugins/plugins11.stdout - testsuite/tests/plugins/simple-plugin/Simple/ReplacePlugin.hs - testsuite/tests/plugins/static-plugins.stdout - + testsuite/tests/pmcheck/should_compile/T27314.hs - + testsuite/tests/pmcheck/should_compile/T27360.hs - testsuite/tests/pmcheck/should_compile/all.T - testsuite/tests/polykinds/T7594.hs - testsuite/tests/printer/AnnotationNoListTuplePuns.stdout - + testsuite/tests/printer/Haddock1.hs - testsuite/tests/printer/Makefile - testsuite/tests/printer/T18791.stderr - + testsuite/tests/printer/T27423c.hs - testsuite/tests/printer/Test20297.stdout - testsuite/tests/printer/Test24533.stdout - testsuite/tests/printer/all.T - testsuite/tests/process/T3994.hs - testsuite/tests/process/process009.hs - testsuite/tests/process/process009.stdout - testsuite/tests/profiling/should_run/callstack001.stdout - testsuite/tests/profiling/should_run/callstack002.stderr - testsuite/tests/profiling/should_run/callstack002.stdout - testsuite/tests/programs/thurston-modular-arith/Main.hs - testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs - testsuite/tests/rename/should_compile/T3103/GHC/Base.lhs - testsuite/tests/rename/should_compile/T3103/GHC/Word.hs - testsuite/tests/rename/should_compile/T3103/test.T - testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr - testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr - + testsuite/tests/rename/should_fail/T21101.hs - + testsuite/tests/rename/should_fail/T21101.stderr - testsuite/tests/rename/should_fail/T26545.stderr - testsuite/tests/rename/should_fail/T9815.stderr - testsuite/tests/rename/should_fail/T9815b.stderr - testsuite/tests/rename/should_fail/T9815bghci.stderr - testsuite/tests/rename/should_fail/T9815ghci.stderr - testsuite/tests/rename/should_fail/all.T - testsuite/tests/rep-poly/RepPolyRecordPattern.hs - testsuite/tests/rep-poly/RepPolyRecordPattern.stderr - testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr - testsuite/tests/rep-poly/T20113.stderr - − testsuite/tests/rep-poly/T20363.stderr - − testsuite/tests/rep-poly/T20363_show_co.hs - − testsuite/tests/rep-poly/T20363_show_co.stderr - − testsuite/tests/rep-poly/T20363b.stderr - + testsuite/tests/rep-poly/T20363c.hs - + testsuite/tests/rep-poly/T27639.hs - testsuite/tests/rep-poly/all.T - testsuite/tests/roles/should_compile/Roles1.stderr - testsuite/tests/roles/should_compile/Roles13.stderr - testsuite/tests/roles/should_compile/Roles14.stderr - testsuite/tests/roles/should_compile/Roles2.stderr - testsuite/tests/roles/should_compile/Roles3.stderr - testsuite/tests/roles/should_compile/Roles4.stderr - testsuite/tests/roles/should_compile/T8958.stderr - + testsuite/tests/rts/T19048.hs - + testsuite/tests/rts/T19048.stdout - + testsuite/tests/rts/T27123.hs - + testsuite/tests/rts/T27585.hs - + testsuite/tests/rts/T27585.stdout - testsuite/tests/rts/all.T - testsuite/tests/rts/ipe/IpeStats/Fold.hs - testsuite/tests/rts/linker/all.T - testsuite/tests/runghc/T7859.stderr-mingw32 - + testsuite/tests/saks/should_compile/T18725a.hs - testsuite/tests/saks/should_compile/all.T - + testsuite/tests/saks/should_fail/T18725b.hs - + testsuite/tests/saks/should_fail/T18725b.stderr - testsuite/tests/saks/should_fail/all.T - + testsuite/tests/show-bytecode/Example.hs - + testsuite/tests/show-bytecode/Makefile - + testsuite/tests/show-bytecode/all.T - + testsuite/tests/show-bytecode/normalize - + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout - + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout-javascript-unknown-ghcjs - + testsuite/tests/show-bytecode/show-bytecode-hpc.stdout - + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout - + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout-javascript-unknown-ghcjs - + testsuite/tests/simd/should_run/T27565.hs - + testsuite/tests/simd/should_run/T27565.stdout - testsuite/tests/simd/should_run/all.T - testsuite/tests/simd/should_run/doublex2_arith.hs - testsuite/tests/simd/should_run/doublex2_arith.stdout - testsuite/tests/simd/should_run/doublex2_arith_baseline.hs - testsuite/tests/simd/should_run/doublex2_arith_baseline.stdout - testsuite/tests/simd/should_run/doublex2_fma.hs - testsuite/tests/simd/should_run/doublex2_fma.stdout - testsuite/tests/simd/should_run/simd010.hs - testsuite/tests/simplCore/should_compile/DataToTagFamilyScrut.stderr - testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr - testsuite/tests/simplCore/should_compile/T11562.hs - testsuite/tests/simplCore/should_compile/T13543.stderr - testsuite/tests/simplCore/should_compile/T14978.stdout - testsuite/tests/simplCore/should_compile/T16038/T16038.stdout - testsuite/tests/simplCore/should_compile/T17966.stderr - testsuite/tests/simplCore/should_compile/T18013.stderr - testsuite/tests/simplCore/should_compile/T24229a.stderr - testsuite/tests/simplCore/should_compile/T24229b.stderr - testsuite/tests/simplCore/should_compile/T26615.stderr - + testsuite/tests/simplCore/should_compile/T27556.hs - + testsuite/tests/simplCore/should_compile/T27556.script - + testsuite/tests/simplCore/should_compile/T27589.hs - + testsuite/tests/simplCore/should_compile/T27589.stderr - + testsuite/tests/simplCore/should_compile/T27590.hs - + testsuite/tests/simplCore/should_compile/T27590.stderr - testsuite/tests/simplCore/should_compile/T3717.stderr - testsuite/tests/simplCore/should_compile/T3772.stdout - testsuite/tests/simplCore/should_compile/T4081.stderr - testsuite/tests/simplCore/should_compile/T4908.stderr - testsuite/tests/simplCore/should_compile/T4930.stderr - testsuite/tests/simplCore/should_compile/T7360.stderr - testsuite/tests/simplCore/should_compile/T7785.stderr - testsuite/tests/simplCore/should_compile/T8274.stdout - testsuite/tests/simplCore/should_compile/T9400.stderr - testsuite/tests/simplCore/should_compile/all.T - testsuite/tests/simplCore/should_compile/noinline01.stderr - testsuite/tests/simplCore/should_compile/par01.stderr - testsuite/tests/simplCore/should_compile/rule2.stderr - testsuite/tests/simplCore/should_compile/spec004.hs - testsuite/tests/simplCore/should_compile/spec004.stderr - testsuite/tests/simplCore/should_compile/str-rules.hs - + testsuite/tests/simplCore/should_run/T27703/Lib.hs - + testsuite/tests/simplCore/should_run/T27703/Main.hs - + testsuite/tests/simplCore/should_run/T27703/T27703.stdout - + testsuite/tests/simplCore/should_run/T27703/all.T - + testsuite/tests/simplCore/should_run/T27705.hs - + testsuite/tests/simplCore/should_run/T27705.stdout - + testsuite/tests/simplCore/should_run/T27705_Inst.hs - testsuite/tests/simplCore/should_run/T3591.hs - testsuite/tests/simplCore/should_run/all.T - testsuite/tests/splice-imports/SI35.hs - testsuite/tests/tcplugins/ArgsPlugin.hs - testsuite/tests/tcplugins/EmitWantedPlugin.hs - testsuite/tests/tcplugins/RewritePlugin.hs - testsuite/tests/tcplugins/T26395_Plugin.hs - testsuite/tests/tcplugins/TcPlugin_RewritePerf.hs - testsuite/tests/tcplugins/TcPlugin_RewritePerf.stderr - testsuite/tests/tcplugins/TyFamPlugin.hs - + testsuite/tests/th/AssocDefaultNotAssoc.hs - + testsuite/tests/th/AssocDefaultNotAssoc.stderr - testsuite/tests/th/T14741.hs - testsuite/tests/th/T17380.stderr - testsuite/tests/th/T18612.stderr - + testsuite/tests/th/T20902.hs - testsuite/tests/th/T21547.stderr - testsuite/tests/th/T26568.stderr - + testsuite/tests/th/T27013th.hs - + testsuite/tests/th/T27034.hs - + testsuite/tests/th/T27034.stderr - testsuite/tests/th/T8761.stderr - + testsuite/tests/th/TH_InvalidTopDecl.hs - + testsuite/tests/th/TH_InvalidTopDecl.stderr - testsuite/tests/th/TH_Roles2.stderr - + testsuite/tests/th/TH_cvt_DefaultDataInstDecl.hs - + testsuite/tests/th/TH_cvt_DefaultDataInstDecl.stderr - + testsuite/tests/th/TH_cvt_GadtNoCons.hs - + testsuite/tests/th/TH_cvt_GadtNoCons.stderr - + testsuite/tests/th/TH_cvt_IllegalDeclaration.hs - + testsuite/tests/th/TH_cvt_IllegalDeclaration.stderr - + testsuite/tests/th/TH_cvt_IllegalSumAlt.hs - + testsuite/tests/th/TH_cvt_IllegalSumAlt.stderr - + testsuite/tests/th/TH_cvt_InvalidCCallImpent.hs - + testsuite/tests/th/TH_cvt_InvalidCCallImpent.stderr - + testsuite/tests/th/TH_cvt_InvalidTyFamInstLHS.hs - + testsuite/tests/th/TH_cvt_InvalidTyFamInstLHS.stderr - + testsuite/tests/th/TH_cvt_InvalidTypeInstanceHeader.hs - + testsuite/tests/th/TH_cvt_InvalidTypeInstanceHeader.stderr - + testsuite/tests/th/TH_cvt_RecGadtNoCons.hs - + testsuite/tests/th/TH_cvt_RecGadtNoCons.stderr - + testsuite/tests/th/TH_cvt_SumAltArityExceeded.hs - + testsuite/tests/th/TH_cvt_SumAltArityExceeded.stderr - + testsuite/tests/th/TH_pragmaSpecOld.hs - + testsuite/tests/th/TH_pragmaSpecOld.stderr - testsuite/tests/th/all.T - testsuite/tests/typecheck/should_compile/DeepSubsumption02.hs - + testsuite/tests/typecheck/should_compile/LazyFieldAnnotations.hs - testsuite/tests/typecheck/should_compile/T12507.hs - testsuite/tests/typecheck/should_compile/T13032.stderr - testsuite/tests/typecheck/should_compile/T13951.hs - testsuite/tests/typecheck/should_compile/T14273.stderr - testsuite/tests/typecheck/should_compile/T15242.stderr - testsuite/tests/typecheck/should_compile/T18406b.stderr - testsuite/tests/typecheck/should_compile/T18529.stderr - testsuite/tests/typecheck/should_compile/T18920.hs - testsuite/tests/typecheck/should_compile/T2595.hs - + testsuite/tests/typecheck/should_compile/T27557.hs - + testsuite/tests/typecheck/should_compile/T27664.hs - testsuite/tests/typecheck/should_compile/T7541.hs - + testsuite/tests/typecheck/should_compile/WarnDefaultedCallStack.hs - + testsuite/tests/typecheck/should_compile/WarnDefaultedCallStack.stderr - testsuite/tests/typecheck/should_compile/all.T - testsuite/tests/typecheck/should_compile/holes.stderr - testsuite/tests/typecheck/should_compile/holes2.stderr - testsuite/tests/typecheck/should_compile/holes3.stderr - testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr - testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr - testsuite/tests/typecheck/should_fail/LazyFieldsDisabled.stderr - + testsuite/tests/typecheck/should_fail/LazyFieldsDisabledStrictData.hs - + testsuite/tests/typecheck/should_fail/LazyFieldsDisabledStrictData.stderr - testsuite/tests/typecheck/should_fail/T12921.stderr - testsuite/tests/typecheck/should_fail/T14884.stderr - testsuite/tests/typecheck/should_fail/T15067.stderr - testsuite/tests/typecheck/should_fail/T15883b.stderr - testsuite/tests/typecheck/should_fail/T15883c.stderr - testsuite/tests/typecheck/should_fail/T15883d.stderr - testsuite/tests/typecheck/should_fail/T21130.stderr - + testsuite/tests/typecheck/should_fail/T26532.hs - + testsuite/tests/typecheck/should_fail/T26532.stderr - testsuite/tests/typecheck/should_fail/T3323.stderr - testsuite/tests/typecheck/should_fail/T5095.stderr - testsuite/tests/typecheck/should_fail/T5300.stderr - testsuite/tests/typecheck/should_fail/T6069.stderr - testsuite/tests/typecheck/should_fail/T7279.stderr - testsuite/tests/typecheck/should_fail/T7368a.hs - testsuite/tests/typecheck/should_fail/T9858b.stderr - testsuite/tests/typecheck/should_fail/TcStaticPointersFail02.stderr - testsuite/tests/typecheck/should_fail/TyAppPat_PatternBindingExistential.stderr - testsuite/tests/typecheck/should_fail/all.T - testsuite/tests/typecheck/should_fail/tcfail072.stderr - testsuite/tests/typecheck/should_fail/tcfail097.stderr - testsuite/tests/typecheck/should_fail/tcfail133.stderr - testsuite/tests/typecheck/should_run/T1735_Help/Basics.hs - testsuite/tests/typecheck/should_run/T22510.stdout - testsuite/tests/typecheck/should_run/T3731-short.hs - testsuite/tests/typecheck/should_run/T3731.hs - testsuite/tests/typecheck/should_run/church.hs - testsuite/tests/typecheck/should_run/tcrun008.hs - testsuite/tests/typecheck/should_run/tcrun017.hs - testsuite/tests/typecheck/should_run/tcrun026.hs - testsuite/tests/typecheck/should_run/tcrun035.hs - testsuite/tests/typecheck/should_run/tcrun036.hs - testsuite/tests/unboxedsums/UbxSumLevPoly.hs - testsuite/tests/unboxedsums/unboxedsums_unit_tests.hs - + testsuite/tests/vdq-rta/should_compile/T27583a.hs - + testsuite/tests/vdq-rta/should_compile/T27583b.hs - + testsuite/tests/vdq-rta/should_compile/T27583c.hs - + testsuite/tests/vdq-rta/should_compile/T27583d.hs - + testsuite/tests/vdq-rta/should_compile/T27583e.hs - + testsuite/tests/vdq-rta/should_compile/T27583g.hs - testsuite/tests/vdq-rta/should_compile/all.T - + testsuite/tests/vdq-rta/should_fail/T27440e.hs - + testsuite/tests/vdq-rta/should_fail/T27440e.stderr - + testsuite/tests/vdq-rta/should_fail/T27583f.hs - + testsuite/tests/vdq-rta/should_fail/T27583f.stderr - + testsuite/tests/vdq-rta/should_fail/T27586a.hs - + testsuite/tests/vdq-rta/should_fail/T27586a.stderr - + testsuite/tests/vdq-rta/should_fail/T27586b.hs - + testsuite/tests/vdq-rta/should_fail/T27586b.stderr - + testsuite/tests/vdq-rta/should_fail/T27586c.hs - + testsuite/tests/vdq-rta/should_fail/T27586c.stderr - testsuite/tests/vdq-rta/should_fail/all.T - testsuite/tests/warnings/should_compile/DerivingTypeable.stderr - + testsuite/tests/warnings/should_compile/T16836a.hs - + testsuite/tests/warnings/should_compile/T16836a.stderr - + testsuite/tests/warnings/should_compile/T16836b.hs - + testsuite/tests/warnings/should_compile/T16836c.hs - + testsuite/tests/warnings/should_compile/T16836c.stderr - + testsuite/tests/warnings/should_compile/T16836d.hs - + testsuite/tests/warnings/should_compile/T16836d.stderr - testsuite/tests/warnings/should_compile/all.T - utils/check-exact/ExactPrint.hs - utils/check-exact/Main.hs - utils/check-exact/Parsers.hs - utils/check-exact/Transform.hs - utils/check-exact/Utils.hs - utils/check-exact/check-exact.cabal - utils/check-ppr/Main.hs - utils/deriveConstants/Main.hs - utils/genprimopcode/Main.hs - utils/ghc-toolchain/src/GHC/Toolchain/Program.hs - utils/ghc-toolchain/src/GHC/Toolchain/Target.hs - utils/haddock/haddock-api/haddock-api.cabal - utils/haddock/haddock-api/src/Haddock.hs - utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.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/GhcUtils.hs - utils/haddock/haddock-api/src/Haddock/Interface.hs - utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs - utils/haddock/haddock-api/src/Haddock/Interface/Create.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/-/compare/7149129c72d312e3bbd215293d2b82… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7149129c72d312e3bbd215293d2b82… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/sjakobi/T27688-bt-single-bit-tests] X86 NCG: use bt for single-bit tests
by Simon Jakobi (@sjakobi) 05 Sep '26

05 Sep '26
Simon Jakobi pushed to branch wip/sjakobi/T27688-bt-single-bit-tests at Glasgow Haskell Compiler / GHC Commits: 292acffe by Simon Jakobi at 2026-09-05T23:26:27+02:00 X86 NCG: use bt for single-bit tests Previously the Cmm patterns (x & (1 << i)) != 0 (x & (1 << i)) == 0 compiled to a mov/shl/and/test sequence pinning the shift count to %cl. Now they compile to a single bt, whose carry flag feeds the branch or setcc directly, matching what C compilers produce. As for btr/bts/btc, a literal single-bit mask that does not fit in an imm32 (e.g. x & (1 << 40)) is also tested with bt, with an immediate bit offset. Masks that do fit keep using test, since test+jcc macro-fuse and bt+jcc do not. The same restriction as for btr/bts/btc applies: a variable bit index is only recognised when the shift is unchecked. Data.Bits.testBit on Int and Word goes through the bounds-checked shiftL, whose bounds mask this pattern does not see through, so it does not benefit yet. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Closes #27688. Assisted-by: Claude Fable 5.1 - - - - - 9 changed files: - + changelog.d/ncg-x86-bt-single-bit-tests - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToAsm/X86/Ppr.hs - + testsuite/tests/codeGen/should_gen_asm/T27688.asm - + testsuite/tests/codeGen/should_gen_asm/T27688.hs - + testsuite/tests/codeGen/should_gen_asm/T27688b.asm - + testsuite/tests/codeGen/should_gen_asm/T27688b.cmm - testsuite/tests/codeGen/should_gen_asm/all.T Changes: ===================================== changelog.d/ncg-x86-bt-single-bit-tests ===================================== @@ -0,0 +1,15 @@ +section: compiler +synopsis: The x86 native code generator now uses the bit-test instruction + ``bt`` to test a single bit +description: + Cmm patterns such as ``(x & (1 << i)) != 0`` and ``(x & (1 << i)) == 0`` + now compile to a single ``bt`` instruction, whose carry flag feeds the + conditional branch directly, instead of a mov/shl/and/test sequence, + matching what C compilers produce. The same applies to a literal mask + that doesn't fit in an imm32 operand, such as ``x & (1 << 40)``. + + As for ``btr``/``bts``/``btc``, a variable bit index benefits only when + the shift is unchecked. The bounds mask added by the checked ``shiftL``, + and hence by the default ``Data.Bits.testBit``, hides the pattern. +mrs: !16639 +issues: #27688 ===================================== compiler/GHC/CmmToAsm/X86/CodeGen.hs ===================================== @@ -3945,6 +3945,24 @@ condIntCode' platform cond (CmmLoad x ty _) (CmmLit lit) -- return (CondCode False cond code) +-- single-bit test, e.g. (x & (1 << i)) != 0 +-- see Note [Bit-test instructions] +condIntCode' platform cond (CmmMachOp (MO_And w) [x, y]) (CmmLit (CmmInt 0 _)) + | Just bt_cond <- bitTestCond cond + , bitTestOpWidthOK (target32Bit platform) w + , Just (opnd, ix) <- setBitArgs_maybe platform w x y + , let fmt = intFormat w + = case ix of + BitIndexImm i -> do + (x_reg, x_code) <- getSomeReg opnd + return $ CondCode False bt_cond $ + x_code `snocOL` BT fmt (OpImm (ImmInt i)) (OpReg x_reg) + BitIndexReg i -> do + (i_reg, i_code) <- getNonClobberedReg i + (x_reg, x_code) <- getSomeReg opnd + return $ CondCode False bt_cond $ + i_code `appOL` x_code `snocOL` BT fmt (OpReg i_reg) (OpReg x_reg) + -- anything vs zero, using a mask -- TODO: Add some sanity checking!!!! condIntCode' platform cond (CmmMachOp (MO_And _) [x,o2]) (CmmLit (CmmInt 0 ty)) @@ -5901,17 +5919,18 @@ genTrivialCode rep instr a b = do {- Note [Bit-test instructions] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -x86 has dedicated instructions for clearing (btr), setting (bts) and -complementing (btc) a single bit whose index is given in a register. We use -them for Cmm patterns such as +x86 has dedicated instructions for testing (bt), clearing (btr), setting +(bts) and complementing (btc) a single bit whose index is given in a +register. We use them for Cmm patterns such as - x & ~(1 << i) ==> btr i, x (#25233) + (x & (1 << i)) != 0 ==> bt i, x; jc + x & ~(1 << i) ==> btr i, x -replacing a mov/shl/not/and sequence with a single instruction. The -shift-count register operand of shl is masked modulo the operand width, and -the bit-offset register operand of btr/bts/btc is masked the same way, so -the replacement is faithful even for out-of-range i (where the Cmm shift is -in any case undefined). +replacing a mov/shl/and/test or mov/shl/not/and sequence with a single +instruction. The shift-count register operand of shl is masked modulo the +operand width, and the bit-offset register operand of the bit-test +instructions is masked the same way, so the replacement is faithful even for +out-of-range i (where the Cmm shift is in any case undefined). The bit-offset operand of these instructions must be an immediate or a register. When the bit index is a literal, no shift reaches the NCG: @@ -5919,10 +5938,11 @@ constant folding has already turned the whole mask into a literal. If that mask fits in an imm32, we keep the ordinary and/or/xor with an immediate: it has the same latency and better throughput (more execution ports) than the bit-test instructions, and at worst two bytes of extra code size for bit -indices 7..30. +indices 7..30. Likewise a single-bit test keeps 'test' with an immediate: +test+jcc macro-fuse into one uop, bt+jcc do not. But a W64 mask touching the upper bits, e.g. ~(1 << 40), would have to be moved into a register first. For such masks we recognise the folded literal itself -(exactly one bit clear resp. set) and emit btr/bts/btc with an immediate +(exactly one bit clear resp. set) and emit bt/btr/bts/btc with an immediate bit offset. We restrict the pattern to W32 and native-width W64: the instructions do not @@ -5959,14 +5979,25 @@ clearBitLit_maybe w m = setBitLit_maybe w (complement m) bitTestOpWidthOK :: Bool -> Width -> Bool bitTestOpWidthOK is32Bit w = w == W32 || (w == W64 && not is32Bit) --- | The bit-offset operand of a bit-test instruction (btr/bts/btc). +-- | The condition to branch on after @bt@, for a @mask != 0@ ('NE') or +-- @mask == 0@ ('EQQ') comparison. 'Nothing' for any other condition. +-- +-- @bt@ reports the tested bit in CF, so we branch on 'CARRY' or 'GEU' +-- rather than on ZF via 'NE' or 'EQQ'. +bitTestCond :: Cond -> Maybe Cond +bitTestCond NE = Just CARRY +bitTestCond EQQ = Just GEU +bitTestCond _ = Nothing + +-- | The bit-offset operand of a bit-test instruction. data BitIndex = BitIndexReg CmmExpr -- ^ variable index, computed into a register | BitIndexImm Int -- ^ literal index, emitted as an immediate --- | Match the operands of a single-bit set or complement operation: one --- operand is a mask @1 << i@, or a literal with exactly one bit set that --- does not fit in an imm32. Returns the other operand and the bit index. +-- | Match the operands of a single-bit set, complement or test operation: +-- one operand is a mask @1 << i@, or a literal with exactly one bit set +-- that does not fit in an imm32. Returns the other operand and the bit +-- index. -- -- Both operand orders are matched, e.g. @x | (1 << i)@ and @(1 << i) | x@. -- ===================================== compiler/GHC/CmmToAsm/X86/Instr.hs ===================================== @@ -192,7 +192,8 @@ data Instr | SHRD Format Operand{-amount-} Operand Operand | SHLD Format Operand{-amount-} Operand Operand - | BT Format Imm Operand + -- | Bit test + | BT Format Operand{- ^ bit offset (imm/reg) -} Operand -- | Bit test-and-reset | BTR Format Operand{- ^ bit offset (imm/reg) -} Operand -- | Bit set @@ -501,7 +502,7 @@ regUsageOfInstr platform instr SHR fmt imm dst -> usageRM fmt imm dst SHLD fmt imm dst1 dst2 -> usageRMM fmt imm dst1 dst2 SHRD fmt imm dst1 dst2 -> usageRMM fmt imm dst1 dst2 - BT fmt _ src -> mkRUR (use_R fmt src []) + BT fmt off src -> mkRUR (use_R fmt off $! use_R fmt src []) BTR fmt off dst -> usageRM fmt off dst BTS fmt off dst -> usageRM fmt off dst BTC fmt off dst -> usageRM fmt off dst @@ -838,7 +839,7 @@ patchRegsOfInstr platform instr env SHR fmt imm dst -> patch1 (SHR fmt imm) dst SHLD fmt imm dst1 dst2 -> patch2 (SHLD fmt imm) dst1 dst2 SHRD fmt imm dst1 dst2 -> patch2 (SHRD fmt imm) dst1 dst2 - BT fmt imm src -> patch1 (BT fmt imm) src + BT fmt off src -> patch2 (BT fmt) off src BTR fmt off dst -> patch2 (BTR fmt) off dst BTS fmt off dst -> patch2 (BTS fmt) off dst BTC fmt off dst -> patch2 (BTC fmt) off dst ===================================== compiler/GHC/CmmToAsm/X86/Ppr.hs ===================================== @@ -859,8 +859,8 @@ pprInstr platform i = case i of SHRD format src dst1 dst2 -> pprShift2 (text "shrd") format src dst1 dst2 - BT format imm src - -> pprFormatImmOp (text "bt") format imm src + BT format off src + -> pprFormatOpOp (text "bt") format off src BTR format off dst -> pprFormatOpOp (text "btr") format off dst @@ -1250,16 +1250,6 @@ pprInstr platform i = case i of FmtInt64 -> text "q" pprBroadcastFormat _ = panic "Scalar Format invading vector operation" - pprFormatImmOp :: Line doc -> Format -> Imm -> Operand -> doc - pprFormatImmOp name format imm op1 - = line $ hcat [ - pprMnemonic name format, - char '$', - pprImm platform imm, - comma, - pprOperand platform format op1 - ] - pprFormatOp_ :: Line doc -> Format -> Operand -> doc pprFormatOp_ name format op1 = line $ hcat [ ===================================== testsuite/tests/codeGen/should_gen_asm/T27688.asm ===================================== @@ -0,0 +1,3 @@ +btq % +btl % +btq $40, ===================================== testsuite/tests/codeGen/should_gen_asm/T27688.hs ===================================== @@ -0,0 +1,30 @@ +{-# LANGUAGE MagicHash #-} + +-- Check that testing a single, variable bit uses the bt instruction +-- (#27688). +module T27688 where + +import GHC.Exts + +testBitNe :: Word# -> Int# -> Int# +testBitNe x i = + if isTrue# ((x `and#` (1## `uncheckedShiftL#` i)) `neWord#` 0##) + then 1# else 2# + +testBitEq :: Word# -> Int# -> Int# +testBitEq x i = + if isTrue# ((x `and#` (1## `uncheckedShiftL#` i)) `eqWord#` 0##) + then 1# else 2# + +testBit32 :: Word32# -> Int# -> Int# +testBit32 x i = + if isTrue# ((x `andWord32#` (wordToWord32# 1## `uncheckedShiftLWord32#` i)) + `neWord32#` wordToWord32# 0##) + then 1# else 2# + +-- With a constant bit index >= 32, the mask constant-folds to a literal +-- that does not fit in an imm32, so bt with an immediate offset is used. +testBit40 :: Word# -> Int# +testBit40 x = + if isTrue# ((x `and#` (1## `uncheckedShiftL#` 40#)) `neWord#` 0##) + then 1# else 2# ===================================== testsuite/tests/codeGen/should_gen_asm/T27688b.asm ===================================== @@ -0,0 +1,4 @@ +btq % +setc +setae +btq $40, ===================================== testsuite/tests/codeGen/should_gen_asm/T27688b.cmm ===================================== @@ -0,0 +1,21 @@ +#include "Cmm.h" + +// Single-bit tests whose result is used as a value rather than as a branch +// condition, a literal mask that does not fit in an imm32, and the mask on +// the left of the operator (#27688). + +testBitValue (W_ x, W_ i) { + return ((x & (1 << i)) != 0); +} + +testBitValueEq (W_ x, W_ i) { + return ((x & (1 << i)) == 0); +} + +testBit40 (W_ x) { + return (((0x10000000000 :: bits64) & x) != 0); +} + +testBitLeft (W_ x, W_ i) { + return (((1 << i) & x) != 0); +} ===================================== testsuite/tests/codeGen/should_gen_asm/all.T ===================================== @@ -27,6 +27,10 @@ test('T25233', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O']) test('T25233b', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, '']) +test('T27688', [unless(arch('x86_64'), skip), + when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O']) +test('T27688b', [unless(arch('x86_64'), skip), + when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, '']) is_aarch64_codegen = [ unless(arch('aarch64'), skip), when(unregisterised(), skip), View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/292acffe17879bb0c8f7e7d8314d31a… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/292acffe17879bb0c8f7e7d8314d31a… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/sjakobi/T27688-bt-single-bit-tests] X86 NCG: use bt for single-bit tests
by Simon Jakobi (@sjakobi) 05 Sep '26

05 Sep '26
Simon Jakobi pushed to branch wip/sjakobi/T27688-bt-single-bit-tests at Glasgow Haskell Compiler / GHC Commits: 342dc80c by Simon Jakobi at 2026-09-05T23:22:20+02:00 X86 NCG: use bt for single-bit tests Previously the Cmm patterns (x & (1 << i)) != 0 (x & (1 << i)) == 0 compiled to a mov/shl/and/test sequence pinning the shift count to %cl. Now they compile to a single bt, whose carry flag feeds the branch or setcc directly, matching what C compilers produce. As for btr/bts/btc, a literal single-bit mask that does not fit in an imm32 (e.g. x & (1 << 40)) is also tested with bt, with an immediate bit offset. Masks that do fit keep using test, since test+jcc macro-fuse and bt+jcc do not. The same restriction as for btr/bts/btc applies: a variable bit index is only recognised when the shift is unchecked. Data.Bits.testBit on Int and Word goes through the bounds-checked shiftL, whose bounds mask this pattern does not see through, so it does not benefit yet. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Closes #27688. Assisted-by: Claude Fable 5.1 - - - - - 9 changed files: - + changelog.d/ncg-x86-bt-single-bit-tests - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToAsm/X86/Ppr.hs - + testsuite/tests/codeGen/should_gen_asm/T27688.asm - + testsuite/tests/codeGen/should_gen_asm/T27688.hs - + testsuite/tests/codeGen/should_gen_asm/T27688b.asm - + testsuite/tests/codeGen/should_gen_asm/T27688b.cmm - testsuite/tests/codeGen/should_gen_asm/all.T Changes: ===================================== changelog.d/ncg-x86-bt-single-bit-tests ===================================== @@ -0,0 +1,15 @@ +section: compiler +synopsis: The x86 native code generator now uses the bit-test instruction + ``bt`` to test a single bit +description: + Cmm patterns such as ``(x & (1 << i)) != 0`` and ``(x & (1 << i)) == 0`` + now compile to a single ``bt`` instruction, whose carry flag feeds the + conditional branch directly, instead of a mov/shl/and/test sequence, + matching what C compilers produce. The same applies to a literal mask + that doesn't fit in an imm32 operand, such as ``x & (1 << 40)``. + + As for ``btr``/``bts``/``btc``, a variable bit index benefits only when + the shift is unchecked. The bounds mask added by the checked ``shiftL``, + and hence by the default ``Data.Bits.testBit``, hides the pattern. +mrs: !0 +issues: #27688 ===================================== compiler/GHC/CmmToAsm/X86/CodeGen.hs ===================================== @@ -3945,6 +3945,24 @@ condIntCode' platform cond (CmmLoad x ty _) (CmmLit lit) -- return (CondCode False cond code) +-- single-bit test, e.g. (x & (1 << i)) != 0 +-- see Note [Bit-test instructions] +condIntCode' platform cond (CmmMachOp (MO_And w) [x, y]) (CmmLit (CmmInt 0 _)) + | Just bt_cond <- bitTestCond cond + , bitTestOpWidthOK (target32Bit platform) w + , Just (opnd, ix) <- setBitArgs_maybe platform w x y + , let fmt = intFormat w + = case ix of + BitIndexImm i -> do + (x_reg, x_code) <- getSomeReg opnd + return $ CondCode False bt_cond $ + x_code `snocOL` BT fmt (OpImm (ImmInt i)) (OpReg x_reg) + BitIndexReg i -> do + (i_reg, i_code) <- getNonClobberedReg i + (x_reg, x_code) <- getSomeReg opnd + return $ CondCode False bt_cond $ + i_code `appOL` x_code `snocOL` BT fmt (OpReg i_reg) (OpReg x_reg) + -- anything vs zero, using a mask -- TODO: Add some sanity checking!!!! condIntCode' platform cond (CmmMachOp (MO_And _) [x,o2]) (CmmLit (CmmInt 0 ty)) @@ -5901,17 +5919,18 @@ genTrivialCode rep instr a b = do {- Note [Bit-test instructions] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -x86 has dedicated instructions for clearing (btr), setting (bts) and -complementing (btc) a single bit whose index is given in a register. We use -them for Cmm patterns such as +x86 has dedicated instructions for testing (bt), clearing (btr), setting +(bts) and complementing (btc) a single bit whose index is given in a +register. We use them for Cmm patterns such as - x & ~(1 << i) ==> btr i, x (#25233) + (x & (1 << i)) != 0 ==> bt i, x; jc + x & ~(1 << i) ==> btr i, x -replacing a mov/shl/not/and sequence with a single instruction. The -shift-count register operand of shl is masked modulo the operand width, and -the bit-offset register operand of btr/bts/btc is masked the same way, so -the replacement is faithful even for out-of-range i (where the Cmm shift is -in any case undefined). +replacing a mov/shl/and/test or mov/shl/not/and sequence with a single +instruction. The shift-count register operand of shl is masked modulo the +operand width, and the bit-offset register operand of the bit-test +instructions is masked the same way, so the replacement is faithful even for +out-of-range i (where the Cmm shift is in any case undefined). The bit-offset operand of these instructions must be an immediate or a register. When the bit index is a literal, no shift reaches the NCG: @@ -5919,10 +5938,11 @@ constant folding has already turned the whole mask into a literal. If that mask fits in an imm32, we keep the ordinary and/or/xor with an immediate: it has the same latency and better throughput (more execution ports) than the bit-test instructions, and at worst two bytes of extra code size for bit -indices 7..30. +indices 7..30. Likewise a single-bit test keeps 'test' with an immediate: +test+jcc macro-fuse into one uop, bt+jcc do not. But a W64 mask touching the upper bits, e.g. ~(1 << 40), would have to be moved into a register first. For such masks we recognise the folded literal itself -(exactly one bit clear resp. set) and emit btr/bts/btc with an immediate +(exactly one bit clear resp. set) and emit bt/btr/bts/btc with an immediate bit offset. We restrict the pattern to W32 and native-width W64: the instructions do not @@ -5959,14 +5979,25 @@ clearBitLit_maybe w m = setBitLit_maybe w (complement m) bitTestOpWidthOK :: Bool -> Width -> Bool bitTestOpWidthOK is32Bit w = w == W32 || (w == W64 && not is32Bit) --- | The bit-offset operand of a bit-test instruction (btr/bts/btc). +-- | The condition to branch on after @bt@, for a @mask != 0@ ('NE') or +-- @mask == 0@ ('EQQ') comparison. 'Nothing' for any other condition. +-- +-- @bt@ reports the tested bit in CF, so we branch on 'CARRY' or 'GEU' +-- rather than on ZF via 'NE' or 'EQQ'. +bitTestCond :: Cond -> Maybe Cond +bitTestCond NE = Just CARRY +bitTestCond EQQ = Just GEU +bitTestCond _ = Nothing + +-- | The bit-offset operand of a bit-test instruction. data BitIndex = BitIndexReg CmmExpr -- ^ variable index, computed into a register | BitIndexImm Int -- ^ literal index, emitted as an immediate --- | Match the operands of a single-bit set or complement operation: one --- operand is a mask @1 << i@, or a literal with exactly one bit set that --- does not fit in an imm32. Returns the other operand and the bit index. +-- | Match the operands of a single-bit set, complement or test operation: +-- one operand is a mask @1 << i@, or a literal with exactly one bit set +-- that does not fit in an imm32. Returns the other operand and the bit +-- index. -- -- Both operand orders are matched, e.g. @x | (1 << i)@ and @(1 << i) | x@. -- ===================================== compiler/GHC/CmmToAsm/X86/Instr.hs ===================================== @@ -192,7 +192,8 @@ data Instr | SHRD Format Operand{-amount-} Operand Operand | SHLD Format Operand{-amount-} Operand Operand - | BT Format Imm Operand + -- | Bit test + | BT Format Operand{- ^ bit offset (imm/reg) -} Operand -- | Bit test-and-reset | BTR Format Operand{- ^ bit offset (imm/reg) -} Operand -- | Bit set @@ -501,7 +502,7 @@ regUsageOfInstr platform instr SHR fmt imm dst -> usageRM fmt imm dst SHLD fmt imm dst1 dst2 -> usageRMM fmt imm dst1 dst2 SHRD fmt imm dst1 dst2 -> usageRMM fmt imm dst1 dst2 - BT fmt _ src -> mkRUR (use_R fmt src []) + BT fmt off src -> mkRUR (use_R fmt off $! use_R fmt src []) BTR fmt off dst -> usageRM fmt off dst BTS fmt off dst -> usageRM fmt off dst BTC fmt off dst -> usageRM fmt off dst @@ -838,7 +839,7 @@ patchRegsOfInstr platform instr env SHR fmt imm dst -> patch1 (SHR fmt imm) dst SHLD fmt imm dst1 dst2 -> patch2 (SHLD fmt imm) dst1 dst2 SHRD fmt imm dst1 dst2 -> patch2 (SHRD fmt imm) dst1 dst2 - BT fmt imm src -> patch1 (BT fmt imm) src + BT fmt off src -> patch2 (BT fmt) off src BTR fmt off dst -> patch2 (BTR fmt) off dst BTS fmt off dst -> patch2 (BTS fmt) off dst BTC fmt off dst -> patch2 (BTC fmt) off dst ===================================== compiler/GHC/CmmToAsm/X86/Ppr.hs ===================================== @@ -859,8 +859,8 @@ pprInstr platform i = case i of SHRD format src dst1 dst2 -> pprShift2 (text "shrd") format src dst1 dst2 - BT format imm src - -> pprFormatImmOp (text "bt") format imm src + BT format off src + -> pprFormatOpOp (text "bt") format off src BTR format off dst -> pprFormatOpOp (text "btr") format off dst @@ -1250,16 +1250,6 @@ pprInstr platform i = case i of FmtInt64 -> text "q" pprBroadcastFormat _ = panic "Scalar Format invading vector operation" - pprFormatImmOp :: Line doc -> Format -> Imm -> Operand -> doc - pprFormatImmOp name format imm op1 - = line $ hcat [ - pprMnemonic name format, - char '$', - pprImm platform imm, - comma, - pprOperand platform format op1 - ] - pprFormatOp_ :: Line doc -> Format -> Operand -> doc pprFormatOp_ name format op1 = line $ hcat [ ===================================== testsuite/tests/codeGen/should_gen_asm/T27688.asm ===================================== @@ -0,0 +1,3 @@ +btq % +btl % +btq $40, ===================================== testsuite/tests/codeGen/should_gen_asm/T27688.hs ===================================== @@ -0,0 +1,30 @@ +{-# LANGUAGE MagicHash #-} + +-- Check that testing a single, variable bit uses the bt instruction +-- (#27688). +module T27688 where + +import GHC.Exts + +testBitNe :: Word# -> Int# -> Int# +testBitNe x i = + if isTrue# ((x `and#` (1## `uncheckedShiftL#` i)) `neWord#` 0##) + then 1# else 2# + +testBitEq :: Word# -> Int# -> Int# +testBitEq x i = + if isTrue# ((x `and#` (1## `uncheckedShiftL#` i)) `eqWord#` 0##) + then 1# else 2# + +testBit32 :: Word32# -> Int# -> Int# +testBit32 x i = + if isTrue# ((x `andWord32#` (wordToWord32# 1## `uncheckedShiftLWord32#` i)) + `neWord32#` wordToWord32# 0##) + then 1# else 2# + +-- With a constant bit index >= 32, the mask constant-folds to a literal +-- that does not fit in an imm32, so bt with an immediate offset is used. +testBit40 :: Word# -> Int# +testBit40 x = + if isTrue# ((x `and#` (1## `uncheckedShiftL#` 40#)) `neWord#` 0##) + then 1# else 2# ===================================== testsuite/tests/codeGen/should_gen_asm/T27688b.asm ===================================== @@ -0,0 +1,4 @@ +btq % +setc +setae +btq $40, ===================================== testsuite/tests/codeGen/should_gen_asm/T27688b.cmm ===================================== @@ -0,0 +1,21 @@ +#include "Cmm.h" + +// Single-bit tests whose result is used as a value rather than as a branch +// condition, a literal mask that does not fit in an imm32, and the mask on +// the left of the operator (#27688). + +testBitValue (W_ x, W_ i) { + return ((x & (1 << i)) != 0); +} + +testBitValueEq (W_ x, W_ i) { + return ((x & (1 << i)) == 0); +} + +testBit40 (W_ x) { + return (((0x10000000000 :: bits64) & x) != 0); +} + +testBitLeft (W_ x, W_ i) { + return (((1 << i) & x) != 0); +} ===================================== testsuite/tests/codeGen/should_gen_asm/all.T ===================================== @@ -27,6 +27,10 @@ test('T25233', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O']) test('T25233b', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, '']) +test('T27688', [unless(arch('x86_64'), skip), + when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O']) +test('T27688b', [unless(arch('x86_64'), skip), + when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, '']) is_aarch64_codegen = [ unless(arch('aarch64'), skip), when(unregisterised(), skip), View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/342dc80cfd6695fa7c6c4aea785abd2… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/342dc80cfd6695fa7c6c4aea785abd2… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/sjakobi/T27688-bt-single-bit-tests] 7 commits: Add -Wimplicit-field-strictness (#16836)
by Simon Jakobi (@sjakobi) 05 Sep '26

05 Sep '26
Simon Jakobi pushed to branch wip/sjakobi/T27688-bt-single-bit-tests at Glasgow Haskell Compiler / GHC Commits: 9e7739ab by Simon Jakobi at 2026-09-03T13:45:43-04:00 Add -Wimplicit-field-strictness (#16836) This opt-in warning fires when a data constructor field lacks an explicit strictness annotation (`!` or `~`). It complements the LazyFieldAnnotations extension (4762a8bf30f) from GHC proposal 752, which makes `~` annotations available for this purpose. Deciding which fields to report requires their levity, so the check runs after typechecking. To keep the noise down, the diagnostic is emitted once per data declaration, grouped by constructor. Closes #16836. Assisted-by: Claude Fable 5 - - - - - 6a44d591 by mangoiv at 2026-09-03T13:46:22-04:00 simplifier: remove a bogus `assert` in `rebuild_app'` in `GHC.CoreToStg.Prep.cpeApp`. Prior to this commit commit 08bc245be70d95801bc1138804ed1de9474fbdc0 Author: sheaf <sam.derbyshire(a)gmail.com> Date: Sat Feb 28 16:30:43 2026 +0100 Clean up join points, casts & ticks This commit shores up the logic dealing with casts and ticks occurring in between a join point binding and a jump any `PlaceRuntime` ticks we observed were profiling ticks, even though that isn't necessary. The more liberal rules in the above commit allow e.g. breakpoint ticks (which are valid PlaceRuntime ticks) to legitimately appear in an argument position. Fixes #27556 - - - - - eaa95a6f by Andrei Borzenkov at 2026-09-04T08:08:40-04:00 Parentheses in prefix GADT constructors (#27423) Updated `splitLHsGadtTy` to allow looking through the parentheses for inner binders. General example of a code pattern that's allowed now: data S a where MkS :: (forall a. S a) That should work now with any combination of nested foralls and parentheses. We don't perform parenthesis unwrapping for record GADT constructors in accordance with GHC Proposal #402. To this end `con_inner_bndrs` no longer stores plain forall telescopes: `[HsForAllTelescope pass]` is replaced with `[LHsGadtTelescope pass]`, a new `HsArg`-style type whose `HsGadtForAll` holds an inner telescope and whose `HsGadtPar` holds a pair of parentheses. The parentheses carry no meaning for renaming or type checking; the only reason to record them is exact-printing. Updated `pprConDecl` to improve the `parse == parse . ppr . parse` property of GADT pretty-printing. The pretty printer can now output code that's similar to this: data T a where MkT1 :: (forall a. T a) MkT2 :: forall . forall a. T a These are special cases of inner forall binders for prefix GADT constructors, when we have either implicit or zero explicit outer binders. - - - - - 639456a8 by Evgeny Malyshev at 2026-09-04T08:09:25-04:00 HsPat: Add spacing to unary tuple patterns Use hsep when printing unary boxed TuplePat applications so that the MkSolo constructor is separated from its argument. The old hcat rendered wildcard and parenthesized arguments as MkSolo_ and MkSolo(). Add T27034 to exercise the HsPat splice-dump path with wildcard and variable arguments, and update existing affected golden output. Fixes #27034 Assisted-By: OpenAI Codex - - - - - 2908ab36 by Simon Jakobi at 2026-09-05T07:22:17-04:00 X86 NCG: use btr/bts/btc for single-bit operations Previously the Cmm patterns x & ~(1 << i) x | (1 << i) x ^ (1 << i) compiled to mov/shl/not/and-style sequences of 3-4 instructions. Now they compile to a single btr, bts or btc, matching what C compilers produce. When the bit index is a literal, constant folding has already collapsed these patterns into ones with a literal mask, such as x & 0xfffffeffffffffff for x & ~(1 << 40). Such masks are now also compiled to a bit-test instruction when they don't fit in an imm32 and would otherwise have to be loaded into a register first. For a variable bit index, this applies only when the shift is unchecked (uncheckedShiftL#, Data.Bits.unsafeShiftL): the bounds-checked shiftL used by e.g. the default clearBit/setBit/complementBit implementations wraps the shift in a bounds mask that this optimisation does not see through. With a literal index, the bounds mask is constant-folded away, so the checked operations benefit too. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Fixes #25233. Assisted-by: Claude Fable 5 - - - - - c673ecf0 by Simon Peyton Jones at 2026-09-05T07:22:59-04:00 Move HsStatic free-var test to typechecker A `static` form should have no free *term* variables, but it can have free *type* variables. Alas, the renamer does not really know what is a term variable and what is a type variable, because of required type arguments. This patch moves the test to the typechecker, which does know. Addresses #27664 - - - - - eace7759 by Simon Jakobi at 2026-09-05T23:19:33+02:00 X86 NCG: use bt for single-bit tests Previously the Cmm patterns (x & (1 << i)) != 0 (x & (1 << i)) == 0 compiled to a mov/shl/and/test sequence pinning the shift count to %cl. Now they compile to a single bt, whose carry flag feeds the branch or setcc directly, matching what C compilers produce. As for btr/bts/btc, a literal single-bit mask that does not fit in an imm32 (e.g. x & (1 << 40)) is also tested with bt, with an immediate bit offset. Masks that do fit keep using test, since test+jcc macro-fuse and bt+jcc do not. The same restriction as for btr/bts/btc applies: a variable bit index is only recognised when the shift is unchecked. Data.Bits.testBit on Int and Word goes through the bounds-checked shiftL, whose bounds mask this pattern does not see through, so it does not benefit yet. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Fixes #27688. Assisted-by: Claude Fable 5.1 - - - - - 84 changed files: - + changelog.d/27556 - + changelog.d/T27764 - + changelog.d/allow-gadt-prefix-con-parens - + changelog.d/implicit-field-strictness-warning - changelog.d/lazy-field-annotations - + changelog.d/ncg-x86-bit-test-instructions - + changelog.d/ncg-x86-bt-single-bit-tests - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToAsm/X86/Ppr.hs - compiler/GHC/CoreToStg/Prep.hs - compiler/GHC/Driver/Flags.hs - compiler/GHC/Driver/Session.hs - compiler/GHC/Hs/Decls.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/Hs/Instances.hs - compiler/GHC/Hs/Pat.hs - compiler/GHC/Hs/Type.hs - compiler/GHC/HsToCore/Quote.hs - compiler/GHC/Iface/Ext/Ast.hs - compiler/GHC/Rename/Expr.hs - compiler/GHC/Rename/HsType.hs - compiler/GHC/Rename/Module.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Errors/Types.hs - compiler/GHC/Tc/Gen/Expr.hs - compiler/GHC/Tc/Gen/HsType.hs - compiler/GHC/Tc/TyCl.hs - compiler/GHC/Types/Error/Codes.hs - compiler/GHC/Types/Hint.hs - compiler/GHC/Types/Hint/Ppr.hs - compiler/GHC/Types/Tickish.hs - compiler/Language/Haskell/Syntax/Decls.hs - compiler/Language/Haskell/Syntax/Type.hs - docs/users_guide/exts/gadt_syntax.rst - docs/users_guide/exts/strict.rst - docs/users_guide/using-warnings.rst - + testsuite/tests/codeGen/should_gen_asm/T25233.asm - + testsuite/tests/codeGen/should_gen_asm/T25233.hs - + testsuite/tests/codeGen/should_gen_asm/T25233b.asm - + testsuite/tests/codeGen/should_gen_asm/T25233b.cmm - + testsuite/tests/codeGen/should_gen_asm/T27688.asm - + testsuite/tests/codeGen/should_gen_asm/T27688.hs - + testsuite/tests/codeGen/should_gen_asm/T27688b.asm - + testsuite/tests/codeGen/should_gen_asm/T27688b.cmm - testsuite/tests/codeGen/should_gen_asm/all.T - − testsuite/tests/gadt/T14320.stderr - testsuite/tests/gadt/T18191.hs - testsuite/tests/gadt/T18191.stderr - + testsuite/tests/gadt/T27423a.hs - + testsuite/tests/gadt/T27423b.hs - + testsuite/tests/gadt/T27423b.stderr - testsuite/tests/gadt/all.T - testsuite/tests/printer/Makefile - + testsuite/tests/printer/T27423c.hs - testsuite/tests/printer/all.T - testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr - testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr - testsuite/tests/rename/should_fail/T26545.stderr - + testsuite/tests/simplCore/should_compile/T27556.hs - + testsuite/tests/simplCore/should_compile/T27556.script - testsuite/tests/simplCore/should_compile/all.T - testsuite/tests/th/T17380.stderr - testsuite/tests/th/T18612.stderr - + testsuite/tests/th/T27034.hs - + testsuite/tests/th/T27034.stderr - testsuite/tests/th/T8761.stderr - testsuite/tests/th/all.T - + testsuite/tests/typecheck/should_compile/T27664.hs - testsuite/tests/typecheck/should_compile/all.T - + testsuite/tests/warnings/should_compile/T16836a.hs - + testsuite/tests/warnings/should_compile/T16836a.stderr - + testsuite/tests/warnings/should_compile/T16836b.hs - + testsuite/tests/warnings/should_compile/T16836c.hs - + testsuite/tests/warnings/should_compile/T16836c.stderr - + testsuite/tests/warnings/should_compile/T16836d.hs - + testsuite/tests/warnings/should_compile/T16836d.stderr - testsuite/tests/warnings/should_compile/all.T - utils/check-exact/ExactPrint.hs - utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs - utils/haddock/haddock-api/src/Haddock/Convert.hs - utils/haddock/haddock-api/src/Haddock/GhcUtils.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/-/compare/4895ad9a667619d9828a45a2529162… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4895ad9a667619d9828a45a2529162… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/rafl/hpc-instances] 8 commits: X86 NCG: use btr/bts/btc for single-bit operations
by Florian Ragwitz (@rafl) 05 Sep '26

05 Sep '26
Florian Ragwitz pushed to branch wip/rafl/hpc-instances at Glasgow Haskell Compiler / GHC Commits: 2908ab36 by Simon Jakobi at 2026-09-05T07:22:17-04:00 X86 NCG: use btr/bts/btc for single-bit operations Previously the Cmm patterns x & ~(1 << i) x | (1 << i) x ^ (1 << i) compiled to mov/shl/not/and-style sequences of 3-4 instructions. Now they compile to a single btr, bts or btc, matching what C compilers produce. When the bit index is a literal, constant folding has already collapsed these patterns into ones with a literal mask, such as x & 0xfffffeffffffffff for x & ~(1 << 40). Such masks are now also compiled to a bit-test instruction when they don't fit in an imm32 and would otherwise have to be loaded into a register first. For a variable bit index, this applies only when the shift is unchecked (uncheckedShiftL#, Data.Bits.unsafeShiftL): the bounds-checked shiftL used by e.g. the default clearBit/setBit/complementBit implementations wraps the shift in a bounds mask that this optimisation does not see through. With a literal index, the bounds mask is constant-folded away, so the checked operations benefit too. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Fixes #25233. Assisted-by: Claude Fable 5 - - - - - c673ecf0 by Simon Peyton Jones at 2026-09-05T07:22:59-04:00 Move HsStatic free-var test to typechecker A `static` form should have no free *term* variables, but it can have free *type* variables. Alas, the renamer does not really know what is a term variable and what is a type variable, because of required type arguments. This patch moves the test to the typechecker, which does know. Addresses #27664 - - - - - e25a36da by Florian Ragwitz at 2026-09-05T09:41:05-07:00 hpc: Test desired HPC behaviour for class instances - - - - - 0c833d17 by Florian Ragwitz at 2026-09-05T09:41:06-07:00 Extend TcGblEnv with a mapping from instance method Ids to DFunIds We want to use this in HPC to provide better support for instance methods. This is working towards #17155. - - - - - ee6519e6 by Florian Ragwitz at 2026-09-05T09:41:06-07:00 hpc: Do not create top-level boxes for generated instance methods Users care about which of their written methods are or aren't covered, not whether all of the inherited methods are covered as well. Those should be covered where they are implemented. We achieve that by stopping to generate top-level boxes which will often appear as uncovered with no clear indication as to why, and no way to fix other than excercising code the user has not written. Fixes #17155. - - - - - 3a176ec9 by Florian Ragwitz at 2026-09-05T09:41:06-07:00 hpc: Provide coverage information for class instances After fixing #17155, we no longer create top-level boxes for the source spans of instance heads (previously that was the source span used for inherited/generated instance methods). With those boxes gone, we can introduce a new top-level box for each class instance with that instance head source span, and provide more meaningful coverage semantics for it. We make the use of any of the instance's methods (user-written or generated) tick this box, providing the programmer with useful information about whether or not the instance was exercised at run-time, and whether the instance might be unnecessary. - - - - - 97292cee by Florian Ragwitz at 2026-09-05T09:41:06-07:00 hpc: Don't allocate boxes for methodless classes With the plumbing we currently have, these could never be covered, which is not helpful to hpc users. This could be improved upon further. - - - - - 6317c95a by Florian Ragwitz at 2026-09-05T09:41:06-07:00 Add a changelog entry for new HPC features - - - - - 28 changed files: - + changelog.d/T27764 - + changelog.d/hpc-classinsts - + changelog.d/ncg-x86-bit-test-instructions - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToAsm/X86/Ppr.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/HsToCore.hs - compiler/GHC/HsToCore/Ticks.hs - compiler/GHC/Rename/Expr.hs - compiler/GHC/Tc/Gen/Expr.hs - compiler/GHC/Tc/Module.hs - compiler/GHC/Tc/TyCl/Instance.hs - compiler/GHC/Tc/Types.hs - compiler/GHC/Tc/Utils/Monad.hs - + testsuite/tests/codeGen/should_gen_asm/T25233.asm - + testsuite/tests/codeGen/should_gen_asm/T25233.hs - + testsuite/tests/codeGen/should_gen_asm/T25233b.asm - + testsuite/tests/codeGen/should_gen_asm/T25233b.cmm - testsuite/tests/codeGen/should_gen_asm/all.T - + testsuite/tests/hpc/instmeths/instmeths.hs - + testsuite/tests/hpc/instmeths/instmeths.stdout - + testsuite/tests/hpc/instmeths/test.T - testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr - testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr - testsuite/tests/rename/should_fail/T26545.stderr - + testsuite/tests/typecheck/should_compile/T27664.hs - testsuite/tests/typecheck/should_compile/all.T Changes: ===================================== changelog.d/T27764 ===================================== @@ -0,0 +1,8 @@ +section: compiler +synopsis: Fix bug in ``static`` forms +issues: #27664 +mrs: !16624 +description: A ``static`` form should have no free *term* variables, but it + can have free *type* variables. Alas, the renamer does not really know what + is a term variable and what is a type variable, because of required type + arguments. This patch moves the test to the typechecker, which does know. ===================================== changelog.d/hpc-classinsts ===================================== @@ -0,0 +1,23 @@ +section: compiler +synopsis: Improve coverage reporting for class instances and their methods +description: + + Coverage reporting (:ghc-flag:`-fhpc`) now treats class instances more + naturally. + + Compiler-generated instance methods, such as inherited default methods, no + longer receive separate top-level coverage boxes. Explicitly implemented + instance methods retain their own declaration coverage. + + This means that it is no longer necessary to exercise all of a class' methods + in order for it to appear "covered". + + Additionally, top-level coverage boxes are now created for all instances of + classes with methods, and ticked by the use of *any* of the class' methods. + This indicates that an instance was in fact used at run-time. + + Note that classes without any instance methods are currently excluded from + this, and won't have any coverage boxes created. + +mrs: !16632 +issues: #17155 ===================================== changelog.d/ncg-x86-bit-test-instructions ===================================== @@ -0,0 +1,20 @@ +section: compiler +synopsis: The x86 native code generator now uses the bit-test instructions + ``btr``/``bts``/``btc`` to clear, set or complement a single bit +description: + Cmm patterns such as ``x & ~(1 << i)``, ``x | (1 << i)`` and + ``x ^ (1 << i)`` now compile to a single ``btr``/``bts``/``btc`` + instruction instead of a mov/shl/not/and-style sequence, matching what C + compilers produce. The same applies to the literal masks that constant + folding produces from these patterns when ``i`` is constant, in the cases + where the mask doesn't fit in an imm32 operand. + + For a variable bit index this applies only when the shift is unchecked, + as with ``uncheckedShiftL#`` or ``Data.Bits.unsafeShiftL``. The + bounds-checked ``shiftL`` — used, for example, by the default + implementations of ``clearBit``, ``setBit`` and ``complementBit`` — + wraps the shift in a bounds mask that this optimisation does not see + through. With a literal index, the bounds mask is constant-folded away, + so the checked operations benefit too. +mrs: !16311 +issues: #25233 ===================================== compiler/GHC/CmmToAsm/X86/CodeGen.hs ===================================== @@ -1442,6 +1442,22 @@ getRegister' platform is32Bit (CmmMachOp mop [x]) = do -- unary MachOps (PUNPCKLQDQ fmt (OpReg dst) dst) ) +-- Use the bit-test instructions btr/bts/btc for clearing, setting and +-- complementing a single bit: e.g. x .&. complement (1 `shiftL` i) is btr. +-- See Note [Bit-test instructions]. +getRegister' platform is32Bit (CmmMachOp (MO_And w) [x, y]) + | bitTestOpWidthOK is32Bit w + , Just (opnd, ix) <- clearBitArgs_maybe platform w x y + = genBitTestCode (intFormat w) BTR opnd ix +getRegister' platform is32Bit (CmmMachOp (MO_Or w) [x, y]) + | bitTestOpWidthOK is32Bit w + , Just (opnd, ix) <- setBitArgs_maybe platform w x y + = genBitTestCode (intFormat w) BTS opnd ix +getRegister' platform is32Bit (CmmMachOp (MO_Xor w) [x, y]) + | bitTestOpWidthOK is32Bit w + , Just (opnd, ix) <- setBitArgs_maybe platform w x y + = genBitTestCode (intFormat w) BTC opnd ix + getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps sse4_1 <- sse4_1Enabled sse4_2 <- sse4_2Enabled @@ -5883,6 +5899,138 @@ genTrivialCode rep instr a b = do instr b_op dst return (Any rep code) +{- Note [Bit-test instructions] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +x86 has dedicated instructions for clearing (btr), setting (bts) and +complementing (btc) a single bit whose index is given in a register. We use +them for Cmm patterns such as + + x & ~(1 << i) ==> btr i, x (#25233) + +replacing a mov/shl/not/and sequence with a single instruction. The +shift-count register operand of shl is masked modulo the operand width, and +the bit-offset register operand of btr/bts/btc is masked the same way, so +the replacement is faithful even for out-of-range i (where the Cmm shift is +in any case undefined). + +The bit-offset operand of these instructions must be an immediate or a +register. When the bit index is a literal, no shift reaches the NCG: +constant folding has already turned the whole mask into a literal. If that +mask fits in an imm32, we keep the ordinary and/or/xor with an immediate: +it has the same latency and better throughput (more execution ports) than +the bit-test instructions, and at worst two bytes of extra code size for bit +indices 7..30. +But a W64 mask touching the upper bits, e.g. ~(1 << 40), would have to be moved +into a register first. For such masks we recognise the folded literal itself +(exactly one bit clear resp. set) and emit btr/bts/btc with an immediate +bit offset. + +We restrict the pattern to W32 and native-width W64: the instructions do not +exist at width 8, and sub-word Cmm operations at W8/W16 are rare enough that +they are not worth the extra care. +-} + +-- | Match @1 << i@, returning @i@. +-- +-- The returned expression is always at word width ('machOpArgReps' fixes +-- shift amounts at 'wordWidth'). See Note [Bit-test instructions]. +singleBit_maybe :: CmmExpr -> Maybe CmmExpr +singleBit_maybe (CmmMachOp (MO_Shl _) [CmmLit (CmmInt 1 _), i]) = Just i +singleBit_maybe _ = Nothing + +-- | If exactly one bit of @m@, taken at width @w@, is set, return its index. +-- +-- See Note [Bit-test instructions]. +setBitLit_maybe :: Width -> Integer -> Maybe Int +setBitLit_maybe w m + | popCount m' == 1 = Just (countTrailingZeros m') + | otherwise = Nothing + where + -- w <= W64 in this X86-specific code, so a Word64 suffices. + m' = fromInteger (narrowU w m) :: Word64 + +-- | If exactly one bit of @m@, taken at width @w@, is clear, return its +-- index. +-- +-- See Note [Bit-test instructions]. +clearBitLit_maybe :: Width -> Integer -> Maybe Int +clearBitLit_maybe w m = setBitLit_maybe w (complement m) + +bitTestOpWidthOK :: Bool -> Width -> Bool +bitTestOpWidthOK is32Bit w = w == W32 || (w == W64 && not is32Bit) + +-- | The bit-offset operand of a bit-test instruction (btr/bts/btc). +data BitIndex + = BitIndexReg CmmExpr -- ^ variable index, computed into a register + | BitIndexImm Int -- ^ literal index, emitted as an immediate + +-- | Match the operands of a single-bit set or complement operation: one +-- operand is a mask @1 << i@, or a literal with exactly one bit set that +-- does not fit in an imm32. Returns the other operand and the bit index. +-- +-- Both operand orders are matched, e.g. @x | (1 << i)@ and @(1 << i) | x@. +-- +-- See Note [Bit-test instructions]. +setBitArgs_maybe :: Platform -> Width -> CmmExpr -> CmmExpr + -> Maybe (CmmExpr, BitIndex) +setBitArgs_maybe platform w x y = go x y `mplus` go y x + where + go opnd mask + | Just i <- singleBit_maybe mask + = Just (opnd, BitIndexReg i) + | CmmLit lit@(CmmInt m _) <- mask + , Just i <- setBitLit_maybe w m + , not (is32BitLit platform lit) + = Just (opnd, BitIndexImm i) + | otherwise + = Nothing + +-- | As 'setBitArgs_maybe', for a single-bit clear operation: the mask is +-- @~(1 << i)@, or a literal with exactly one bit clear. +clearBitArgs_maybe :: Platform -> Width -> CmmExpr -> CmmExpr + -> Maybe (CmmExpr, BitIndex) +clearBitArgs_maybe platform w x y = go x y `mplus` go y x + where + go opnd mask + | CmmMachOp (MO_Not _) [b] <- mask + , Just i <- singleBit_maybe b + = Just (opnd, BitIndexReg i) + | CmmLit lit@(CmmInt m _) <- mask + , Just i <- clearBitLit_maybe w m + , not (is32BitLit platform lit) + = Just (opnd, BitIndexImm i) + | otherwise + = Nothing + +-- | Generate code for @dst := x@ followed by a bit-test instruction +-- (btr/bts/btc). +-- +-- See Note [Bit-test instructions]. +genBitTestCode :: Format -> (Format -> Operand -> Operand -> Instr) + -> CmmExpr -> BitIndex -> NatM Register +genBitTestCode rep instr x (BitIndexImm i) = do + x_code <- getAnyReg x + let code dst = x_code dst `snocOL` instr rep (OpImm (ImmInt i)) (OpReg dst) + return (Any rep code) +genBitTestCode rep instr x (BitIndexReg i) = do + (i_reg, i_code) <- getNonClobberedReg i + x_code <- getAnyReg x + tmp <- getNewRegNat rep + let + -- As in genTrivialCode, 'i' must stay alive across the computation of + -- 'x' into dst, so save it in a temporary if dst holds 'i'. + code dst + | dst == i_reg = + i_code `appOL` + unitOL (MOV rep (OpReg i_reg) (OpReg tmp)) `appOL` + x_code dst `snocOL` + instr rep (OpReg tmp) (OpReg dst) + | otherwise = + i_code `appOL` + x_code dst `snocOL` + instr rep (OpReg i_reg) (OpReg dst) + return (Any rep code) + regClashesWithOp :: Reg -> Operand -> Bool reg `regClashesWithOp` OpReg reg2 = reg == reg2 reg `regClashesWithOp` OpAddr amode = any (==reg) (addrModeRegs amode) ===================================== compiler/GHC/CmmToAsm/X86/Instr.hs ===================================== @@ -193,6 +193,12 @@ data Instr | SHLD Format Operand{-amount-} Operand Operand | BT Format Imm Operand + -- | Bit test-and-reset + | BTR Format Operand{- ^ bit offset (imm/reg) -} Operand + -- | Bit set + | BTS Format Operand{- ^ bit offset (imm/reg) -} Operand + -- | Bit complement + | BTC Format Operand{- ^ bit offset (imm/reg) -} Operand | NOP @@ -496,6 +502,9 @@ regUsageOfInstr platform instr SHLD fmt imm dst1 dst2 -> usageRMM fmt imm dst1 dst2 SHRD fmt imm dst1 dst2 -> usageRMM fmt imm dst1 dst2 BT fmt _ src -> mkRUR (use_R fmt src []) + BTR fmt off dst -> usageRM fmt off dst + BTS fmt off dst -> usageRM fmt off dst + BTC fmt off dst -> usageRM fmt off dst PUSH fmt op -> mkRUR (use_R fmt op []) POP fmt op -> mkRU [] (def_W fmt op) @@ -830,6 +839,9 @@ patchRegsOfInstr platform instr env SHLD fmt imm dst1 dst2 -> patch2 (SHLD fmt imm) dst1 dst2 SHRD fmt imm dst1 dst2 -> patch2 (SHRD fmt imm) dst1 dst2 BT fmt imm src -> patch1 (BT fmt imm) src + BTR fmt off dst -> patch2 (BTR fmt) off dst + BTS fmt off dst -> patch2 (BTS fmt) off dst + BTC fmt off dst -> patch2 (BTC fmt) off dst TEST fmt src dst -> patch2 (TEST fmt) src dst CMP fmt src dst -> patch2 (CMP fmt) src dst PUSH fmt op -> patch1 (PUSH fmt) op ===================================== compiler/GHC/CmmToAsm/X86/Ppr.hs ===================================== @@ -862,6 +862,15 @@ pprInstr platform i = case i of BT format imm src -> pprFormatImmOp (text "bt") format imm src + BTR format off dst + -> pprFormatOpOp (text "btr") format off dst + + BTS format off dst + -> pprFormatOpOp (text "bts") format off dst + + BTC format off dst + -> pprFormatOpOp (text "btc") format off dst + CMP format src dst | isFloatFormat format -> pprFormatOpOp (text "ucomi") format src dst -- SSE2 | otherwise -> pprFormatOpOp (text "cmp") format src dst ===================================== compiler/GHC/Hs/Expr.hs ===================================== @@ -39,6 +39,7 @@ import GHC.Tc.Types.ErrCtxt import GHC.Types.Id.Info ( RecSelParent ) import GHC.Types.Name import GHC.Types.Name.Reader +import GHC.Types.Name.Set( FreeNames ) import GHC.Types.Basic import GHC.Types.Fixity import GHC.Types.SourceText @@ -363,7 +364,9 @@ type instance XArithSeq GhcTc = PostTcExpr type instance XProc (GhcPass _) = (EpToken "proc", TokRarrow) type instance XStatic GhcPs = EpToken "static" -type instance XStatic GhcRn = NoExtField +type instance XStatic GhcRn = FreeNames + -- Free variables of the body; we can't tell if they are + -- type or term variables until we are typechecking type instance XStatic GhcTc = (Type, HsExpr GhcTc) -- Type of expression, and the (fromStaticPtr function) -- These are stored for convenience as the wiring in ===================================== compiler/GHC/HsToCore.hs ===================================== @@ -147,6 +147,7 @@ deSugar hsc_env tcg_tcs = tcs, tcg_default_exports = defaults, tcg_insts = insts, + tcg_inst_meths = inst_meths, tcg_fam_insts = fam_insts, tcg_complete_matches = complete_matches, tcg_self_boot = self_boot @@ -170,7 +171,8 @@ deSugar hsc_env (hsc_logger hsc_env) (initTicksConfig (hsc_dflags hsc_env)) mod mod_loc - export_set (typeEnvTyCons type_env) binds + export_set (typeEnvTyCons type_env) + insts inst_meths binds else return (binds, Nothing) ; let modBreaks | Just (_, _, breakpointSpecs) <- m_tickInfo ===================================== compiler/GHC/HsToCore/Ticks.hs ===================================== @@ -5,7 +5,7 @@ {- (c) Galois, 2006 (c) University of Glasgow, 2007 -(c) Florian Ragwitz, 2025 +(c) Florian Ragwitz, 2025-2026 -} module GHC.HsToCore.Ticks @@ -24,6 +24,8 @@ import GHC.Unit import GHC.Core.Type import GHC.Core.TyCon +import GHC.Core.InstEnv +import GHC.Core.Class import GHC.Data.Maybe import GHC.Data.FastString @@ -56,6 +58,7 @@ import Data.Foldable (toList) import Trace.Hpc.Mix import Data.Bifunctor (second) +import Data.Functor import Data.List.NonEmpty (NonEmpty (..)) import Data.Set (Set) import qualified Data.Set as Set @@ -100,11 +103,13 @@ addTicksToBinds -- isExportedId doesn't work yet (the desugarer -- hasn't set it), so we have to work from this set. -> [TyCon] -- ^ Type constructors in this module + -> [ClsInst] + -> IdEnv DFunId -> LHsBinds GhcTc -> IO (LHsBinds GhcTc, Maybe (FilePath, SizedSeq Tick, SizedSeq Tick)) addTicksToBinds logger cfg - mod mod_loc exports tyCons binds + mod mod_loc exports tyCons insts inst_meths binds | let passes = ticks_passes cfg , not (null passes) , Just orig_file <- ml_hs_file mod_loc = do @@ -129,8 +134,13 @@ addTicksToBinds logger cfg , this_mod = mod , tickishType = tickish , recSelBinds = emptyVarEnv + , instMeths = inst_meths + , instTicks = emptyVarEnv } - (binds',_,st') = unTM (addTickLHsBinds binds) env st + addTick = do + instTicks <- allocInstTicks insts + withEnv (\e -> e{ instTicks }) $ addTickLHsBinds binds + (binds',_,st') = unTM addTick env st in (binds', st') (binds1,st) = foldr tickPass (binds, initTTState) passes @@ -231,7 +241,7 @@ addTickLHsBind :: LHsBind GhcTc -> TM (LHsBind GhcTc) addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds , abs_exports = abs_exports }))) = - withEnv (add_rec_sels . add_inlines . add_exports) $ do + withEnv (add_inst_meths . add_rec_sels . add_inlines . add_exports) $ do binds' <- addTickLHsBinds binds return $ L pos $ XHsBindsLR $ bind { abs_binds = binds' } where @@ -259,19 +269,24 @@ addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds | ABE{ abe_poly, abe_mono } <- abs_exports , RecSelId{} <- [idDetails abe_poly] ] } + add_inst_meths env = + env{ instMeths = instMeths env `extendVarEnvList` + [ (abe_mono, dfun) + | ABE{ abe_poly, abe_mono } <- abs_exports + , Just dfun <- [lookupVarEnv (instMeths env) abe_poly] ] } + addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches }))) = do let name = getOccString id decl_path <- getPathEntry density <- getDensity + env <- getEnv - inline_ids <- liftM inlines getEnv -- See Note [inline sccs] let inline = isInlinePragma (idInlinePragma id) - || id `elemVarSet` inline_ids + || id `elemVarSet` inlines env -- See Note [inline sccs] - tickish <- tickishType `liftM` getEnv - case tickish of { ProfNotes | inline -> return (L pos funBind); _ -> do + case tickishType env of { ProfNotes | inline -> return (L pos funBind); _ -> do -- See Note [Record-selector ticks] selTicks <- recSelTick id @@ -294,16 +309,24 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches toplev = null decl_path exported = idName id `elemNameSet` exported_names - tick <- if not blackListed && - shouldTickBind density toplev exported simple inline + let generatedInstMeth = density == TickForCoverage + && id `elemVarEnv` instMeths env + && isGenerated (mg_origin (mg_ext matches)) + + tick <- if not generatedInstMeth + && not blackListed + && shouldTickBind density toplev exported simple inline then bindTick density name (locA pos) fvs else return Nothing + instTick <- instMethTick id + let mbCons = maybe Prelude.id (:) return $ L pos $ funBind { fun_matches = mg - , fun_ext = second (tick `mbCons`) (fun_ext funBind) } + , fun_ext = second ((instTick `mbCons`) . (tick `mbCons`)) + (fun_ext funBind) } } } where -- See Note [Record-selector ticks] @@ -1098,6 +1121,8 @@ data TickTransEnv = TTE { fileName :: FastString , this_mod :: Module , tickishType :: TickishType , recSelBinds :: IdEnv DVarSet + , instMeths :: IdEnv DFunId + , instTicks :: IdEnv CoreTickish } -- deriving Show @@ -1238,6 +1263,18 @@ isBlackListed (RealSrcSpan pos _) = TM $ \ env st -> (Set.member pos (blackList isBlackListed GeneratedSrcSpan{} = return False isBlackListed UnhelpfulSpan{} = return False +allocInstTicks :: [ClsInst] -> TM (IdEnv CoreTickish) +allocInstTicks insts = + ifDensity TickForCoverage (mkVarEnv . catMaybes <$> mapM alloc insts) (pure emptyVarEnv) + where + alloc ClsInst{ is_dfun, is_cls } + | null (classMethods is_cls) = pure Nothing + | otherwise = fmap (is_dfun,) <$> allocATickBox (TopLevelBox [getOccString is_dfun]) + False True (getSrcSpan is_dfun) noFVs + +instMethTick :: Id -> TM (Maybe CoreTickish) +instMethTick id = getEnv <&> \e -> lookupVarEnv (instMeths e) id >>= lookupVarEnv (instTicks e) + -- the tick application inherits the source position of its -- expression argument to support nested box allocations allocTickBox :: BoxLabel -> Bool -> Bool -> SrcSpan -> TM (HsExpr GhcTc) ===================================== compiler/GHC/Rename/Expr.hs ===================================== @@ -667,18 +667,7 @@ rnExpr e@(HsStatic _ expr) -- Rename the payload ; (expr',fvs) <- rnLExpr expr - -- Check that the free variables of the static form are top-level defined - -- It's OK to use nonDetEltsUniqSet here as the only side effects of - -- checkClosedInStaticForm are error messages. - -- See (SF2) Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable - ; mapM_ check_fv (nonDetEltsUniqSet fvs) - - ; return (HsStatic noExtField expr', fvs) } - where - check_fv :: Name -> RnM () - -- Check for free vars not defined at top level - check_fv n = unless (isExternalName n) $ - addErrTc (TcRnStaticFormNotClosed n) + ; return (HsStatic fvs expr', fvs) } {- ************************************************************************ ===================================== compiler/GHC/Tc/Gen/Expr.hs ===================================== @@ -602,13 +602,19 @@ tcExpr (HsProc x pat cmd) res_ty -- and wrap (static e) in a call to -- fromStaticPtr :: IsStatic p => StaticPtr a -> p a -tcExpr (HsStatic _ expr) res_ty +tcExpr (HsStatic free_names expr) res_ty = do { res_ty <- expTypeToType res_ty ; (co, (p_ty, expr_ty)) <- matchExpectedAppTy res_ty ; (expr', lie) <- captureConstraints $ addErrCtxt (StaticFormCtxt expr) $ tcCheckPolyExprNC expr expr_ty + -- Check that the free variables of the static form are top-level defined + -- It's OK to use nonDetEltsUniqSet here as the only side effects of + -- checkClosedInStaticForm are error messages. + -- See (SF2) Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable + ; mapM_ check_free_name (nonDetEltsUniqSet free_names) + -- Emit an implication that captures the constraints of `expr`, -- but with a `ic_info` of StaticFormSkol -- See #13499 for an explanation of why this is the right thing to do: @@ -637,6 +643,24 @@ tcExpr (HsStatic _ expr) res_ty HsStatic (static_expr_ty, mkHsWrap wrap fromStaticPtr) expr'' } + where + check_free_name :: Name -> TcM () + -- Check for free /term/ vars not defined at top level + -- We use isExternalName as a proxy for top-level-defined + check_free_name n + = do { mb_thing <- tcLookupLcl_maybe n + ; case mb_thing of + Nothing -> return () -- Imports, tycons, classes allowed + Just (ATcId {}) -> unless (isExternalName n) $ + addErrTc (TcRnStaticFormNotClosed n) + + Just (ATyVar {}) -> return () -- Free type variables are allowed + + -- Not really expecting these, but we'll get an error from + -- elsewhere, so don't produce an error here + Just (ATcTyCon {}) -> return () + Just (APromotionErr {}) -> return () + Just (AGlobal {}) -> return () } tcExpr (HsEmbTy _ _) _ = failWith (TcRnIllegalTypeExpr TypeKeywordSyntax) tcExpr (HsQual _ _ _) _ = failWith (TcRnIllegalTypeExpr ContextArrowSyntax) ===================================== compiler/GHC/Tc/Module.hs ===================================== @@ -1770,7 +1770,7 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls, -- Second pass over class and instance declarations, -- now using the kind-checked decls traceTc "Tc6" empty ; - inst_binds <- tcInstDecls2 (tyClGroupTyClDecls tycl_decls) inst_infos ; + (inst_binds, inst_meths) <- tcInstDecls2 (tyClGroupTyClDecls tycl_decls) inst_infos ; -- Foreign exports traceTc "Tc7" empty ; @@ -1802,8 +1802,9 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls, , tcg_anns = tcg_anns tcg_env ++ annotations , tcg_ann_env = extendAnnEnvList (tcg_ann_env tcg_env) annotations , tcg_fords = tcg_fords tcg_env ++ foe_decls ++ fi_decls - , tcg_dus = tcg_dus tcg_env `plusDU` usesOnly fo_fvs } } ; + , tcg_dus = tcg_dus tcg_env `plusDU` usesOnly fo_fvs -- tcg_dus: see Note [Newtype constructor usage in foreign declarations] + , tcg_inst_meths = tcg_inst_meths tcg_env `plusVarEnv` inst_meths } } ; -- See Note [Newtype constructor usage in foreign declarations] addUsedGREs NoDeprecationWarnings (bagToList fo_gres) ; ===================================== compiler/GHC/Tc/TyCl/Instance.hs ===================================== @@ -1282,7 +1282,7 @@ takes a slightly different approach. ********************************************************************* -} tcInstDecls2 :: [LTyClDecl GhcRn] -> [InstInfo GhcRn] - -> TcM (LHsBinds GhcTc) + -> TcM (LHsBinds GhcTc, IdEnv DFunId) -- (a) From each class declaration, -- generate any default-method bindings -- (b) From each instance decl @@ -1299,11 +1299,11 @@ tcInstDecls2 tycl_decls inst_decls -- Add the default method Ids (again) -- (they were already added in GHC.Tc.TyCl.Utils.tcAddImplicits) -- See Note [Default methods in the type environment] - ; inst_binds_s <- tcExtendGlobalValEnv dm_ids $ - mapM tcInstDecl2 inst_decls + ; (inst_binds_s, inst_meths_s) <- unzip <$> (tcExtendGlobalValEnv dm_ids $ + mapM tcInstDecl2 inst_decls) -- Done - ; return (dm_binds ++ concat inst_binds_s) } + ; return (dm_binds ++ concat inst_binds_s, plusVarEnvList inst_meths_s) } {- Note [Default methods in the type environment] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1319,12 +1319,12 @@ So right here in tcInstDecls2 we must re-extend the type envt with the default method Ids replete with their INLINE pragmas. Urk. -} -tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc) +tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc, IdEnv DFunId) -- Returns a binding for the dfun tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds }) - = recoverM (return emptyLHsBinds) $ - setSrcSpan loc $ - addErrCtxt (instDeclCtxt2 dfun_ty) $ + = recoverM (return (emptyLHsBinds, emptyVarEnv)) $ + setSrcSpan loc $ + addErrCtxt (instDeclCtxt2 dfun_ty) $ do { -- Instantiate the instance decl with skolem constants (skol_info, inst_tyvars, dfun_theta, clas, inst_tys) <- tcSkolDFunType dfun_ty ; dfun_ev_vars <- newEvVars dfun_theta @@ -1342,7 +1342,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds }) -- See Note [Typechecking plan for instance declarations] ; dfun_ev_binds_var <- newTcEvBinds ; let dfun_ev_binds = TcEvBinds dfun_ev_binds_var - ; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics)) + ; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics, meth_ids)) <- pushTcLevelM $ do { (sc_ids, sc_binds, sc_implics) <- tcSuperClasses skol_info dfun_id clas inst_tyvars @@ -1356,7 +1356,8 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds }) ; return ( sc_ids ++ meth_ids , sc_binds ++ meth_binds - , sc_implics `unionBags` meth_implics ) } + , sc_implics `unionBags` meth_implics + , meth_ids ) } ; imp <- newImplication ; emitImplication $ @@ -1413,7 +1414,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds }) , abs_binds = [dict_bind] , abs_sig = True } - ; return (L loc' main_bind : sc_meth_binds) + ; return (L loc' main_bind : sc_meth_binds, mkVarEnv $ (,dfun_id) <$> meth_ids) } where dfun_id = instanceDFunId ispec ===================================== compiler/GHC/Tc/Types.hs ===================================== @@ -157,6 +157,7 @@ import GHC.Types.Name.Env import GHC.Types.Name.Set import GHC.Types.Avail import GHC.Types.Var +import GHC.Types.Var.Env import GHC.Types.TypeEnv import GHC.Types.SourceFile import GHC.Types.SrcLoc @@ -530,6 +531,8 @@ data TcGblEnv -- NB. BangPattern is to fix a leak, see #15111 tcg_fam_inst_env :: !FamInstEnv, -- ^ Ditto for family instances -- NB. BangPattern is to fix a leak, see #15111 + tcg_inst_meths :: IdEnv DFunId, + -- ^ Maps instance method Ids to the DFunId of the instance they belong to. tcg_ann_env :: AnnEnv, -- ^ And for annotations tcg_complete_match_env :: CompleteMatches, -- ^ The complete matches for all /home-package/ modules; ===================================== compiler/GHC/Tc/Utils/Monad.hs ===================================== @@ -409,6 +409,7 @@ initTcGblEnv hsc_env hsc_src keep_rn_syntax mod loc = , tcg_knot_vars = hsc_type_env_vars hsc_env , tcg_known_key_maps = known_key_maps_var , tcg_inst_env = emptyInstEnv + , tcg_inst_meths = emptyVarEnv , tcg_fam_inst_env = emptyFamInstEnv , tcg_ann_env = emptyAnnEnv , tcg_complete_match_env = [] ===================================== testsuite/tests/codeGen/should_gen_asm/T25233.asm ===================================== @@ -0,0 +1,9 @@ +btrq +btsq +btcq +btrl +btsl +btcl +btrq $40, +btsq $40, +btcq $40, ===================================== testsuite/tests/codeGen/should_gen_asm/T25233.hs ===================================== @@ -0,0 +1,39 @@ +{-# LANGUAGE MagicHash #-} + +-- Check that clearing/setting/complementing a single, variable bit +-- uses the btr/bts/btc instructions (#25233). +module T25233 where + +import GHC.Exts + +myClearBit :: Word# -> Int# -> Word# +myClearBit x i = x `and#` not# (1## `uncheckedShiftL#` i) + +mySetBit :: Word# -> Int# -> Word# +mySetBit x i = x `or#` (1## `uncheckedShiftL#` i) + +myComplementBit :: Word# -> Int# -> Word# +myComplementBit x i = x `xor#` (1## `uncheckedShiftL#` i) + +myClearBit32 :: Word32# -> Int# -> Word32# +myClearBit32 x i = + x `andWord32#` notWord32# (wordToWord32# 1## `uncheckedShiftLWord32#` i) + +mySetBit32 :: Word32# -> Int# -> Word32# +mySetBit32 x i = x `orWord32#` (wordToWord32# 1## `uncheckedShiftLWord32#` i) + +myComplementBit32 :: Word32# -> Int# -> Word32# +myComplementBit32 x i = + x `xorWord32#` (wordToWord32# 1## `uncheckedShiftLWord32#` i) + +-- With a constant bit index >= 32, the mask constant-folds to a literal +-- that does not fit in an imm32, so a bit-test instruction with an +-- immediate offset is used. +myClearBit40 :: Word# -> Word# +myClearBit40 x = x `and#` not# (1## `uncheckedShiftL#` 40#) + +mySetBit40 :: Word# -> Word# +mySetBit40 x = x `or#` (1## `uncheckedShiftL#` 40#) + +myComplementBit40 :: Word# -> Word# +myComplementBit40 x = x `xor#` (1## `uncheckedShiftL#` 40#) ===================================== testsuite/tests/codeGen/should_gen_asm/T25233b.asm ===================================== @@ -0,0 +1,6 @@ +btrq % +btsq % +btcq % +btrq $40, +btsq $40, +btcq $40, ===================================== testsuite/tests/codeGen/should_gen_asm/T25233b.cmm ===================================== @@ -0,0 +1,27 @@ +#include "Cmm.h" + +// Single-bit masks written on the left of the operator (#25233). + +clearBitVar (W_ x, W_ i) { + return ((~((1 :: bits64) << i)) & x); +} + +setBitVar (W_ x, W_ i) { + return (((1 :: bits64) << i) | x); +} + +complementBitVar (W_ x, W_ i) { + return (((1 :: bits64) << i) ^ x); +} + +clearBit40 (W_ x) { + return ((0xFFFFFEFFFFFFFFFF :: bits64) & x); +} + +setBit40 (W_ x) { + return ((0x10000000000 :: bits64) | x); +} + +complementBit40 (W_ x) { + return ((0x10000000000 :: bits64) ^ x); +} ===================================== testsuite/tests/codeGen/should_gen_asm/all.T ===================================== @@ -23,6 +23,10 @@ test('avx512-int64-minmax', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512vl']) test('avx512-word64-minmax', [unless(arch('x86_64'), skip), when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512vl']) +test('T25233', [unless(arch('x86_64'), skip), + when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O']) +test('T25233b', [unless(arch('x86_64'), skip), + when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, '']) is_aarch64_codegen = [ unless(arch('aarch64'), skip), when(unregisterised(), skip), ===================================== testsuite/tests/hpc/instmeths/instmeths.hs ===================================== @@ -0,0 +1,57 @@ +import Data.List +import Data.Maybe +import Trace.Hpc.Mix +import Trace.Hpc.Reflect +import Trace.Hpc.Tix +import Trace.Hpc.Util + +class Foo a where + defMeth, defMeth', reqMeth :: a -> String + defMeth = const "class default" + defMeth' = const "class default" + +newtype T a = T a deriving (Show, Eq, Functor) +instance Foo (T a) where + reqMeth = const "Foo (T a) instance" + +newtype T' a = T' a + +instance Foo (T' a) where + reqMeth = const "Foo (T' a) instance" + defMeth = const "Foo (T' a) instance" + +-- no method use could "cover" this instance, so we (for now) omit the top-level box for it +class Marker a +instance Marker (T Bool) + +interesting :: (Int, MixEntry) -> Maybe (Int, HpcPos, String) +interesting (n, (pos, TopLevelBox [name])) | isInteresting name = Just (n, pos, name) + where isInteresting = (||) <$> isInst <*> isMeth + isInst = ("$f" `isPrefixOf`) + isMeth = (||) <$> (`elem` ["(==)", "(/=)", "show", "showList", "showsPrec", "fmap", "(<$)"]) + <*> ("Meth" `isSubsequenceOf`) +interesting _ = Nothing + +-- candidate for HPC.Utils, maybe? +sourceAt :: String -> HpcPos -> String +sourceAt src pos + | l1 == l2 = take (c2 - c1 + 1) . drop (c1 - 1) $ ls !! (l1 - 1) + | otherwise = intercalate "\n" $ first : (middle ++ [last]) + where + (l1, c1, l2, c2) = fromHpcPos pos + ls = lines src + first = drop (c1 - 1) $ ls !! (l1 - 1) + middle = take (l2 - l1 - 1) $ drop l1 ls + last = take c2 $ ls !! (l2 - 1) + +main :: IO () +main = do + print (T 23 == (succ <$> T 22)) -- tick Eq and Functor by using any of their methods + print (reqMeth (T' 1)) -- tick `Foo (T' a)` and that instance's `reqMeth` + + Mix source _ _ _ mixEntries <- readMix [".hpc"] (Left "Main") + src <- readFileUtf8 source + let boxes = mapMaybe interesting $ zip [0 ..] mixEntries + Tix [TixModule "Main" _ _ counts] <- examineTix + mapM_ print [ (counts !! n, path, sourceAt src pos) + | (n, pos, path) <- sortOn (\(_, _, s) -> s) boxes ] ===================================== testsuite/tests/hpc/instmeths/instmeths.stdout ===================================== @@ -0,0 +1,12 @@ +True +"Foo (T' a) instance" +(1,"$fEqT","Eq") +(0,"$fFooT","Foo (T a)") +(1,"$fFooT'","Foo (T' a)") +(1,"$fFunctorT","Functor") +(0,"$fShowT","Show") +(0,"defMeth","defMeth = const \"class default\"") +(0,"defMeth","defMeth = const \"Foo (T' a) instance\"") +(0,"defMeth'","defMeth' = const \"class default\"") +(0,"reqMeth","reqMeth = const \"Foo (T a) instance\"") +(1,"reqMeth","reqMeth = const \"Foo (T' a) instance\"") ===================================== testsuite/tests/hpc/instmeths/test.T ===================================== @@ -0,0 +1,5 @@ +setTestOpts([omit_ghci, when(fast(), skip), js_skip]) + +test('instmeths', + [ignore_extension], + compile_and_run, ['-fhpc']) ===================================== testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr ===================================== @@ -1,3 +1,5 @@ RnStaticPointersFail01.hs:5:7: error: [GHC-88431] - ‘x’ is used in a static form but it is not defined at top level + • ‘x’ is used in a static form but it is not defined at top level + • In the expression: static x + In an equation for ‘f’: f x = static x ===================================== testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr ===================================== @@ -1,12 +1,34 @@ RnStaticPointersFail03.hs:8:7: error: [GHC-88431] - ‘x’ is used in a static form but it is not defined at top level + • ‘x’ is used in a static form but it is not defined at top level + • In the expression: static (x . id) + In an equation for ‘f’: f x = static (x . id) RnStaticPointersFail03.hs:10:8: error: [GHC-88431] - ‘k’ is used in a static form but it is not defined at top level + • ‘k’ is used in a static form but it is not defined at top level + • In the expression: static (k . id) + In an equation for ‘f0’: + f0 x + = static (k . id) + where + k = const (const () x) RnStaticPointersFail03.hs:14:8: error: [GHC-88431] - ‘k’ is used in a static form but it is not defined at top level + • ‘k’ is used in a static form but it is not defined at top level + • In the expression: static (k . id) + In an equation for ‘f1’: + f1 x + = static (k . id) + where + k = id RnStaticPointersFail03.hs:19:15: error: [GHC-88431] - ‘g’ is used in a static form but it is not defined at top level + • ‘g’ is used in a static form but it is not defined at top level + • In the first argument of ‘const’, namely ‘(static (g undefined))’ + In the expression: const (static (g undefined)) (h x) + In an equation for ‘f2’: + f2 x + = const (static (g undefined)) (h x) + where + g = h + h = typeOf ===================================== testsuite/tests/rename/should_fail/T26545.stderr ===================================== @@ -1,3 +1,6 @@ T26545.hs:12:23: error: [GHC-88431] - ‘v’ is used in a static form but it is not defined at top level + • ‘v’ is used in a static form but it is not defined at top level + • In the expression: static (I# (v +# 1#)) + In the expression: let v = f 3# in static (I# (v +# 1#)) + In an equation for ‘h’: h x = let v = f 3# in static (I# (v +# 1#)) ===================================== testsuite/tests/typecheck/should_compile/T27664.hs ===================================== @@ -0,0 +1,11 @@ +{-# LANGUAGE StaticPointers, ScopedTypeVariables #-} +module Repro where + +import Data.Typeable +import GHC.StaticPtr + +f1 :: forall a. Typeable a => StaticPtr (a -> a) +f1 = static (id :: a -> a) + +f2 :: forall a. Typeable a => StaticPtr (a -> a) +f2 = static (id) :: StaticPtr (a->a) ===================================== testsuite/tests/typecheck/should_compile/all.T ===================================== @@ -969,3 +969,4 @@ test('ExpansionQLIm', normal, compile, ['']) test('T23135', normal, compile, ['']) test('LazyFieldAnnotations', normal, compile, ['']) test('T27557', normal, compile, ['']) +test('T27664', normal, compile, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c5f3a8570a0b3c1c2c54f09e884c21… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c5f3a8570a0b3c1c2c54f09e884c21… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 6 commits: X86 NCG: use btr/bts/btc for single-bit operations
by Marge Bot (@marge-bot) 05 Sep '26

05 Sep '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 2908ab36 by Simon Jakobi at 2026-09-05T07:22:17-04:00 X86 NCG: use btr/bts/btc for single-bit operations Previously the Cmm patterns x & ~(1 << i) x | (1 << i) x ^ (1 << i) compiled to mov/shl/not/and-style sequences of 3-4 instructions. Now they compile to a single btr, bts or btc, matching what C compilers produce. When the bit index is a literal, constant folding has already collapsed these patterns into ones with a literal mask, such as x & 0xfffffeffffffffff for x & ~(1 << 40). Such masks are now also compiled to a bit-test instruction when they don't fit in an imm32 and would otherwise have to be loaded into a register first. For a variable bit index, this applies only when the shift is unchecked (uncheckedShiftL#, Data.Bits.unsafeShiftL): the bounds-checked shiftL used by e.g. the default clearBit/setBit/complementBit implementations wraps the shift in a bounds mask that this optimisation does not see through. With a literal index, the bounds mask is constant-folded away, so the checked operations benefit too. See Note [Bit-test instructions] in GHC.CmmToAsm.X86.CodeGen. Fixes #25233. Assisted-by: Claude Fable 5 - - - - - c673ecf0 by Simon Peyton Jones at 2026-09-05T07:22:59-04:00 Move HsStatic free-var test to typechecker A `static` form should have no free *term* variables, but it can have free *type* variables. Alas, the renamer does not really know what is a term variable and what is a type variable, because of required type arguments. This patch moves the test to the typechecker, which does know. Addresses #27664 - - - - - 92b878ce by sheaf at 2026-09-05T07:55:33-04:00 Windows: enforce path convention in ./configure As detailed in Note [MSYS paths] in Hadrian.Utilities, the standing convention (using Windows-style paths with forward slashes) is now enforced in ./configure instead of within Hadrian, removing the need for 'cygpath' calls within Hadrian. Fixes #26683 - - - - - b3d9abd1 by sheaf at 2026-09-05T07:55:33-04:00 Hadrian: introduce ExeSpawnPath Specific details about the filepath used to specify the executable to spawn with CreateProcess matters on Windows: whether we use forward or backward slashes, a leading ./, or an absolute path changes how the executable is found. This commit introduces 'ExeSpawnPath' which is a path that is guaranteed to be found when spawning a process. All command invocations now go through this type to ensure the path has been properly sanitised. See Note [NeedCurrentDirectoryForExePath] in Hadrian.Utilities. The same treatment is applied to hsc2hs. Updates hsc2hs submodule. - - - - - d0d07cf1 by sheaf at 2026-09-05T07:55:37-04:00 Preserve tick ordering in 'tickTickedExpr' 'GHC.Core.Utils.tickTickedExpr' tries to combine a tick 't1' into an existing stack of ticks 't2s'. There are two situations: 1. 't1' is subsumed by a tick in 't2s': drop it. 2. A tick in 't2s' is subsumed by 't1', say 't2'. This commit ensures that in case (2) we keep 't1' on the outside instead of replacing 't2' at its position in the stack. This avoids re-ordering source notes (which was the cause of #27749). This fixes a regression introduced in 2dadf3b0d05. Fixes #27749 - - - - - dd0ec867 by sheaf at 2026-09-05T07:55:37-04:00 Consistently prefer local source note ticks GHC.Cmm.DebugBlock.cmmDebugGen (DWARF annotations) and GHC.Stg.Debug.quickSourcePos (-finfo-table-map) both contained logic to prioritise source note ticks from the current module. This commit commons up this logic and propagates it to a third consumer: IPE stack frames, in GHC.Driver.GenerateCgIPEStub. See the new function GHC.Types.Tickish.bestSourceNote. - - - - - 53 changed files: - + changelog.d/T27749 - + changelog.d/T27764 - + changelog.d/ncg-x86-bit-test-instructions - compiler/GHC/Cmm/DebugBlock.hs - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToAsm/X86/Ppr.hs - compiler/GHC/Core/Utils.hs - compiler/GHC/Driver/GenerateCgIPEStub.hs - compiler/GHC/Driver/Main/Compile.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/Rename/Expr.hs - compiler/GHC/Stg/Debug.hs - compiler/GHC/Tc/Gen/Expr.hs - compiler/GHC/Types/Tickish.hs - configure.ac - hadrian/src/Base.hs - hadrian/src/Builder.hs - hadrian/src/Hadrian/Builder.hs - hadrian/src/Hadrian/Builder/Ar.hs - hadrian/src/Hadrian/Oracles/Path.hs - hadrian/src/Hadrian/Utilities.hs - hadrian/src/Oracles/Setting.hs - hadrian/src/Oracles/TestSettings.hs - hadrian/src/Rules/BinaryDist.hs - hadrian/src/Rules/Changelog.hs - hadrian/src/Rules/Codes.hs - hadrian/src/Rules/Lint.hs - hadrian/src/Rules/Nofib.hs - hadrian/src/Rules/Test.hs - m4/find_python.m4 - + m4/fp_canonicalise_win_path.m4 - m4/fp_find_nm.m4 - m4/fp_find_root.m4 - m4/fp_prog_ar.m4 - m4/fp_prog_ar_args.m4 - m4/fp_prog_sh.m4 - m4/fptools_alex.m4 - m4/fptools_happy.m4 - + testsuite/tests/codeGen/should_gen_asm/T25233.asm - + testsuite/tests/codeGen/should_gen_asm/T25233.hs - + testsuite/tests/codeGen/should_gen_asm/T25233b.asm - + testsuite/tests/codeGen/should_gen_asm/T25233b.cmm - testsuite/tests/codeGen/should_gen_asm/all.T - testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr - testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr - testsuite/tests/rename/should_fail/T26545.stderr - + testsuite/tests/simplCore/should_compile/T27749.hs - + testsuite/tests/simplCore/should_compile/T27749.stderr - testsuite/tests/simplCore/should_compile/all.T - + testsuite/tests/typecheck/should_compile/T27664.hs - testsuite/tests/typecheck/should_compile/all.T - utils/hsc2hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c396d8cbb1828c84ce08376c8d3f6d… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c396d8cbb1828c84ce08376c8d3f6d… You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • ...
  • 61
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.