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

  • 1 participants
  • 10704 discussions
[Git][ghc/ghc][wip/davide/ghc-internal-def] Hadrian: create a ghc-internal .def file per ghc-internal dll
by David Eichmann (@DavidEichmann) 20 May '26

20 May '26
David Eichmann pushed to branch wip/davide/ghc-internal-def at Glasgow Haskell Compiler / GHC Commits: e5dcd268 by David Eichmann at 2026-05-20T16:08:07+01:00 Hadrian: create a ghc-internal .def file per ghc-internal dll The .def file generated from rts/win32/libHSghc-internal.def.in contains the name of the ghc-internal dll, but that differs based on if the dll is inplace/final and what way it is. Previously, this was not accounted for and inconsistent dlls names where used. That led to failure when loading dlls are runtime in experiments with windows dynamic linking. - - - - - 5 changed files: - hadrian/src/Rules/Generate.hs - hadrian/src/Rules/Library.hs - hadrian/src/Rules/Rts.hs - rts/.gitignore - rts/win32/libHSghc-internal.def.in Changes: ===================================== hadrian/src/Rules/Generate.hs ===================================== @@ -377,7 +377,6 @@ templateRules = do , interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1 , interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2 ] - templateRule "rts/win32/libHSghc-internal.def" projectVersion templateRule "docs/index.html" $ packageUnitIds Stage1 templateRule "docs/users_guide/ghc_config.py" $ mconcat [ projectVersion ===================================== hadrian/src/Rules/Library.hs ===================================== @@ -203,10 +203,21 @@ extraObjects context | package context == rts = do target <- interpretInContext context getStagedTarget - builddir <- buildPath context - return [ builddir -/- "libHSghc-internal.dll.a" - | archOS_OS (tgtArchOs target) == OSMinGW32 - , Dynamic `wayUnit` way context ] + if not (archOS_OS (tgtArchOs target) == OSMinGW32 + && Dynamic `wayUnit` way context) + then return [] + else do + -- Find the ghc-internal library file name + let way' = if Profiling `wayUnit` way context then profilingDynamic else dynamic + ghcInternalDllName <- takeFileName <$> pkgLibraryFile (Context { + stage = stage context, + way = way', + iplace = iplace context, + package = ghcInternal + }) + + builddir <- buildPath context + return [ builddir -/- ghcInternalDllName <> ".a"] | otherwise = return [] ===================================== hadrian/src/Rules/Rts.hs ===================================== @@ -29,11 +29,19 @@ rtsRules = priority 3 $ do -- to be linked into the rts dll. forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do let buildPath = root -/- buildDir (rtsContext stage) - buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib + buildPath -/- "libHSghc-internal-*.def" %> buildGhcInternalImportDef + buildPath -/- "libHSghc-internal-*.dll.a" %> buildGhcInternalImportLib + +buildGhcInternalImportDef :: FilePath -> Action () +buildGhcInternalImportDef target = do + templateIn <- readFile' "rts/win32/libHSghc-internal.def.in" + let dllName = (dropExtension (takeFileName target)) <.> "dll" + templateOut = replace "@GhcInternalDll@" dllName templateIn + writeFile' target templateOut buildGhcInternalImportLib :: FilePath -> Action () buildGhcInternalImportLib target = do - let input = "rts/win32/libHSghc-internal.def" + let input = (dropExtension (dropExtension target)) <.> "def" -- the .def file output = target -- the .dll.a import lib need [input] runBuilder Dlltool ["-d", input, "-l", output] [input] [output] ===================================== rts/.gitignore ===================================== @@ -20,4 +20,3 @@ /ghcautoconf.h.autoconf.in /ghcautoconf.h.autoconf /include/ghcautoconf.h -/win32/libHSghc-internal.def ===================================== rts/win32/libHSghc-internal.def.in ===================================== @@ -1,4 +1,4 @@ -LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll +LIBRARY @GhcInternalDll@ EXPORTS init_ghc_hs_iface View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e5dcd268ddf0449496b789d1e8d5f35… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e5dcd268ddf0449496b789d1e8d5f35… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/davide/ghc-internal-def] Hadrian: create a ghc-internal .def file per ghc-internal dll
by David Eichmann (@DavidEichmann) 20 May '26

20 May '26
David Eichmann pushed to branch wip/davide/ghc-internal-def at Glasgow Haskell Compiler / GHC Commits: bbee1693 by David Eichmann at 2026-05-20T15:48:40+01:00 Hadrian: create a ghc-internal .def file per ghc-internal dll The .def file generated from rts/win32/libHSghc-internal.def.in contains the name of the ghc-internal dll, but that differs based on if the dll is inplace/final and what way it is. Previously, this was not accounted for and inconsistent dlls names where used. That led to failure when loading dlls are runtime in experiments with windows dynamic linking. - - - - - 5 changed files: - hadrian/src/Rules/Generate.hs - hadrian/src/Rules/Library.hs - hadrian/src/Rules/Rts.hs - rts/.gitignore - rts/win32/libHSghc-internal.def.in Changes: ===================================== hadrian/src/Rules/Generate.hs ===================================== @@ -377,7 +377,6 @@ templateRules = do , interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1 , interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2 ] - templateRule "rts/win32/libHSghc-internal.def" projectVersion templateRule "docs/index.html" $ packageUnitIds Stage1 templateRule "docs/users_guide/ghc_config.py" $ mconcat [ projectVersion ===================================== hadrian/src/Rules/Library.hs ===================================== @@ -203,10 +203,21 @@ extraObjects context | package context == rts = do target <- interpretInContext context getStagedTarget - builddir <- buildPath context - return [ builddir -/- "libHSghc-internal.dll.a" - | archOS_OS (tgtArchOs target) == OSMinGW32 - , Dynamic `wayUnit` way context ] + if not (archOS_OS (tgtArchOs target) == OSMinGW32 + && Dynamic `wayUnit` way context) + then return [] + else do + -- Find the ghc-internal library file name + let way' = if Profiling `wayUnit` way context then profilingDynamic else dynamic + ghcInternalDllName <- pkgLibraryFile (Context { + stage = stage context, + way = way', + iplace = iplace context, + package = ghcInternal + }) + + builddir <- buildPath context + return [ builddir -/- ghcInternalDllName <> ".a"] | otherwise = return [] ===================================== hadrian/src/Rules/Rts.hs ===================================== @@ -29,11 +29,19 @@ rtsRules = priority 3 $ do -- to be linked into the rts dll. forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do let buildPath = root -/- buildDir (rtsContext stage) - buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib + buildPath -/- "libHSghc-internal-*.def" %> buildGhcInternalImportDef + buildPath -/- "libHSghc-internal-*.dll.a" %> buildGhcInternalImportLib + +buildGhcInternalImportDef :: FilePath -> Action () +buildGhcInternalImportDef target = do + templateIn <- readFile' "rts/win32/libHSghc-internal.def.in" + let dllName = (dropExtension (takeFileName target)) <.> "dll" + templateOut = replace "@GhcInternalDll@" dllName templateIn + writeFile' target templateOut buildGhcInternalImportLib :: FilePath -> Action () buildGhcInternalImportLib target = do - let input = "rts/win32/libHSghc-internal.def" + let input = (dropExtension (dropExtension target)) <.> "def" -- the .def file output = target -- the .dll.a import lib need [input] runBuilder Dlltool ["-d", input, "-l", output] [input] [output] ===================================== rts/.gitignore ===================================== @@ -20,4 +20,3 @@ /ghcautoconf.h.autoconf.in /ghcautoconf.h.autoconf /include/ghcautoconf.h -/win32/libHSghc-internal.def ===================================== rts/win32/libHSghc-internal.def.in ===================================== @@ -1,4 +1,4 @@ -LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll +LIBRARY @GhcInternalDll@ EXPORTS init_ghc_hs_iface View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bbee16932f3a66a3b02d754b24d7067… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bbee16932f3a66a3b02d754b24d7067… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/mangoiv/ghc-9.12-bp] driver: recognise .dyn_o as a valid object file to link if passed on the command line.
by Magnus (@MangoIV) 20 May '26

20 May '26
Magnus pushed to branch wip/mangoiv/ghc-9.12-bp at Glasgow Haskell Compiler / GHC Commits: 213aa422 by Zubin Duggal at 2026-05-20T15:42:11+02:00 driver: recognise .dyn_o as a valid object file to link if passed on the command line. This allows plugins compiled with this suffix to run. Fixes #24486 (cherry picked from commit bc4b44870d096d43e8cbc530da1fd613d9e4514f) - - - - - 9 changed files: - compiler/GHC/Driver/Phases.hs - testsuite/tests/plugins/Makefile - + testsuite/tests/plugins/T24486-plugin/Makefile - + testsuite/tests/plugins/T24486-plugin/Setup.hs - + testsuite/tests/plugins/T24486-plugin/T24486-plugin.cabal - + testsuite/tests/plugins/T24486-plugin/T24486_Plugin.hs - + testsuite/tests/plugins/T24486.hs - + testsuite/tests/plugins/T24486_Helper.hs - testsuite/tests/plugins/all.T Changes: ===================================== compiler/GHC/Driver/Phases.hs ===================================== @@ -256,7 +256,7 @@ objish_suffixes :: Platform -> [String] -- the GHC-compiled code will run objish_suffixes platform = case platformOS platform of OSMinGW32 -> [ "o", "O", "obj", "OBJ" ] - _ -> [ "o" ] + _ -> [ "o", "dyn_o"] dynlib_suffixes :: Platform -> [String] dynlib_suffixes platform = case platformOS platform of ===================================== testsuite/tests/plugins/Makefile ===================================== @@ -234,3 +234,14 @@ test-late-plugin: ContainsLateBinding=$$(echo $$SHOW_IFACE | grep -o 222222) ; \ echo "$$ContainsLateBinding" ; \ [ "$$ContainsEarlyBinding" = "111111" ] && [ "$$ContainLateBinding" = "" ] + +.PHONY: T21730 +T21730: + "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) -v0 T21730.hs -package-db T21730-plugin/pkg.T21730-plugin/local.package.conf + +# Test that .dyn_o files are accepted as valid object files on the command line +# without producing "ignoring unrecognised input" warnings (#24486) +.PHONY: T24486 +T24486: + "$(TEST_HC)" $(TEST_HC_OPTS) -v0 -c T24486_Helper.hs -osuf dyn_o + "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) -v0 T24486.hs T24486_Helper.dyn_o -package-db T24486-plugin/pkg.T24486-plugin/local.package.conf -fplugin T24486_Plugin -plugin-package T24486-plugin ===================================== testsuite/tests/plugins/T24486-plugin/Makefile ===================================== @@ -0,0 +1,18 @@ +TOP=../../.. +include $(TOP)/mk/boilerplate.mk +include $(TOP)/mk/test.mk + +clean.%: + rm -rf pkg.$* + +HERE := $(abspath .) +$(eval $(call canonicalise,HERE)) + +package.%: + $(MAKE) -s --no-print-directory clean.$* + mkdir pkg.$* + "$(TEST_HC)" -outputdir pkg.$* --make -v0 -o pkg.$*/setup Setup.hs + "$(GHC_PKG)" init pkg.$*/local.package.conf + pkg.$*/setup configure --distdir pkg.$*/dist -v0 $(CABAL_PLUGIN_BUILD) --prefix="$(HERE)/pkg.$*/install" --with-compiler="$(TEST_HC)" --with-hc-pkg="$(GHC_PKG)" --package-db=pkg.$*/local.package.conf $(if $(findstring YES,$(HAVE_PROFILING)), --enable-library-profiling) + pkg.$*/setup build --distdir pkg.$*/dist -v0 + pkg.$*/setup install --distdir pkg.$*/dist -v0 ===================================== testsuite/tests/plugins/T24486-plugin/Setup.hs ===================================== @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain ===================================== testsuite/tests/plugins/T24486-plugin/T24486-plugin.cabal ===================================== @@ -0,0 +1,9 @@ +Name: T24486-plugin +Version: 0.1 +Synopsis: For testing +Cabal-Version: >= 1.2 +Build-Type: Simple + +Library + Build-Depends: base, ghc + Exposed-Modules: T24486_Plugin ===================================== testsuite/tests/plugins/T24486-plugin/T24486_Plugin.hs ===================================== @@ -0,0 +1,6 @@ +module T24486_Plugin (plugin) where + +import GHC.Plugins + +plugin :: Plugin +plugin = defaultPlugin ===================================== testsuite/tests/plugins/T24486.hs ===================================== @@ -0,0 +1,4 @@ +module Main where + +main :: IO () +main = return () ===================================== testsuite/tests/plugins/T24486_Helper.hs ===================================== @@ -0,0 +1,4 @@ +module T24486_Helper where + +helper :: Int +helper = 42 ===================================== testsuite/tests/plugins/all.T ===================================== @@ -376,3 +376,10 @@ test('test-late-plugin', [extra_files(['late-plugin/LatePlugin.hs']), ignore_stdout], makefile_test, []) + +test('T24486', + [extra_files(['T24486-plugin/', 'T24486_Helper.hs']), + when(opsys('mingw32'), skip), + pre_cmd('$MAKE -s --no-print-directory -C T24486-plugin package.T24486-plugin TOP={top}') + ], + makefile_test, []) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/213aa422f3c3046f606d88f5b532f8a… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/213aa422f3c3046f606d88f5b532f8a… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/mangoiv/ghc-9.12-bp] 2 commits: configure: Accept happy-2.2
by Magnus (@MangoIV) 20 May '26

20 May '26
Magnus pushed to branch wip/mangoiv/ghc-9.12-bp at Glasgow Haskell Compiler / GHC Commits: 9ba34598 by Brian J. Cardiff at 2026-05-20T15:17:39+02:00 configure: Accept happy-2.2 In Jan 2026 happy-2.2 was released. The most sensible change is https://github.com/haskell/happy/issues/335 which didn't trigger in a fresh build (cherry picked from commit 4f2840f2bb729ef1a6660f9f5c46906b7b838147) - - - - - 4a9baf14 by sheaf at 2026-05-20T15:28:16+02:00 Careful with ticked join points in mergeCaseAlts This commit backports the fix to GHC.Core.Utils.mergeCaseAlts that was carried out in f726fcc4fb0b59f8ad2e2fa80f1b03efdaf73c30. That is, this commit addresses the regression that was introduced by e026bdf275e287005f2c2e534d3ba034ebf11c01, which allowed mergeCaseAlts to move ticks in between a join point and one of its jumps, which results in disaster (see #26929 but also #26642, #26693). See (MC6) in Note [Merge Nested Cases] for a detailed explanation. (cherry picked from commit 08bc245be70d95801bc1138804ed1de9474fbdc0) (cherry picked from commit 974586eb5b6a924e8ce3ea8c4b2180ea9c0f3801) - - - - - 4 changed files: - compiler/GHC/Core/Utils.hs - m4/fptools_happy.m4 - + testsuite/tests/simplCore/should_compile/T26642.hs - testsuite/tests/simplCore/should_compile/all.T Changes: ===================================== compiler/GHC/Core/Utils.hs ===================================== @@ -709,11 +709,16 @@ mergeCaseAlts outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts) | otherwise = Nothing - -- We don't want ticks to get in the way; just push them inwards. - -- (This happens when you add SourceTicks e.g. GHC.Num.Integer.integerLt#) + -- Push ticks **inwards** (when possible). + -- See (MC5) in Note [Merge Nested Cases]. go (Tick t body) - = do { (joins, alts) <- go body - ; return (joins, [Alt con bs (Tick t rhs) | Alt con bs rhs <- alts]) } + = do { (joins, alts) <- go body -- (MC4): any join points inside are floated out of the tick. + + -- Abort if this would put a non-soft-scope tick in between + -- a join point binding and its jumps. See (MC6). + ; guard $ null joins || t `tickishScopesLike` SoftScope + ; return (joins, [Alt con bs (mkTick t rhs) | Alt con bs rhs <- alts]) + } go _ = Nothing @@ -924,9 +929,70 @@ Wrinkles So `mergeCaseAlts` floats out any join points. It doesn't float out non-join-points unless the /outer/ case has just one alternative; doing - so would risk more allocation + so would risk more allocation. + + Note also that `mergeCaseAlts` floats join points out of ticks, for which + we need to be extra careful; see (MC6). + +(MC5) We want to move ticks out of the way if possible, to prevent them from + inhibiting optimisation. For example, say we have: + + case expensive of r { + C1 -> rhs1; -- happy path + _ -> scctick<doEdgeCase> (case r of { C2 -> rhs2; C3 -> rhs3 }) + } + + In this situation, we push the "doEdgeCase" tick **inwards** and proceed + to merge cases, like so: + + case expensive of + C1 -> rhs1 + C2 -> scctick<doEdgeCase> rhs2 + C3 -> scctick<doEdgeCase> rhs3 + + This preserves the tick semantics, because this transformation: + + 1. preserves counts, + 2. does not move cost in or out of the tick scope. + + (1) is clear: we will tick 'doEdgeCase' exactly in the C2/C3 alternatives, + and we won't otherwise. + For (2), recall that case is strict in Core. We already evaluated 'expensive', + so re-scrutinising 'r' is free. + + This means that, perhaps surprisingly, this transformation is valid for + **all** ticks, including non-floatable ones. + + In contrast, we would not want to move the tick outwards, because this: + + - will lead to additional counting of 'doEdgeCase' in the 'C1' (happy path) case, + - risks attributing the cost of evaluating 'expensive' to 'doEdgeCase'. + +(MC6) There is a dangerous interaction between (MC4) and (MC5), which can lead + to invalid Core (as reported in #26642, #26929). Suppose we have: + + case f x of r -> + scctick<foo> + join j y = rhs in + case r of { C1 -> j 1; C2 -> bar } + + If we naively carried out (MC4) and (MC5) together, this would result in: + + join j y = rhs in + case f x of + C1 -> scctick<foo> (j 1) + C2 -> scctick<foo> bar + + This has moved the tick in between the join point binding 'j' and the + join point jump, which is invalid. The simplifier cannot deal with such + Core, resulting in #26642. + + The solution: abort whenever we would position a non-soft-scope tick + inside a join point in this manner. + An alternative would be to float the tick outwards, but as we saw in (MC5) + this risks a grave misattribution of profiling costs, so we don't do that. -(MC5) See Note [Cascading case merge] +(MC7) See Note [Cascading case merge] See also Note [Example of case-merging and caseRules] in GHC.Core.Opt.Simplify.Utils ===================================== m4/fptools_happy.m4 ===================================== @@ -24,13 +24,18 @@ changequote([, ])dnl ]) if test ! -f compiler/GHC/Parser.hs || test ! -f compiler/GHC/Cmm/Parser.hs then - failure_msg="Happy version == 1.20.* || >= 2.0.2 && < 2.2 is required to compile GHC" + if test x"$fptools_cv_happy_version" != x; then + fptools_cv_happy_version_display="version $fptools_cv_happy_version"; + else + fptools_cv_happy_version_display="none"; + fi; + failure_msg="Happy version == 1.20.* || >= 2.0.2 && < 2.3 is required to compile GHC. (Found: $fptools_cv_happy_version_display)" FP_COMPARE_VERSIONS([$fptools_cv_happy_version],[-lt],[1.20.0], [AC_MSG_ERROR([$failure_msg])])[] FP_COMPARE_VERSIONS([$fptools_cv_happy_version],[-ge],[1.21.0], FP_COMPARE_VERSIONS([$fptools_cv_happy_version], [-le], [2.0.1], [AC_MSG_ERROR([$failure_msg])])[])[] - FP_COMPARE_VERSIONS([$fptools_cv_happy_version],[-ge],[2.2.0], + FP_COMPARE_VERSIONS([$fptools_cv_happy_version],[-ge],[2.3.0], [AC_MSG_ERROR([$failure_msg])])[] fi ===================================== testsuite/tests/simplCore/should_compile/T26642.hs ===================================== @@ -0,0 +1,46 @@ +module T26642 ( saveClobberedTemps ) where + +import Prelude ( IO, Bool(..), Int, (>>=), (==), return ) +import Data.Word ( Word64 ) + +------------------------------------------------------------------------------- + +data Word64Map a + = Bin (Word64Map a) (Word64Map a) + | Tip a + | Nil + +{-# NOINLINE myFoldr #-} +myFoldr :: (a -> b -> b) -> b -> Word64Map a -> b +myFoldr f = go + where + {-# NOINLINE go #-} + go z' Nil = z' + go z' (Tip x) = f x z' + go z' (Bin l r) = go (go z' r) l + +{-# NOINLINE nonDetFold #-} +nonDetFold :: (b -> elt -> IO b) -> b -> Word64Map elt -> IO b +nonDetFold f z0 xs = myFoldr c return xs z0 + where + {-# NOINLINE c #-} + c x k z = f z x >>= k + +{-# NOINLINE myFalse #-} +myFalse :: Bool +myFalse = False + +type RealReg = Int +data Loc = InReg RealReg | InMem + +saveClobberedTemps :: forall instr. [RealReg] -> IO [instr] +saveClobberedTemps clobbered = nonDetFold maybe_spill [] Nil + where + {-# NOINLINE maybe_spill #-} + maybe_spill :: [instr] -> Loc -> IO [instr] + maybe_spill instrs !loc = + case loc of + InReg reg + | myFalse + -> return [] + _ -> return instrs ===================================== testsuite/tests/simplCore/should_compile/all.T ===================================== @@ -470,6 +470,8 @@ test('T22272', normal, multimod_compile, ['T22272', '-O -fexpose-all-unfoldings # go should become a join point test('T22428', [grep_errmsg(r'jump go') ], compile, ['-O -ddump-simpl -dsuppress-uniques -dno-typeable-binds -dsuppress-unfoldings']) +test('T26642', [unless(have_profiling(), skip)], compile, ['-O -prof -fprof-auto-calls']) + test('T22459', normal, compile, ['']) test('T22623', normal, multimod_compile, ['T22623', '-O -v0']) test('T22662', normal, compile, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3319b7da62b0665b4425dbac3c060e… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3319b7da62b0665b4425dbac3c060e… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/davide/ghc-internal-def] Hadrian: create a ghc-internal .def file per ghc-internal dll
by David Eichmann (@DavidEichmann) 20 May '26

20 May '26
David Eichmann pushed to branch wip/davide/ghc-internal-def at Glasgow Haskell Compiler / GHC Commits: a072d02f by David Eichmann at 2026-05-20T14:20:52+01:00 Hadrian: create a ghc-internal .def file per ghc-internal dll The .def file generated from rts/win32/libHSghc-internal.def.in contains the name of the ghc-internal dll, but that differs based on if the dll is inplace/final and what way it is. Previously, this was not accounted for and inconsistent dlls names where used. That led to failure when loading dlls are runtime in experiments with windows dynamic linking. - - - - - 5 changed files: - hadrian/src/Rules/Generate.hs - hadrian/src/Rules/Library.hs - hadrian/src/Rules/Rts.hs - rts/.gitignore - rts/win32/libHSghc-internal.def.in Changes: ===================================== hadrian/src/Rules/Generate.hs ===================================== @@ -377,7 +377,6 @@ templateRules = do , interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1 , interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2 ] - templateRule "rts/win32/libHSghc-internal.def" projectVersion templateRule "docs/index.html" $ packageUnitIds Stage1 templateRule "docs/users_guide/ghc_config.py" $ mconcat [ projectVersion ===================================== hadrian/src/Rules/Library.hs ===================================== @@ -203,10 +203,21 @@ extraObjects context | package context == rts = do target <- interpretInContext context getStagedTarget - builddir <- buildPath context - return [ builddir -/- "libHSghc-internal.dll.a" - | archOS_OS (tgtArchOs target) == OSMinGW32 - , Dynamic `wayUnit` way context ] + if not (archOS_OS (tgtArchOs target) == OSMinGW32 + && Dynamic `wayUnit` way context) + then return [] + else do + -- Find the ghc-internal library file name + let way' = if Profiling `wayUnit` way context then profiling else vanilla + ghcInternalDllName <- takeFileName <$> pkgLibraryFile (Context { + stage = stage context, + way = way', + iplace = iplace context, + package = ghcInternal + }) + + builddir <- buildPath context + return [ builddir -/- ghcInternalDllName <> ".a"] | otherwise = return [] ===================================== hadrian/src/Rules/Rts.hs ===================================== @@ -29,11 +29,19 @@ rtsRules = priority 3 $ do -- to be linked into the rts dll. forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do let buildPath = root -/- buildDir (rtsContext stage) - buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib + buildPath -/- "libHSghc-internal-*.def" %> buildGhcInternalImportDef + buildPath -/- "libHSghc-internal-*.dll.a" %> buildGhcInternalImportLib + +buildGhcInternalImportDef :: FilePath -> Action () +buildGhcInternalImportDef target = do + templateIn <- readFile' "rts/win32/libHSghc-internal.def.in" + let dllName = (dropExtension (takeFileName target)) <.> "dll" + templateOut = replace "@GhcInternalDll@" dllName templateIn + writeFile' target templateOut buildGhcInternalImportLib :: FilePath -> Action () buildGhcInternalImportLib target = do - let input = "rts/win32/libHSghc-internal.def" + let input = (dropExtension (dropExtension target)) <.> "def" -- the .def file output = target -- the .dll.a import lib need [input] runBuilder Dlltool ["-d", input, "-l", output] [input] [output] ===================================== rts/.gitignore ===================================== @@ -20,4 +20,3 @@ /ghcautoconf.h.autoconf.in /ghcautoconf.h.autoconf /include/ghcautoconf.h -/win32/libHSghc-internal.def ===================================== rts/win32/libHSghc-internal.def.in ===================================== @@ -1,4 +1,4 @@ -LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll +LIBRARY @GhcInternalDll@ EXPORTS init_ghc_hs_iface View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a072d02fd97cac69f0bc6a50477d4cf… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a072d02fd97cac69f0bc6a50477d4cf… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/mangoiv/ghc-9.12-bp] 4 commits: rts: cast Sp_plusW to StgPtr to appease gcc
by Magnus (@MangoIV) 20 May '26

20 May '26
Magnus pushed to branch wip/mangoiv/ghc-9.12-bp at Glasgow Haskell Compiler / GHC Commits: d99bb8e1 by mangoiv at 2026-05-20T14:52:56+02:00 rts: cast Sp_plusW to StgPtr to appease gcc - - - - - 8fde70d7 by mangoiv at 2026-05-20T14:52:56+02:00 rts: disable out of bounds array warning for sometimes inlined rts function - - - - - b4ef6088 by Duncan Coutts at 2026-05-20T14:56:06+02:00 Handle heap allocation failure in I/O primops The current I/O managers do not use allocateMightFail, but future ones will. To support this properly we need to be able to return to the primop with a failure. We simply use a bool return value. Currently however, we will just throw an exception rather than calling the GC because that's what all the other primops do too. For the general issue of primops invoking GC and retrying, see https://gitlab.haskell.org/ghc/ghc/-/issues/24105 (cherry picked from commit 62ae97de67f8cc59fc702e26a9e29eda1f84d461) - - - - - 3319b7da by Luite Stegeman at 2026-05-20T14:56:59+02:00 Windows: remove StgAsyncIOResult and fix crash/leaks In stg_block_async{_void}, a stack slot was reserved for an StgAsyncIOResult. This slot would be filled by the IO manager upon completion of the async call. However, if the blocked thread was interrupted by an async exception, we would end up in an invalid state: - If the blocked computation was never re-entered, the StgAsyncIOResult would never be freed. - If the blocked computation was re-entered, the thread would find an unitialized stack slot for the StgAsyncIOResult, leading to a crash reading its fields, or freeing the pointer. We fix this by removing the StgAsyncIOResult altogether and writing the result directly to the stack. Fixes #26341 (cherry picked from commit fcf092dda534cc38637d1f7920aa0dae58fe5273) - - - - - 20 changed files: - rts/HeapStackCheck.cmm - rts/IOManager.c - rts/IOManager.h - rts/Interpreter.c - rts/PrimOps.cmm - rts/RtsSymbols.c - rts/Threads.c - rts/include/rts/storage/ClosureMacros.h - rts/include/rts/storage/TSO.h - rts/include/stg/MiscClosures.h - rts/win32/AsyncMIO.c - rts/win32/AsyncMIO.h - + testsuite/tests/concurrent/should_run/T26341.hs - + testsuite/tests/concurrent/should_run/T26341.stdout - + testsuite/tests/concurrent/should_run/T26341a.hs - + testsuite/tests/concurrent/should_run/T26341a.stdout - + testsuite/tests/concurrent/should_run/T26341b.hs - + testsuite/tests/concurrent/should_run/T26341b.stdout - testsuite/tests/concurrent/should_run/all.T - utils/deriveConstants/Main.hs Changes: ===================================== rts/HeapStackCheck.cmm ===================================== @@ -706,38 +706,24 @@ stg_block_throwto (P_ tso, P_ exception) } #if defined(mingw32_HOST_OS) -INFO_TABLE_RET ( stg_block_async, RET_SMALL, W_ info_ptr, W_ ares ) +INFO_TABLE_RET ( stg_block_async, RET_SMALL, W_ info_ptr, W_ len, W_ errCode ) return () { - W_ len, errC; - - len = TO_W_(StgAsyncIOResult_len(ares)); - errC = TO_W_(StgAsyncIOResult_errCode(ares)); - ccall free(ares "ptr"); - return (len, errC); + return (len, errCode); } stg_block_async { - Sp_adj(-2); - Sp(0) = stg_block_async_info; - BLOCK_GENERIC; -} + W_ eintr; + (eintr) = ccall rts_EINTR(); -/* Used by threadDelay implementation; it would be desirable to get rid of - * this free()'ing void return continuation. - */ -INFO_TABLE_RET ( stg_block_async_void, RET_SMALL, W_ info_ptr, W_ ares ) - return () -{ - ccall free(ares "ptr"); - return (); -} - -stg_block_async_void -{ - Sp_adj(-2); - Sp(0) = stg_block_async_void_info; + // Fill the stack frame with values that indicate that the operation + // has been interrupted. The IO manager will overwrite these with the + // actual results if the async operation completes. + Sp_adj(-3); + Sp(0) = stg_block_async_info; + Sp(1) = -1; // len: -1 indicates error + Sp(2) = eintr; // errCode: interrupted BLOCK_GENERIC; } ===================================== rts/IOManager.c ===================================== @@ -561,10 +561,8 @@ void scavengeTSOIOManager(StgTSO *tso) */ /* case IO_MANAGER_WIN32_LEGACY: - * BlockedOn{Read,Write,DoProc} uses block_info.async_result - * The StgAsyncIOResult async_result is allocated on the C heap. - * It'd probably be better if it used the GC heap. If it did we'd - * scavenge it here. + * BlockedOn{Read,Write,DoProc} uses block_info.async_reqID + * which is a plain integer, so nothing to scavenge. */ default: @@ -707,7 +705,7 @@ void awaitCompletedTimeoutsOrIO(Capability *cap) } -void syncIOWaitReady(Capability *cap, +bool syncIOWaitReady(Capability *cap, StgTSO *tso, IOReadOrWrite rw, HsInt fd) @@ -724,7 +722,7 @@ void syncIOWaitReady(Capability *cap, tso->block_info.fd = fd; RELEASE_STORE(&tso->why_blocked, why_blocked); appendToIOBlockedQueue(cap, tso); - break; + return true; } #endif default: @@ -747,7 +745,7 @@ void syncIOCancel(Capability *cap, StgTSO *tso) case IO_MANAGER_WIN32_LEGACY: removeThreadFromDeQueue(cap, &cap->iomgr->blocked_queue_hd, &cap->iomgr->blocked_queue_tl, tso); - abandonWorkRequest(tso->block_info.async_result->reqID); + abandonWorkRequest(tso->block_info.async_reqID); break; #endif default: @@ -761,7 +759,7 @@ static void insertIntoSleepingQueue(Capability *cap, StgTSO *tso, LowResTime tar #endif -void syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay) +bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay) { debugTrace(DEBUG_iomanager, "thread %ld waiting for %lld us", tso->id, us_delay); ASSERT(tso->why_blocked == NotBlocked); @@ -773,7 +771,7 @@ void syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay) tso->block_info.target = target; RELEASE_STORE(&tso->why_blocked, BlockedOnDelay); insertIntoSleepingQueue(cap, tso, target); - break; + return true; } #endif #if defined(IOMGR_ENABLED_WIN32_LEGACY) @@ -782,12 +780,7 @@ void syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay) * would make the primops more consistent. */ { - StgAsyncIOResult *ares = stgMallocBytes(sizeof(StgAsyncIOResult), - "syncDelay"); - ares->reqID = addDelayRequest(us_delay); - ares->len = 0; - ares->errCode = 0; - tso->block_info.async_result = ares; + tso->block_info.async_reqID = addDelayRequest(us_delay); /* Having all async-blocked threads reside on the blocked_queue * simplifies matters, so set the status to OnDoProc and put the @@ -795,7 +788,7 @@ void syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay) */ RELEASE_STORE(&tso->why_blocked, BlockedOnDoProc); appendToIOBlockedQueue(cap, tso); - break; + return true; } #endif default: ===================================== rts/IOManager.h ===================================== @@ -282,13 +282,20 @@ typedef enum { IORead, IOWrite } IOReadOrWrite; /* Synchronous operations: I/O and delays. As synchronous operations they * necessarily operate on threads. The thread is suspended until the operation * completes. + * + * These are called from CMM primops. The ones returing int can perform heap + * allocation, which might fail. They return 0 on success, or n > 0 on heap + * allocation failure, needing n words. The CMM primops should invoke the + * GC to free up at least n words and then retry the operation. */ -void syncIOWaitReady(Capability *cap, StgTSO *tso, IOReadOrWrite rw, HsInt fd); +/* Result is true on success, or false on allocation failure. */ +bool syncIOWaitReady(Capability *cap, StgTSO *tso, IOReadOrWrite rw, HsInt fd); void syncIOCancel(Capability *cap, StgTSO *tso); -void syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay); +/* Result is true on success, or false on allocation failure. */ +bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay); void syncDelayCancel(Capability *cap, StgTSO *tso); ===================================== rts/Interpreter.c ===================================== @@ -468,7 +468,7 @@ slow_spw(void *Sp, StgStack *cur_stack, StgWord offset_words){ } // 2b. Access the element if there is no underflow frame, it must be right // at the top of the stack. - else if(Sp_plusW(offset_words) < (StgPtr)(cur_stack->stack + cur_stack->stack_size)) { + else if((StgPtr)Sp_plusW(offset_words) < (StgPtr)(cur_stack->stack + cur_stack->stack_size)) { // Still inside the stack chunk return Sp_plusW(offset_words); } else { @@ -1832,7 +1832,7 @@ run_BCO: threadStackUnderflow(cap, cap->r.rCurrentTSO); LOAD_STACK_POINTERS; by -= sp_to_uf; - } else if (Sp_plusW(by) < (StgPtr)(stk->stack + stk->stack_size)) { + } else if ((StgPtr)Sp_plusW(by) < (StgPtr)(stk->stack + stk->stack_size)) { // we're within the first stack chunk, this chunk has // no underflow frame break; ===================================== rts/PrimOps.cmm ===================================== @@ -2561,54 +2561,55 @@ stg_whereFromzh (P_ clos, W_ buf) stg_waitReadzh ( W_ fd ) { - ccall syncIOWaitReady(MyCapability() "ptr", CurrentTSO "ptr", - /* IORead */ 0::I32, fd); - jump stg_block_noregs(); + CBool ok; /* Ok, or heap alloc failure. */ + + (ok) = ccall syncIOWaitReady(MyCapability() "ptr", CurrentTSO "ptr", + /* IORead */ 0::I32, fd); + if (ok != 0::CBool) (likely: True) { + jump stg_block_noregs(); + } else { + jump stg_raisezh(ghczminternal_GHCziInternalziIOziException_heapOverflow_closure); + } } stg_waitWritezh ( W_ fd ) { - ccall syncIOWaitReady(MyCapability() "ptr", CurrentTSO "ptr", - /* IOWrite */ 1::I32, fd); - jump stg_block_noregs(); + CBool ok; /* Ok, or heap alloc failure. */ + + (ok) = ccall syncIOWaitReady(MyCapability() "ptr", CurrentTSO "ptr", + /* IOWrite */ 1::I32, fd); + if (ok != 0::CBool) (likely: True) { + jump stg_block_noregs(); + } else { + jump stg_raisezh(ghczminternal_GHCziInternalziIOziException_heapOverflow_closure); + } } stg_delayzh ( W_ us_delay ) { - ccall syncDelay(MyCapability() "ptr", CurrentTSO "ptr", us_delay); + CBool ok; /* Ok, or heap alloc failure. */ - /* Annoyingly, we cannot be consistent with how we wait and resume the - * blocked thread. The reason is that the win32 legacy I/O manager - * allocates a StgAsyncIOResult struct on the C heap which has to be - * freed when the thread resumes. It's a bit awkward to arrange to - * allocate it on the GC heap instead, so that's how it is for now. Sigh. - */ -#if defined(mingw32_HOST_OS) - jump stg_block_async_void(); -#else - jump stg_block_noregs(); -#endif + (ok) = ccall syncDelay(MyCapability() "ptr", CurrentTSO "ptr", us_delay); + + if (ok != 0::CBool) (likely: True) { + jump stg_block_noregs(); + } else { + jump stg_raisezh(ghczminternal_GHCziInternalziIOziException_heapOverflow_closure); + } } #if defined(mingw32_HOST_OS) stg_asyncReadzh ( W_ fd, W_ is_sock, W_ len, W_ buf ) { - W_ ares; CInt reqID; #if defined(THREADED_RTS) ccall barf("asyncRead# on threaded RTS") never returns; #else - /* could probably allocate this on the heap instead */ - ("ptr" ares) = ccall stgMallocBytes(SIZEOF_StgAsyncIOResult, - "stg_asyncReadzh"); (reqID) = ccall addIORequest(fd, 0/*FALSE*/,is_sock,len,buf "ptr"); - StgAsyncIOResult_reqID(ares) = reqID; - StgAsyncIOResult_len(ares) = 0; - StgAsyncIOResult_errCode(ares) = 0; - StgTSO_block_info(CurrentTSO) = ares; + StgTSO_block_info(CurrentTSO) = reqID; ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32); %release StgTSO_why_blocked(CurrentTSO) = BlockedOnRead::I32; @@ -2620,21 +2621,14 @@ stg_asyncReadzh ( W_ fd, W_ is_sock, W_ len, W_ buf ) stg_asyncWritezh ( W_ fd, W_ is_sock, W_ len, W_ buf ) { - W_ ares; CInt reqID; #if defined(THREADED_RTS) ccall barf("asyncWrite# on threaded RTS") never returns; #else - ("ptr" ares) = ccall stgMallocBytes(SIZEOF_StgAsyncIOResult, - "stg_asyncWritezh"); (reqID) = ccall addIORequest(fd, 1/*TRUE*/,is_sock,len,buf "ptr"); - - StgAsyncIOResult_reqID(ares) = reqID; - StgAsyncIOResult_len(ares) = 0; - StgAsyncIOResult_errCode(ares) = 0; - StgTSO_block_info(CurrentTSO) = ares; + StgTSO_block_info(CurrentTSO) = reqID; ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32); %release StgTSO_why_blocked(CurrentTSO) = BlockedOnWrite::I32; @@ -2646,21 +2640,14 @@ stg_asyncWritezh ( W_ fd, W_ is_sock, W_ len, W_ buf ) stg_asyncDoProczh ( W_ proc, W_ param ) { - W_ ares; CInt reqID; #if defined(THREADED_RTS) ccall barf("asyncDoProc# on threaded RTS") never returns; #else - /* could probably allocate this on the heap instead */ - ("ptr" ares) = ccall stgMallocBytes(SIZEOF_StgAsyncIOResult, - "stg_asyncDoProczh"); (reqID) = ccall addDoProcRequest(proc "ptr",param "ptr"); - StgAsyncIOResult_reqID(ares) = reqID; - StgAsyncIOResult_len(ares) = 0; - StgAsyncIOResult_errCode(ares) = 0; - StgTSO_block_info(CurrentTSO) = ares; + StgTSO_block_info(CurrentTSO) = reqID; ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32); %release StgTSO_why_blocked(CurrentTSO) = BlockedOnDoProc::I32; ===================================== rts/RtsSymbols.c ===================================== @@ -30,6 +30,7 @@ #include <shfolder.h> /* SHGetFolderPathW */ #include "IOManager.h" #include "win32/AsyncWinIO.h" +#include "win32/AsyncMIO.h" #endif #if defined(openbsd_HOST_OS) @@ -168,6 +169,7 @@ extern char **environ; SymI_HasProto(__stdio_common_vswprintf_s) \ SymI_HasProto(__stdio_common_vswprintf) \ SymI_HasProto(_errno) \ + SymI_HasProto(rts_EINTR) \ /* see Note [Symbols for MinGW's printf] */ \ SymI_HasProto(_lock_file) \ SymI_HasProto(_unlock_file) \ ===================================== rts/Threads.c ===================================== @@ -928,7 +928,7 @@ printThreadBlockage(StgTSO *tso) switch (ACQUIRE_LOAD(&tso->why_blocked)) { #if defined(mingw32_HOST_OS) case BlockedOnDoProc: - debugBelch("is blocked on proc (request: %u)", tso->block_info.async_result->reqID); + debugBelch("is blocked on proc (request: %" FMT_Word ")", tso->block_info.async_reqID); break; #endif #if !defined(THREADED_RTS) ===================================== rts/include/rts/storage/ClosureMacros.h ===================================== @@ -322,8 +322,10 @@ EXTERN_INLINE bool LOOKS_LIKE_PTR (const void* p) EXTERN_INLINE bool LOOKS_LIKE_INFO_PTR_NOT_NULL (StgWord p); EXTERN_INLINE bool LOOKS_LIKE_INFO_PTR_NOT_NULL (StgWord p) { +NO_WARN(-Warray-bounds, StgInfoTable *info = INFO_PTR_TO_STRUCT((StgInfoTable *)p); return info->type != INVALID_OBJECT && info->type < N_CLOSURE_TYPES; +) } EXTERN_INLINE bool LOOKS_LIKE_INFO_PTR (StgWord p); ===================================== rts/include/rts/storage/TSO.h ===================================== @@ -37,15 +37,6 @@ typedef StgWord64 StgThreadID; */ typedef unsigned int StgThreadReturnCode; -#if defined(mingw32_HOST_OS) -/* results from an async I/O request + its request ID. */ -typedef struct { - unsigned int reqID; - int len; - int errCode; -} StgAsyncIOResult; -#endif - /* Reason for thread being blocked. See comment above struct StgTso_. */ typedef union { StgClosure *closure; @@ -55,7 +46,7 @@ typedef union { struct MessageWakeup_ *wakeup; StgInt fd; /* StgInt instead of int, so that it's the same size as the ptrs */ #if defined(mingw32_HOST_OS) - StgAsyncIOResult *async_result; + StgWord async_reqID; #endif #if !defined(THREADED_RTS) StgWord target; ===================================== rts/include/stg/MiscClosures.h ===================================== @@ -430,8 +430,6 @@ RTS_RET(stg_block_putmvar); #if defined(mingw32_HOST_OS) RTS_FUN_DECL(stg_block_async); RTS_RET(stg_block_async); -RTS_FUN_DECL(stg_block_async_void); -RTS_RET(stg_block_async_void); #endif RTS_FUN_DECL(stg_block_stmwait); RTS_FUN_DECL(stg_block_throwto); ===================================== rts/win32/AsyncMIO.c ===================================== @@ -8,16 +8,19 @@ * For the WINIO manager see base in the GHC.Event modules. */ -#if !defined(THREADED_RTS) #include "Rts.h" +#include <errno.h> +#include "win32/AsyncMIO.h" + +#if !defined(THREADED_RTS) + #include "RtsUtils.h" #include <windows.h> #include <stdio.h> #include "Schedule.h" #include "Capability.h" #include "IOManagerInternals.h" -#include "win32/AsyncMIO.h" #include "win32/MIOManager.h" /* @@ -299,14 +302,9 @@ start: case BlockedOnRead: case BlockedOnWrite: case BlockedOnDoProc: - if (tso->block_info.async_result->reqID == rID) { - // Found the thread blocked waiting on request; - // stodgily fill - // in its result block. - tso->block_info.async_result->len = - completedTable[i].len; - tso->block_info.async_result->errCode = - completedTable[i].errCode; + if (tso->block_info.async_reqID == rID) { + HsInt len = completedTable[i].len; + HsInt errCode = completedTable[i].errCode; // Drop the matched TSO from blocked_queue if (prev) { @@ -322,11 +320,14 @@ start: // Terminates the run queue + this inner for-loop. tso->_link = END_TSO_QUEUE; tso->why_blocked = NotBlocked; - // save the StgAsyncIOResult in the - // stg_block_async_info stack frame, because - // the block_info field will be overwritten by - // pushOnRunQueue(). - tso->stackobj->sp[1] = (W_)tso->block_info.async_result; + // For stg_block_async frames (read/write/doProc), + // write len and errCode directly to the stack. + // For stg_block_noregs frames (delay), nothing + // to write. + if (tso->stackobj->sp[0] == (W_)&stg_block_async_info) { + tso->stackobj->sp[1] = (W_)len; + tso->stackobj->sp[2] = (W_)errCode; + } pushOnRunQueue(&MainCapability, tso); break; } @@ -389,3 +390,8 @@ resetAbandonRequestWait( void ) } #endif /* !defined(THREADED_RTS) */ + +HsInt rts_EINTR(void) +{ + return EINTR; +} ===================================== rts/win32/AsyncMIO.h ===================================== @@ -27,3 +27,4 @@ extern int awaitRequests(bool wait); extern void abandonRequestWait(void); extern void resetAbandonRequestWait(void); +extern HsInt rts_EINTR(void); ===================================== testsuite/tests/concurrent/should_run/T26341.hs ===================================== @@ -0,0 +1,20 @@ +{-# OPTIONS_GHC -O -fno-full-laziness #-} + +import Control.Concurrent (threadDelay, myThreadId, forkIO, killThread) +import System.IO.Unsafe (unsafePerformIO) +import Control.Exception +import GHC.Exts + +compute :: Int +compute = noinline unsafePerformIO $ do + mainThreadID <- myThreadId + _ <- forkIO $ do + threadDelay 500000 + killThread mainThreadID + threadDelay 1000000 + return 0 + +main = do + catch (print compute) (\(e :: AsyncException) -> print $ "1:" ++ show e) + catch (print compute) (\(e :: AsyncException) -> print $ "2:" ++ show e) + print "done" ===================================== testsuite/tests/concurrent/should_run/T26341.stdout ===================================== @@ -0,0 +1,3 @@ +"1:thread killed" +0 +"done" ===================================== testsuite/tests/concurrent/should_run/T26341a.hs ===================================== @@ -0,0 +1,75 @@ +-- Test that re-evaluating an AP_STACK from an interrupted async I/O call +-- does not crash. On Windows non-threaded RTS, re-entry returns EINTR +-- which readRawBufferPtr converts to IOException Interrupted. On the +-- threaded RTS (any platform), the blocking read is re-attempted and +-- succeeds because we write a byte to the pipe between evaluations. +-- +-- Before the fix for #26341, re-evaluation on Windows would crash or read +-- uninitialized memory from a freed StgAsyncIOResult. +{-# OPTIONS_GHC -O -fno-full-laziness #-} + +import Control.Concurrent (threadDelay, myThreadId, forkIO, killThread, rtsSupportsBoundThreads) +import Control.Exception +import Data.IORef +import Foreign +import Foreign.C +import GHC.Exts +import GHC.IO.Exception (IOErrorType(..), IOException(..)) +import GHC.IO.FD (FD(..), readRawBufferPtr, writeRawBufferPtr) +import System.Info (os) +import System.IO.Unsafe (unsafePerformIO) +import System.Process (createPipeFd) + +-- Store the write fd so main can feed data into the pipe between +-- evaluations. On Unix this unblocks the re-entered read; on Windows +-- stg_block_async returns EINTR regardless. +{-# NOINLINE writeFdRef #-} +writeFdRef :: IORef CInt +writeFdRef = unsafePerformIO $ newIORef (-1) + +-- | A thunk whose unsafePerformIO blocks on a pipe read. A forked +-- thread kills the main thread after 200ms, which creates an AP_STACK. +{-# NOINLINE blockedRead #-} +blockedRead :: () +blockedRead = noinline unsafePerformIO $ do + (readFd, writeFd) <- createPipeFd + writeIORef writeFdRef writeFd + buf <- mallocBytes 1 + mainTid <- myThreadId + _ <- forkIO $ do + threadDelay 200000 -- 200ms + killThread mainTid + -- readRawBufferPtr dispatches to asyncReadRawBufferPtr on Windows + -- non-threaded RTS; on Unix it uses threadWaitRead + read(). + _ <- readRawBufferPtr "blockedRead" (FD readFd 0) buf 0 1 + return () + +main :: IO () +main = do + -- First evaluation: the thunk blocks on the pipe read, gets killed. + catch (evaluate blockedRead) + (\(e :: AsyncException) -> putStrLn $ "caught: " ++ show e) + + -- Write a byte so the re-entered read can complete on Unix. + wfd <- readIORef writeFdRef + buf <- mallocBytes 1 + poke buf 0 + _ <- writeRawBufferPtr "unblock" (FD wfd 0) buf 0 1 + + -- Second evaluation: AP_STACK re-enters. + -- Non-threaded Windows: asyncRead returns (-1, EINTR) → IOException + -- Threaded / Unix: read succeeds → returns normally + let expectEINTR = os == "mingw32" && not rtsSupportsBoundThreads + result <- try (evaluate blockedRead) + case result of + Left e + | Just ioe <- fromException e + , ioe_type (ioe :: IOException) == Interrupted + -> putStrLn "re-evaluated ok" + | otherwise + -> putStrLn $ "unexpected: " ++ show e + Right () + | expectEINTR -> putStrLn "unexpected: expected EINTR" + | otherwise -> putStrLn "re-evaluated ok" + + putStrLn "done" ===================================== testsuite/tests/concurrent/should_run/T26341a.stdout ===================================== @@ -0,0 +1,3 @@ +caught: thread killed +re-evaluated ok +done ===================================== testsuite/tests/concurrent/should_run/T26341b.hs ===================================== @@ -0,0 +1,101 @@ +-- Stress test for #26341: repeatedly interrupt async-blocked threads and +-- re-enter their AP_STACKs. Before the fix, re-entering a thunk whose +-- unsafePerformIO was blocked on an async I/O call (Windows non-threaded +-- RTS) would read uninitialized memory or free a dangling pointer, +-- because stg_block_async reserved a stack slot for a heap-allocated +-- StgAsyncIOResult that became invalid after an async exception. +-- +-- This test spawns many concurrent workers, each of which: +-- 1. Creates a pipe. +-- 2. Builds a thunk that blocks on a pipe read via unsafePerformIO. +-- 3. Evaluates the thunk and kills it with an async exception. +-- 4. Re-evaluates the thunk (AP_STACK re-entry). +-- 5. Repeats many times. +-- +-- On threaded RTS / Unix the re-entered read succeeds (we write a byte +-- first). On Windows non-threaded RTS the re-entered async call returns +-- EINTR. Both paths exercise the fixed stack-frame layout. +{-# OPTIONS_GHC -O -fno-full-laziness #-} + +import Control.Concurrent +import Control.Exception +import Foreign +import Foreign.C +import GHC.Exts +import GHC.IO.Exception (IOErrorType(..), IOException(..)) +import GHC.IO.FD (FD(..), readRawBufferPtr, writeRawBufferPtr) +import System.IO (hFlush, stdout) +import System.IO.Unsafe (unsafePerformIO) +import System.Posix.Internals (c_close) +import System.Process (createPipeFd) + +iterations :: Int +iterations = 200 + +workers :: Int +workers = 4 + +-- Each worker independently performs `iterations` rounds of: +-- block on pipe read → interrupt → re-evaluate the AP_STACK. +worker :: Int -> MVar () -> IO () +worker wid done = do + buf <- mallocBytes 1 + let go 0 = return () + go n = do + (readFd, writeFd) <- createPipeFd + + -- Build a fresh thunk each iteration so we get a new AP_STACK. + let {-# NOINLINE blockedThunk #-} + blockedThunk :: () + blockedThunk = noinline unsafePerformIO $ do + tid <- myThreadId + _ <- forkIO $ do + threadDelay 1000 -- 1ms: tight window + killThread tid + _ <- readRawBufferPtr "stress" (FD readFd 0) buf 0 1 + return () + + -- First evaluation: block and get killed. + catch (evaluate blockedThunk) + (\(_ :: SomeException) -> return ()) + + -- Write a byte so the re-entered read can complete on + -- threaded RTS / Unix. + poke buf 0 + _ <- writeRawBufferPtr "unblock" (FD writeFd 0) buf 0 1 + + -- Second evaluation: AP_STACK re-entry. + result <- try (evaluate blockedThunk) + case result of + Left e + | Just ioe <- fromException e + , ioe_type (ioe :: IOException) == Interrupted + -> return () -- expected on Windows non-threaded + | otherwise + -> throwIO (userError $ + "worker " ++ show wid ++ " iteration " ++ show n ++ + ": unexpected exception: " ++ show e) + Right () -> return () -- expected on threaded / Unix + + -- Close the pipe fds. + _ <- c_close readFd + _ <- c_close writeFd + + go (n - 1) + + go iterations + putMVar done () + +main :: IO () +main = do + dones <- mapM (\wid -> do + done <- newEmptyMVar + _ <- forkIO (worker wid done) + return done + ) [1..workers] + + -- Wait for all workers to finish. + mapM_ takeMVar dones + + putStrLn "stress test passed" + hFlush stdout ===================================== testsuite/tests/concurrent/should_run/T26341b.stdout ===================================== @@ -0,0 +1 @@ +stress test passed ===================================== testsuite/tests/concurrent/should_run/all.T ===================================== @@ -298,3 +298,19 @@ test('hs_try_putmvar003', # Check forkIO exception determinism under optimization test('T13330', normal, compile_and_run, ['-O']) + +test('T26341', normal, compile_and_run, ['']) + +# Test EINTR for async I/O interrupted by an exception (#26341) +test('T26341a' + # test uses pipe operations which are not supported by the JS/wasm backends + , when(arch('wasm32') or arch('javascript'), skip) + , compile_and_run, ['-package process']) + +# Stress test: many threads repeatedly interrupt and re-enter async-blocked +# thunks (#26341). Before the fix, this would crash due to dangling +# StgAsyncIOResult pointers on the stack. +test('T26341b' + # test uses pipe operations which are not supported by the JS/wasm backends + , when(arch('wasm32') or arch('javascript'), skip) + , compile_and_run, ['-package process']) ===================================== utils/deriveConstants/Main.hs ===================================== @@ -646,12 +646,7 @@ wanteds os = concat -- Note that this conditional part only affects the C headers. -- That's important, as it means we get the same PlatformConstants -- type on all platforms. - ,if os == Just Windows - then concat [structSize C "StgAsyncIOResult" - ,structField C "StgAsyncIOResult" "reqID" - ,structField C "StgAsyncIOResult" "len" - ,structField C "StgAsyncIOResult" "errCode"] - else [] + ,[] -- struct HsIface ,structField C "HsIface" "processRemoteCompletion_closure" @@ -814,9 +809,6 @@ getWanted verbose os tmpdir gccProgram gccFlags nmProgram mobjdumpProgram "", "#define PROFILING", "#define THREADED_RTS", - -- We need to define this if we want StgAsyncIOResult - -- struct to be present after CPP - -- -- FIXME: rts/PosixSource.h should include ghcplatform.h -- which should set this. There is a mismatch host/target -- again... View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d93c45110022be45f70600b25b184d… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d93c45110022be45f70600b25b184d… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 5 commits: Turn `Trustworthy` into `Safe` in `base` where possible
by Marge Bot (@marge-bot) 20 May '26

20 May '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 2dd36fa3 by Wolfgang Jeltsch at 2026-05-20T04:49:52-04:00 Turn `Trustworthy` into `Safe` in `base` where possible - - - - - f4399dd1 by Wolfgang Jeltsch at 2026-05-20T04:50:37-04:00 Make the current `base` buildable with GHC 10.0 - - - - - 55b19fb0 by Duncan Coutts at 2026-05-20T07:56:03-04:00 Hadrian: remove legacy rts .so symlinks For compatibility with the old makefile based build system, hadrian had rules to generate symlinks from unversioned to versioned names for the rts .so/.dynlib file, like libHSrts-ghcx.y.so -> libHSrts-1.0.3-ghcx.y.so We no longer need these symlinks since the makefile build system has been retired some time ago. The need for these symlinks is awkward on windows where we cannot (in practice) create symlinks. So rather than make them conditional (non-windows), just remove them entirely. - - - - - 5ee49cbc by fendor at 2026-05-20T07:56:04-04:00 Fix regression T27202: `:load` and `:add` work in GHCi To fix the regression there are conceptually two major things that we fix: * We don't remove the `importDirs` from `interactive-session` * When `:add`ing a module, we don't try to find them via PackageImports * The PackageImport is wrong as we can't know the package-name at this stage in ghc/UI.hs What does it mean to not remove the `importDirs` from `interactive-session`? It means that, given some initial `DynFlags`, we will use those `importDirs` in `interactive-session`. The initial `DynFlags`, however, depend on how you initialise the GHC session. For a simple session, initialised by ghc -isrc -this-unit-id main It is simple, just use the `DynFlags` given on the cli. Thus, `main` and `interactive-session` will have the same `DynFlags`, except for the `homeUnitId` and `interactive-session` depends on `main` by construction of the GHCi session. What about a multiple home unit session, though? ghc -unit @unit1 -unit @unit2 What are the `DynFlags` in this cli invocation? It shouldn't be either `@unti1` nor `@unit2`, as the order shouldn't matter or any other implicit condition. For consistency, we decide that the initial `DynFlags` are the top `DynFlags` on the cli, ignoring `-unit` flags. Thus, in this example, there are no `importsDirs` regardless of what we might find in `@unit1` and `@unit2`. But in this invocation: ghc -isrc -unit @unit1 -unit @unit2 The `interactive-session` will have the `importsDirs` `src`. Note, `-isrc` will be inherited in `@unit1` and `@unit2`, so you need to explicitly use `-i` to clear the `importsDirs`, in order to avoid accidentally adding `src` as an import directory to all other home units. This fix has been made possible by the improvements introduced in !15888, which avoids ambiguity when a home unit shares the `importsDirs` with the `interactive-session`, on top of being much faster for multiple home units. Adds regression tests for T27202 for `:load`ing and `:add`ing modules that are located in import directories. - - - - - ac034fa7 by fendor at 2026-05-20T07:56:04-04:00 Use home unit package db stacks in GHCi prompt and session unit In order to import modules from home unit dependencies (e.g., `Data.Map`), the ghci prompt unit needs to populate its `UnitState`. This is tricky to handle correctly, which `PackageDBFlag`s should we use to populate the `UnitState`? We decide, the most intuitive solution for users is to depend on all `PackageDBFlag`s, so that any dependency can be imported in GHCi. This assumes consistency in the `PackageDBFlag`s, so no two home units specify `PackageDBFlag`s that are inconsistent with each other. We could simply concat all the `PackageDBFlag`s of the existing home units, but later `PackageDBFlag`s shadow earlier ones, leading to the last processed home units' `PackageDBFlag`s to shadow the earlier ones. This is hard to fix, we need to give users the capability to provide ghc options for the ghci prompt home unit. However, as this is considerably more work, we decided on an approximation that should work out most of the time. Package Db stacks in cabal and stack follow a certain structure: -no-user-package-db > -package-db $cabal-store > -package-db $local-db The first two arguments are always the same, namely the `-no-user-package-db` and `-package-db`. We compute the longest common prefix over all home units, and use that as the start of the package db stack. Then, over the rest of the `PackageDBFlag`s, we simply take the union and append them to our initial stack. We assume, that the rest of package dbs only defines very few, "local" units that are usually not shadowing each other. This allows us to get a relatively consistent package database stack for the ghci prompt home unit. Similar reasoning applies to the session unit in order to add modules to the session and have dependencies available in the module. We do something similar for `-package` flags, to make sure only the correct units are actually visible in the ghci session. This time, we simply take the union of all `PackageFlag`s, allowing us to import modules from the home unit dependencies. In the future, it would be beneficial to allow the user to provide the exact ghc options to control the visibilities. For now, this will have to do. - - - - - 82 changed files: - + changelog.d/T27202 - + changelog.d/rts_symlinks.md - compiler/GHC/Driver/DynFlags.hs - compiler/GHC/Unit/State.hs - ghc/GHCi/UI.hs - ghc/Main.hs - hadrian/src/Rules/Register.hs - hadrian/src/Rules/Rts.hs - libraries/base/src/Control/Exception.hs - libraries/base/src/Control/Monad/IO/Class.hs - libraries/base/src/Data/Data.hs - libraries/base/src/Data/Fixed.hs - libraries/base/src/Data/List/NonEmpty.hs - libraries/base/src/Data/Version.hs - libraries/base/src/GHC/ByteOrder.hs - libraries/base/src/Numeric.hs - libraries/base/src/System/IO.hs - libraries/base/src/System/Timeout.hs - testsuite/tests/driver/fat-iface/fat014.stdout - + testsuite/tests/ghci/prog-mhu006/Makefile - + testsuite/tests/ghci/prog-mhu006/a/A.hs - + testsuite/tests/ghci/prog-mhu006/all.T - + testsuite/tests/ghci/prog-mhu006/b/B.hs - + testsuite/tests/ghci/prog-mhu006/prog-mhu006a.script - + testsuite/tests/ghci/prog-mhu006/prog-mhu006a.stdout - + testsuite/tests/ghci/prog-mhu006/unitA - + testsuite/tests/ghci/prog-mhu006/unitB - testsuite/tests/ghci/prog003/prog003.T - testsuite/tests/ghci/prog018/prog018.stdout - testsuite/tests/ghci/prog020/Makefile - testsuite/tests/ghci/prog020/all.T - testsuite/tests/ghci/prog020/ghci.prog020.script → testsuite/tests/ghci/prog020/ghci.prog020a.script - testsuite/tests/ghci/prog020/ghci.prog020.stderr → testsuite/tests/ghci/prog020/ghci.prog020a.stderr - testsuite/tests/ghci/prog020/ghci.prog020.stdout → testsuite/tests/ghci/prog020/ghci.prog020a.stdout - + testsuite/tests/ghci/prog020/ghci.prog020b.script - + testsuite/tests/ghci/prog020/ghci.prog020b.stderr - + testsuite/tests/ghci/prog020/ghci.prog020b.stdout - + testsuite/tests/ghci/prog023/Makefile - + testsuite/tests/ghci/prog023/all.T - + testsuite/tests/ghci/prog023/prog023a.script - + testsuite/tests/ghci/prog023/prog023a.stdout - + testsuite/tests/ghci/prog023/prog023b.script - + testsuite/tests/ghci/prog023/prog023b.stdout - + testsuite/tests/ghci/prog023/src/A.hs - + testsuite/tests/ghci/prog024/Makefile - + testsuite/tests/ghci/prog024/all.T - + testsuite/tests/ghci/prog024/prog024a.script - + testsuite/tests/ghci/prog024/prog024a.stdout - + testsuite/tests/ghci/prog024/prog024b.script - + testsuite/tests/ghci/prog024/prog024b.stdout - + testsuite/tests/ghci/prog024/prog024c.script - + testsuite/tests/ghci/prog024/prog024c.stderr - + testsuite/tests/ghci/prog024/prog024c.stdout - + testsuite/tests/ghci/prog024/prog024d.script - + testsuite/tests/ghci/prog024/prog024d.stderr - + testsuite/tests/ghci/prog024/prog024d.stdout - + testsuite/tests/ghci/prog024/prog024e.script - + testsuite/tests/ghci/prog024/prog024e.stdout - + testsuite/tests/ghci/prog024/prog024f.script - + testsuite/tests/ghci/prog024/prog024f.stdout - + testsuite/tests/ghci/prog024/src/A.hs - + testsuite/tests/ghci/prog024/src/B.hs - + testsuite/tests/ghci/prog025/Makefile - + testsuite/tests/ghci/prog025/a/A.hs - + testsuite/tests/ghci/prog025/all.T - + testsuite/tests/ghci/prog025/prog025a.script - + testsuite/tests/ghci/prog025/prog025a.stdout - + testsuite/tests/ghci/prog025/prog025b.script - + testsuite/tests/ghci/prog025/prog025b.stdout - + testsuite/tests/ghci/prog025/testpkg/Test.hs - + testsuite/tests/ghci/prog025/testpkg/testpkg-0.1.0.0.pkg - + testsuite/tests/ghci/prog025/testpkg/testpkg-0.2.0.0.pkg - + testsuite/tests/ghci/prog025/unitA - testsuite/tests/ghci/scripts/T13997.stdout - testsuite/tests/ghci/scripts/T1914.stdout - testsuite/tests/ghci/scripts/T20217.stdout - testsuite/tests/ghci/scripts/T8042.stdout - testsuite/tests/ghci/scripts/T8042recomp.stdout - testsuite/tests/ghci/should_run/T10920.stderr - 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 The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/00902e66c3c854563c3d9f6f8f0756… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/00902e66c3c854563c3d9f6f8f0756… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/jeltsch/base-buildable-with-ghc-9-14] Make the current `base` buildable with GHC 9.14
by Wolfgang Jeltsch (@jeltsch) 20 May '26

20 May '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/base-buildable-with-ghc-9-14 at Glasgow Haskell Compiler / GHC Commits: 15d27c82 by Wolfgang Jeltsch at 2026-05-20T12:54:44+03:00 Make the current `base` buildable with GHC 9.14 This comprises the following changes: * Disable some imports into `GHC.Base` for GHC 9.14 * Disable some imports into `Prelude` for GHC 9.14 * Disable separate `ArrowLoop` import for GHC 9.14 * Disable `GHC.Internal.STM` import for GHC 9.14 * Disable `GHC.Internal.Unicode.Version` import for GHC 9.14 * Disable `GHC.Internal.TH.Monad` import for GHC 9.14 * Add alternative `fixIO` import for GHC 9.14 * Add alternative `unsafeCodeCoerce` import for GHC 9.14 * Disable hiding of imported SIMD operations for GHC 9.14 * Disable use of GHC 9.14’s `printToHandleFinalizerExceptionHandler` * Enable use of `getFileHash` from `ghc-internal` for GHC 9.14 * Make `thenA` available for GHC 9.14 * Make `thenM` available for GHC 9.14 * Disable translation of `IoManagerFlagPoll` for GHC 9.14 * Add `hGetNewlineMode` for GHC 9.14 - - - - - 18 changed files: - libraries/base/src/Control/Applicative.hs - libraries/base/src/Control/Arrow.hs - libraries/base/src/Control/Monad.hs - libraries/base/src/Data/Array/Byte.hs - libraries/base/src/Data/Fixed.hs - libraries/base/src/GHC/Base.hs - libraries/base/src/GHC/Conc.hs - libraries/base/src/GHC/Conc/Sync.hs - libraries/base/src/GHC/Exts.hs - libraries/base/src/GHC/Fingerprint.hs - libraries/base/src/GHC/IO/Handle.hs - libraries/base/src/GHC/RTS/Flags.hs - libraries/base/src/GHC/Unicode.hs - libraries/base/src/GHC/Weak.hs - libraries/base/src/GHC/Weak/Finalize.hs - libraries/base/src/Prelude.hs - libraries/base/src/System/IO.hs - libraries/base/src/System/Mem/Weak.hs Changes: ===================================== libraries/base/src/Control/Applicative.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -64,8 +65,13 @@ import GHC.Internal.Data.Data (Data) import GHC.Internal.Base ( Alternative(..), Applicative(..), Functor(..), Monad(..), MonadPlus(..), - ap, const, liftA, liftA3, liftM, liftM2, thenA, (.), (<**>), + ap, const, liftA, liftA3, liftM, liftM2, (.), (<**>), ) +#if __GLASGOW_HASKELL__ < 1000 +import GHC.Internal.Base (id) +#else +import GHC.Internal.Base (thenA) +#endif import GHC.Internal.Functor.ZipList (ZipList(..)) import GHC.Internal.Types import GHC.Generics @@ -148,3 +154,19 @@ deriving instance (Typeable (a :: Type -> Type -> Type), Typeable b, Typeable c, optional :: Alternative f => f a -> f (Maybe a) optional v = Just <$> v <|> pure Nothing + +#if __GLASGOW_HASKELL__ < 1000 + +-- | Sequence two `Applicative` actions, discarding the result of the first one. +-- +-- Defined as `thenA fa fb = (id <$ fa) <*> fb`. +-- +-- This can be used to explicitly define `(*>) = thenA`, which is the default +-- definition. +-- +-- @since 4.23.0.0 +thenA :: Applicative f => f a -> f b -> f b +thenA fa fb = (id <$ fa) <*> fb +{-# INLINEABLE thenA #-} + +#endif ===================================== libraries/base/src/Control/Arrow.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} -- | @@ -50,4 +51,6 @@ module Control.Arrow ) where import GHC.Internal.Control.Arrow +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.Control.Monad.Fix (ArrowLoop(..)) +#endif ===================================== libraries/base/src/Control/Monad.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} -- | @@ -63,6 +64,9 @@ module Control.Monad ) where import GHC.Internal.Control.Monad +#if __GLASGOW_HASKELL__ < 1000 +import Data.Function (const) +#endif {- $naming @@ -88,3 +92,18 @@ The functions in this module use the following naming conventions: > mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a -} + +#if __GLASGOW_HASKELL__ < 1000 + +-- | Sequence two monadic actions, discarding the result of the first one. +-- +-- Defined as `thenM ma mb = ma >>= const mb`. +-- +-- This can be used to define `(*>) = thenM`. +-- +-- @since 4.23.0.0 +thenM :: (Monad m) => m a -> m b -> m b +thenM ma mb = ma >>= const mb +{-# INLINEABLE thenM #-} + +#endif ===================================== libraries/base/src/Data/Array/Byte.hs ===================================== @@ -8,6 +8,7 @@ -- -- Derived from @primitive@ package. +{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE TypeFamilies #-} @@ -32,7 +33,9 @@ import GHC.Internal.Show (intToDigit) import GHC.Internal.ST (ST(..), runST) import GHC.Internal.Word (Word8(..)) import GHC.Internal.TH.Syntax -import GHC.Internal.TH.Monad +#if __GLASGOW_HASKELL__ >= 1000 +import GHC.Internal.TH.Monad (unsafeCodeCoerce) +#endif import GHC.Internal.TH.Lift import GHC.Internal.ForeignPtr import Prelude ===================================== libraries/base/src/Data/Fixed.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE PolyKinds #-} @@ -91,7 +92,11 @@ import GHC.Internal.TypeLits (KnownNat, natVal) import GHC.Internal.Read import GHC.Internal.Text.ParserCombinators.ReadPrec import GHC.Internal.Text.Read.Lex -import qualified GHC.Internal.TH.Monad as TH +#if __GLASGOW_HASKELL__ < 1000 +import GHC.Internal.TH.Syntax (unsafeCodeCoerce) +#else +import GHC.Internal.TH.Monad (unsafeCodeCoerce) +#endif import qualified GHC.Internal.TH.Lift as TH import Data.Typeable import Prelude @@ -147,7 +152,7 @@ instance (Typeable k,Typeable a) => Data (Fixed (a :: k)) where -- @since template-haskell-2.19.0.0 -- @since base-4.21.0.0 instance TH.Lift (Fixed a) where - liftTyped x = TH.unsafeCodeCoerce (TH.lift x) + liftTyped x = unsafeCodeCoerce (TH.lift x) lift (MkFixed x) = [| MkFixed x |] -- | Types which can be used as a resolution argument to the 'Fixed' type constructor must implement the 'HasResolution' typeclass. ===================================== libraries/base/src/GHC/Base.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} {-# OPTIONS_HADDOCK not-home #-} @@ -139,10 +140,12 @@ module GHC.Base ) where import GHC.Internal.Base hiding ( NonEmpty(..) ) +import GHC.Internal.Data.NonEmpty ( NonEmpty(..) ) +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.Classes import GHC.Internal.CString -import GHC.Internal.Data.NonEmpty ( NonEmpty(..) ) import GHC.Internal.Magic.Dict ( WithDict(..) ) +#endif import GHC.Prim hiding ( -- Hide dataToTag# ops because they are expected to break for @@ -273,6 +276,7 @@ import GHC.Prim hiding , minWord8X16# , minWord8X32# , minWord8X64# +#if __GLASGOW_HASKELL__ >= 1000 -- Don't re-export vector logical primops , andDoubleX2# , andDoubleX4# @@ -389,13 +393,16 @@ import GHC.Prim hiding , sqrtDoubleX4# , sqrtFloatX16# , sqrtDoubleX8# +#endif ) import GHC.Prim.Ext import GHC.Prim.PtrEq import GHC.Internal.Err import GHC.Internal.IO (seq#) +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.Magic +#endif import GHC.Internal.Maybe import GHC.Types hiding ( Unit#, ===================================== libraries/base/src/GHC/Conc.hs ===================================== @@ -119,7 +119,9 @@ module GHC.Conc import GHC.Internal.Conc.IO import GHC.Internal.Conc.Sync +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.STM +#endif #if !defined(mingw32_HOST_OS) import GHC.Internal.Conc.Signal ===================================== libraries/base/src/GHC/Conc/Sync.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} {-# OPTIONS_HADDOCK not-home #-} @@ -89,4 +90,6 @@ module GHC.Conc.Sync ) where import GHC.Internal.Conc.Sync +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.STM +#endif ===================================== libraries/base/src/GHC/Exts.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} {-# OPTIONS_HADDOCK not-home #-} @@ -246,6 +247,7 @@ import GHC.Prim hiding , minWord8X16# , minWord8X32# , minWord8X64# +#if __GLASGOW_HASKELL__ >= 1000 -- Don't re-export vector logical primops , andDoubleX2# , andDoubleX4# @@ -362,6 +364,7 @@ import GHC.Prim hiding , sqrtDoubleX4# , sqrtFloatX16# , sqrtDoubleX8# +#endif ) import GHC.Prim.Ext ===================================== libraries/base/src/GHC/Fingerprint.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} module GHC.Fingerprint ( @@ -10,6 +11,8 @@ module GHC.Fingerprint ( import GHC.Internal.Fingerprint +#if __GLASGOW_HASKELL__ >= 1000 + import Data.Function (($)) import Control.Monad (return, when) import Data.Bool (not, (&&)) @@ -51,3 +54,5 @@ getFileHash path = withBinaryFile path ReadMode $ \ hdl -> ) return (if isFinished then Just chunkSize else Nothing) in fingerprintBufferedStream readChunk + +#endif ===================================== libraries/base/src/GHC/IO/Handle.hs ===================================== @@ -1,4 +1,10 @@ +{-# LANGUAGE CPP #-} +#if __GLASGOW_HASKELL__ < 1000 +{-# LANGUAGE Trustworthy #-} +#else {-# LANGUAGE Safe #-} +#endif +{-# LANGUAGE RecordWildCards #-} -- | -- @@ -75,3 +81,19 @@ module GHC.IO.Handle ) where import GHC.Internal.IO.Handle + +#if __GLASGOW_HASKELL__ < 1000 + +import GHC.Internal.Base (($), IO, return) +import GHC.Internal.IO.Handle.Types (Handle__ (..)) +import GHC.Internal.IO.Handle.Internals (withHandle_) + +-- | Return the current 'NewlineMode' for the specified 'Handle'. +-- +-- @since 4.23.0.0 +hGetNewlineMode :: Handle -> IO NewlineMode +hGetNewlineMode hdl = + withHandle_ "hGetNewlineMode" hdl $ \Handle__{..} -> + return NewlineMode{ inputNL = haInputNL, outputNL = haOutputNL } + +#endif ===================================== libraries/base/src/GHC/RTS/Flags.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE DeriveGeneric #-} @@ -388,11 +389,13 @@ internal_to_base_MiscFlags i@Internal.MiscFlags{..} = internal_to_base_ioManager :: Internal.IoManagerFlag -> IoManagerFlag internal_to_base_ioManager Internal.IoManagerFlagAuto = IoManagerFlagAuto internal_to_base_ioManager Internal.IoManagerFlagSelect = IoManagerFlagSelect +#if __GLASGOW_HASKELL__ >= 1000 internal_to_base_ioManager Internal.IoManagerFlagPoll = IoManagerFlagAuto -- This is a lie, we cannot translate poll. We cannot translate -- accurately because want to freeze the API of the the compat RTS flags -- here. Using "auto" is the least bad translation. -- https://github.com/haskell/core-libraries-committee/issues/362 +#endif internal_to_base_ioManager Internal.IoManagerFlagMIO = IoManagerFlagMIO internal_to_base_ioManager Internal.IoManagerFlagWinIO = IoManagerFlagWinIO internal_to_base_ioManager Internal.IoManagerFlagWin32Legacy = IoManagerFlagWin32Legacy ===================================== libraries/base/src/GHC/Unicode.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} {-# OPTIONS_HADDOCK not-home #-} @@ -44,4 +45,6 @@ module GHC.Unicode ) where import GHC.Internal.Unicode +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.Unicode.Version +#endif ===================================== libraries/base/src/GHC/Weak.hs ===================================== @@ -25,9 +25,8 @@ module GHC.Weak -- this handler will be ignored. setFinalizerExceptionHandler, getFinalizerExceptionHandler, - printToHandleFinalizerExceptionHandler + GHC.Weak.Finalize.printToHandleFinalizerExceptionHandler ) where import GHC.Internal.Weak -import GHC.Internal.Weak.Finalize import GHC.Weak.Finalize ===================================== libraries/base/src/GHC/Weak/Finalize.hs ===================================== @@ -7,7 +7,7 @@ module GHC.Weak.Finalize -- this handler will be ignored. setFinalizerExceptionHandler , getFinalizerExceptionHandler - , printToHandleFinalizerExceptionHandler + , GHC.Weak.Finalize.printToHandleFinalizerExceptionHandler -- * Internal , GHC.Weak.Finalize.runFinalizerBatch ) where ===================================== libraries/base/src/Prelude.hs ===================================== @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE ExplicitNamespaces #-} @@ -176,14 +177,16 @@ import GHC.Internal.Data.Maybe import GHC.Internal.Data.Traversable ( Traversable(..) ) import GHC.Internal.Data.Tuple -import GHC.Internal.Base hiding ( foldr, mapM, sequence ) +#if __GLASGOW_HASKELL__ >= 1000 import GHC.Internal.Classes import GHC.Internal.Err +import GHC.Internal.Prim (seq) +import GHC.Internal.Types +#endif +import GHC.Internal.Base hiding ( foldr, mapM, sequence ) import Text.Read import GHC.Internal.Enum import GHC.Internal.Num -import GHC.Internal.Prim (seq) import GHC.Internal.Real import GHC.Internal.Float import GHC.Internal.Show -import GHC.Internal.Types ===================================== libraries/base/src/System/IO.hs ===================================== @@ -279,7 +279,11 @@ import GHC.IO.StdHandles stdout, stderr ) +#if __GLASGOW_HASKELL__ < 1000 +import GHC.Internal.System.IO (fixIO) +#else import GHC.Internal.Control.Monad.Fix (fixIO) +#endif import Control.Monad (return, (>>=)) import Control.Exception (ioError) import Data.Eq ((==)) ===================================== libraries/base/src/System/Mem/Weak.hs ===================================== @@ -78,7 +78,7 @@ module System.Mem.Weak ( -- this handler will be ignored. setFinalizerExceptionHandler, getFinalizerExceptionHandler, - printToHandleFinalizerExceptionHandler, + GHC.Weak.printToHandleFinalizerExceptionHandler, -- * A precise semantics View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/15d27c8292e19e545263fd319884f6c… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/15d27c8292e19e545263fd319884f6c… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/mangoiv/ghc-9.12-bp] 11 commits: Fix missing profiling header for origin_thunk frame.
by Magnus (@MangoIV) 20 May '26

20 May '26
Magnus pushed to branch wip/mangoiv/ghc-9.12-bp at Glasgow Haskell Compiler / GHC Commits: 2aacc599 by Andreas Klebinger at 2026-05-20T11:51:11+02:00 Fix missing profiling header for origin_thunk frame. Fixes #27007 (cherry picked from commit 63ae8eb38c54eaba77949b048a3621a5f4ca76e3) - - - - - 0acea5fa by Luite Stegeman at 2026-05-20T11:51:13+02:00 bytecode: Carefully SLIDE off the end of a stack chunk The SLIDE bytecode instruction was not checking for stack chunk boundaries and could corrupt the stack underflow frame, leading to crashes. We add a check to use safe writes if we cross the chunk boundary and also handle stack underflow if Sp is advanced past the underflow frame. fix #27001 (cherry picked from commit 72b20fc0ad4b6ad12c67f686af5cb42700656886) - - - - - b2e91dc8 by Andreas Klebinger at 2026-05-20T11:51:13+02:00 Configure: Fix check for --target support in stage0 CC The check FP_PROG_CC_LINKER_TARGET used $CC unconditionally to check for --target support. However this fails for the stage0 config where the C compiler used is not $CC but $CC_STAGE0. Since we already pass the compiler under test into the macro I simply changed it to use that instead. Fixes #26999 (cherry picked from commit 43638643adbe999de8d2288a40bdd15c602f6481) - - - - - 682654f0 by Ian Duncan at 2026-05-20T11:51:14+02:00 AArch64: fix MOVK regUsageOfInstr to mark dst as both read and written MOVK (move with keep) modifies only a 16-bit slice of the destination register, so the destination is both read and written. The register allocator must know this to avoid clobbering live values. Update regUsageOfInstr to list the destination in both src and dst sets. No regression test: triggering the misallocation requires specific register pressure around a MOVK sequence, which is difficult to reliably provoke from Haskell source. (cherry picked from commit 2823b03966e495581f4695f07649c5885306b656) - - - - - a50fabdf by Zubin Duggal at 2026-05-20T11:51:14+02:00 compiler/ffi: Collapse void pointer chains in capi wrappers New gcc/clang treat -Wincompatible-pointer-types as an error by default. Since C only allows implicit conversion from void*, not void**, capi wrappers for functions taking e.g. abstract** would fail to compile when the Haskell type Ptr (Ptr Abstract) was naively translated to void**. Collapse nested void pointers to a single void* when the pointee type has no known C representation. Fixes #26852 (cherry picked from commit 80e2dd4f084eff9cc857b31daf9ea2e9e460c727) - - - - - b62022a9 by Zubin Duggal at 2026-05-20T11:51:14+02:00 hadrian: Don't include the package hash in the haddock directory Since GHC 9.8 and hash_unit_ids, haddock urls have looked like`ghc-9.10.3/doc/html/libraries/base-4.20.2.0-39f9/**/*.html` The inclusion of the hash makes it hard for downstream non-boot packages to properly link to these files, as the hash is not part of a standard cabal substitution. Since we only build one version of each package, we don't need the hash to disambiguate anything, we can just remove it. Fixes #26635 (cherry picked from commit 07267f79d91169f474cacc8bcd38d76a6e97887d) - - - - - 0f95ad43 by ARATA Mizuki at 2026-05-20T11:51:14+02:00 rts: Align stack to 64-byte boundary in StgRun on x86 When LLVM spills AVX/AVX-512 vector registers to the stack, it requires 32-byte (__m256) or 64-byte (__m512) alignment. If the stack is not sufficiently aligned, LLVM inserts a realignment prologue that reserves %rbp as a frame pointer, conflicting with GHC's use of %rbp as an STG callee-saved register and breaking the tail-call-based calling convention. Previously, GHC worked around this by lying to LLVM about the stack alignment and rewriting aligned vector loads/stores (VMOVDQA, VMOVAPS) to unaligned ones (VMOVDQU, VMOVUPS) in the LLVM Mangler. This had two problems: - It did not extend to AVX-512, which requires 64-byte alignment. (#26595) - When Haskell calls a C function that takes __m256/__m512 arguments on the stack, the callee requires genuine alignment, which could cause a segfault. (#26822) This patch genuinely aligns the stack to 64 bytes in StgRun by saving the original stack pointer before alignment and restoring it in StgReturn. We now unconditionally advertise 64-byte stack alignment to LLVM for all x86 targets, making rewriteAVX in the LLVM Mangler unnecessary. STG_RUN_STACK_FRAME_SIZE is increased from 48 to 56 bytes on non-Windows x86-64 to store the saved stack pointer. Closes #26595 and #26822 Co-Authored-By: Claude Opus 4.5 <noreply(a)anthropic.com> (cherry picked from commit a5ec467ee3d4e77c026437a545981269acde3434) - - - - - 6726c914 by Wen Kokke at 2026-05-20T11:51:14+02:00 Fix race condition between flushEventLog and start/endEventLogging. This commit changes `flushEventLog` to acquire/release the `state_change` mutex to prevent interleaving with `startEventLogging` and `endEventLogging`. In the current RTS, `flushEventLog` _does not_ acquire this mutex, which may lead to eventlog corruption on the following interleaving: - `startEventLogging` writes the new `EventLogWriter` to `event_log_writer`. - `flushEventLog` flushes some events to `event_log_writer`. - `startEventLogging` writes the eventlog header to `event_log_writer`. This causes the eventlog to be written out in an unreadable state, with one or more events preceding the eventlog header. This commit renames the old function to `flushEventLog_` and defines `flushEventLog` simply as: ```c void flushEventLog(Capability **cap USED_IF_THREADS) { ACQUIRE_LOCK(&state_change_mutex); flushEventLog_(cap); RELEASE_LOCK(&state_change_mutex); } ``` The old function is still needed internally within the compilation unit, where it is used in `endEventLogging` in a context where the `state_change` mutex has already been acquired. I've chosen to mark `flushEventLog_` as static and let other uses of `flushEventLog` within the RTS refer to the new version. There is one use in `hs_init_ghc` via `flushTrace`, where the new locking behaviour should be harmless, and one use in `handle_tick`, which I believe was likely vulnerable to the same race condition, so the new locking behaviour is desirable. I have not added a test. The behaviour is highly non-deterministic and requires a program that concurrently calls `flushEventLog` and `startEventLogging`/`endEventLogging`. I encountered the issue while developing `eventlog-socket` and within that context have verified that my patch likely addresses the issue: a test that used to fail within the first dozen or so runs now has been running on repeat for several hours. (cherry picked from commit 3d6492ce311611707e80b2594103ddbe93fc6c76) - - - - - dbcd6032 by Luite Stegeman at 2026-05-20T11:51:14+02:00 Windows: remove StgAsyncIOResult and fix crash/leaks In stg_block_async{_void}, a stack slot was reserved for an StgAsyncIOResult. This slot would be filled by the IO manager upon completion of the async call. However, if the blocked thread was interrupted by an async exception, we would end up in an invalid state: - If the blocked computation was never re-entered, the StgAsyncIOResult would never be freed. - If the blocked computation was re-entered, the thread would find an unitialized stack slot for the StgAsyncIOResult, leading to a crash reading its fields, or freeing the pointer. We fix this by removing the StgAsyncIOResult altogether and writing the result directly to the stack. Fixes #26341 (cherry picked from commit fcf092dda534cc38637d1f7920aa0dae58fe5273) - - - - - 7bc3cd73 by mangoiv at 2026-05-20T11:51:14+02:00 rts: cast Sp_plusW to StgPtr to appease gcc - - - - - d93c4511 by mangoiv at 2026-05-20T11:51:14+02:00 rts: disable out of bounds array warning for sometimes inlined rts function - - - - - 48 changed files: - compiler/GHC/CmmToAsm/AArch64/Instr.hs - compiler/GHC/CmmToLlvm.hs - compiler/GHC/CmmToLlvm/Config.hs - compiler/GHC/CmmToLlvm/Mangler.hs - compiler/GHC/Driver/Config/CmmToLlvm.hs - compiler/GHC/HsToCore/Foreign/C.hs - hadrian/bindist/Makefile - hadrian/src/CommandLine.hs - hadrian/src/Context.hs - hadrian/src/Settings/Builders/Cabal.hs - m4/fp_prog_cc_linker_target.m4 - rts/HeapStackCheck.cmm - rts/IOManager.c - rts/Interpreter.c - rts/PrimOps.cmm - rts/RtsSymbols.c - rts/StgCRun.c - rts/StgMiscClosures.cmm - rts/Threads.c - rts/eventlog/EventLog.c - rts/include/rts/Constants.h - rts/include/rts/storage/ClosureMacros.h - rts/include/rts/storage/TSO.h - rts/include/stg/MiscClosures.h - rts/win32/AsyncMIO.c - rts/win32/AsyncMIO.h - + testsuite/tests/bytecode/T27001.hs - + testsuite/tests/bytecode/T27001.stdout - testsuite/tests/bytecode/all.T - + testsuite/tests/concurrent/should_run/T26341.hs - + testsuite/tests/concurrent/should_run/T26341.stdout - + testsuite/tests/concurrent/should_run/T26341a.hs - + testsuite/tests/concurrent/should_run/T26341a.stdout - + testsuite/tests/concurrent/should_run/T26341b.hs - + testsuite/tests/concurrent/should_run/T26341b.stdout - testsuite/tests/concurrent/should_run/all.T - + testsuite/tests/ffi/should_compile/T26852.h - + testsuite/tests/ffi/should_compile/T26852.hs - + testsuite/tests/ffi/should_compile/T26852.stderr - testsuite/tests/ffi/should_compile/all.T - + testsuite/tests/simd/should_run/StackAlignment32.hs - + testsuite/tests/simd/should_run/StackAlignment32.stdout - + testsuite/tests/simd/should_run/StackAlignment32_main.c - + testsuite/tests/simd/should_run/StackAlignment64.hs - + testsuite/tests/simd/should_run/StackAlignment64.stdout - + testsuite/tests/simd/should_run/StackAlignment64_main.c - testsuite/tests/simd/should_run/all.T - utils/deriveConstants/Main.hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b4cc2def845bffa5d7d00fd9e24c37… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b4cc2def845bffa5d7d00fd9e24c37… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
[Git][ghc/ghc][wip/jeltsch/base-buildable-with-ghc-9-14] 28 commits: AArch64: use ASR not LSR for MO_U_Shr at W8/W16
by Wolfgang Jeltsch (@jeltsch) 20 May '26

20 May '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/base-buildable-with-ghc-9-14 at Glasgow Haskell Compiler / GHC Commits: 50188615 by Ian Duncan at 2026-05-14T13:45:07+02:00 AArch64: use ASR not LSR for MO_U_Shr at W8/W16 The unsigned right shift (MO_U_Shr) for sub-word widths (W8, W16) with a variable shift amount was emitting ASR (arithmetic/signed shift right) after zero-extending with UXTB/UXTH. This should be LSR (logical/unsigned shift right). After zero-extension the upper bits happen to be 0 so ASR produces the same result, but it is semantically wrong and would break if the zero-extension were ever optimized away. Includes assembly output test (grep for lsr) and runtime test verifying unsigned right shift of Word8 and Word16 values. - - - - - 28666fbf by Vladislav Zavialov at 2026-05-19T12:44:05-04:00 Add type families: Tuple, Constraints, Tuple#, Sum# (#27179) These type families map tuples of types to the corresponding Tuple<N>, Tuple<N>#, CTuple<N>, and Sum<N># types. Some examples at N=2: Tuple (Int, Bool) = Tuple2 Int Bool Constraints (Show a, Eq a) = CTuple2 (Show a) (Eq a) Tuple# (Int#, Float#) = Tuple2# Int# Float# Sum# (Int#, Float#) = Sum2# Int# Float# See GHC Proposal #145 "Non-punning list and tuple syntax". To make the Sum# instance at N=64 possible, this patch also introduces the Sum64# constructor declaration and bumps mAX_SUM_SIZE from 63 to 64. Metric Increase: ghc_experimental_dir - - - - - 41c2448b by Wen Kokke at 2026-05-19T12:44:53-04:00 rts: Add IPE event class for -l This commit adds a new IPE event class to the -l RTS flag. Previously, IPE events were enabled unconditionally. However, the IPE events can easily grow to hundreds or thousands of megabytes. With the new event class you can pass, e.g., -l-I to disable IPE events. - - - - - 62536551 by Wen Kokke at 2026-05-19T12:44:53-04:00 ghc-internal: Add TraceFlags.traceIPE - - - - - e45312d1 by Wen Kokke at 2026-05-19T12:44:53-04:00 testsuite: Add test for TraceFlags.traceIpe - - - - - 4768d9aa by Wen Kokke at 2026-05-19T12:44:53-04:00 ghc-internal: Add DebugFlags.ipe - - - - - bc1b5c69 by Wen Kokke at 2026-05-19T12:44:53-04:00 testsuite: Add test for DebugFlags.ipe - - - - - 0da1543f by Duncan Coutts at 2026-05-19T12:45:37-04:00 Document removal of the signal-based interval timer Update mentions within the RTS section of the users guide. Add a changelog entry. - - - - - b2911514 by Duncan Coutts at 2026-05-19T12:45:37-04:00 Fix section for an recent changelog entry - - - - - d6d76a7a by David Eichmann at 2026-05-19T12:46:19-04:00 ghc-toolchain: implement llvm program versioning logic - - - - - 2dd36fa3 by Wolfgang Jeltsch at 2026-05-20T04:49:52-04:00 Turn `Trustworthy` into `Safe` in `base` where possible - - - - - f4399dd1 by Wolfgang Jeltsch at 2026-05-20T04:50:37-04:00 Make the current `base` buildable with GHC 10.0 - - - - - 2b7c1a4f by Wolfgang Jeltsch at 2026-05-20T12:13:33+03:00 Disable hiding of imported SIMD operations for GHC 9.14 - - - - - e0a5fc72 by Wolfgang Jeltsch at 2026-05-20T12:13:33+03:00 Disable some imports into `GHC.Base` for GHC 9.14 - - - - - 27d4dc85 by Wolfgang Jeltsch at 2026-05-20T12:13:33+03:00 Make `thenM` available with GHC 9.14 - - - - - 239ac5a5 by Wolfgang Jeltsch at 2026-05-20T12:13:33+03:00 Disable separate `ArrowLoop` import for GHC 9.14 - - - - - 29c8acbe by Wolfgang Jeltsch at 2026-05-20T12:13:33+03:00 Make `thenA` available with GHC 9.14 - - - - - c1158bd3 by Wolfgang Jeltsch at 2026-05-20T12:13:33+03:00 Disable `GHC.Internal.STM` import for GHC 9.14 - - - - - acc1a370 by Wolfgang Jeltsch at 2026-05-20T12:13:34+03:00 Add `hGetNewlineMode` for GHC 9.14 - - - - - 328a292d by Wolfgang Jeltsch at 2026-05-20T12:13:34+03:00 Add alternative `fixIO` import for GHC 9.14 - - - - - 09053b49 by Wolfgang Jeltsch at 2026-05-20T12:13:34+03:00 Disable `GHC.Internal.Unicode.Version` import for GHC 9.14 - - - - - 5a4b3727 by Wolfgang Jeltsch at 2026-05-20T12:13:34+03:00 Disable GHC 9.14 `printToHandleFinalizerExceptionHandler` - - - - - 5fb4cea6 by Wolfgang Jeltsch at 2026-05-20T12:13:34+03:00 Disable some imports into `Prelude` for GHC 9.14 - - - - - 384cbad0 by Wolfgang Jeltsch at 2026-05-20T12:14:45+03:00 Add alternative `unsafeCodeCoerce` import for GHC 9.14 - - - - - 4e6af24b by Wolfgang Jeltsch at 2026-05-20T12:14:48+03:00 Disable `GHC.Internal.TH.Monad` import for GHC 9.14 - - - - - 869e5020 by Wolfgang Jeltsch at 2026-05-20T12:14:48+03:00 Use `getFileHash` from `ghc-internal` on GHC 9.14 - - - - - 32ea087c by Wolfgang Jeltsch at 2026-05-20T12:14:48+03:00 Disable translation of `IoManagerFlagPoll` for GHC 9.14 - - - - - ec9be274 by Wolfgang Jeltsch at 2026-05-20T12:14:48+03:00 Strengthen the Safe-Haskell annotation of `GHC.IO.Handle` - - - - - 85 changed files: - + changelog.d/T26979 - changelog.d/dynamic-trace-flags - + changelog.d/ipe-event-class - + changelog.d/lib-add-tuple-tyfam-27179 - + changelog.d/no-more-timer-signal - compiler/GHC/CmmToAsm/AArch64/CodeGen.hs - compiler/GHC/Settings/Constants.hs - docs/users_guide/profiling.rst - docs/users_guide/runtime_control.rst - libraries/base/src/Control/Applicative.hs - libraries/base/src/Control/Arrow.hs - libraries/base/src/Control/Exception.hs - libraries/base/src/Control/Monad.hs - libraries/base/src/Control/Monad/IO/Class.hs - libraries/base/src/Data/Array/Byte.hs - libraries/base/src/Data/Data.hs - libraries/base/src/Data/Fixed.hs - libraries/base/src/Data/List/NonEmpty.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/Conc/Sync.hs - libraries/base/src/GHC/Exts.hs - libraries/base/src/GHC/Fingerprint.hs - libraries/base/src/GHC/IO/Handle.hs - libraries/base/src/GHC/RTS/Flags.hs - libraries/base/src/GHC/Unicode.hs - libraries/base/src/GHC/Weak.hs - libraries/base/src/GHC/Weak/Finalize.hs - libraries/base/src/Numeric.hs - libraries/base/src/Prelude.hs - libraries/base/src/System/IO.hs - libraries/base/src/System/Mem/Weak.hs - libraries/base/src/System/Timeout.hs - libraries/ghc-experimental/src/Data/Sum/Experimental.hs - libraries/ghc-experimental/src/Data/Tuple/Experimental.hs - libraries/ghc-internal/src/GHC/Internal/Base.hs - libraries/ghc-internal/src/GHC/Internal/Exts.hs - libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc - libraries/ghc-internal/src/GHC/Internal/Types.hs - m4/ghc_toolchain.m4 - rts/IPE.c - rts/RtsFlags.c - rts/Trace.c - rts/Trace.h - rts/include/rts/EventLogWriter.h - rts/include/rts/Flags.h - + testsuite/tests/codeGen/should_gen_asm/aarch64-shl-subword.asm - + testsuite/tests/codeGen/should_gen_asm/aarch64-shl-subword.hs - + testsuite/tests/codeGen/should_gen_asm/aarch64-ushr-subword.asm - + testsuite/tests/codeGen/should_gen_asm/aarch64-ushr-subword.hs - testsuite/tests/codeGen/should_gen_asm/all.T - + testsuite/tests/codeGen/should_run/aarch64-subword-ops.hs - + testsuite/tests/codeGen/should_run/aarch64-subword-ops.stdout - + testsuite/tests/codeGen/should_run/aarch64-ushr-subword-run.hs - + testsuite/tests/codeGen/should_run/aarch64-ushr-subword-run.stdout - testsuite/tests/codeGen/should_run/all.T - testsuite/tests/ghci/scripts/ListTuplePunsPprNoAbbrevTuple.stdout - testsuite/tests/ghci/scripts/all.T - 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/parser/should_compile/ListTuplePunsSuccess1.hs - testsuite/tests/parser/should_compile/all.T - + testsuite/tests/parser/should_fail/ListTuplePunsFail6.hs - + testsuite/tests/parser/should_fail/ListTuplePunsFail6.stderr - testsuite/tests/parser/should_fail/all.T - testsuite/tests/parser/should_run/ListTuplePunsConstraints.hs - testsuite/tests/profiling/should_run/callstack001.stdout - + testsuite/tests/rts/T25275/DebugIpe.hs - + testsuite/tests/rts/T25275/T25275_A.stdout - + testsuite/tests/rts/T25275/T25275_B.stdout - + testsuite/tests/rts/T25275/T25275_C.stdout - + testsuite/tests/rts/T25275/T25275_D.stdout - + testsuite/tests/rts/T25275/TraceIpe.hs - + testsuite/tests/rts/T25275/all.T - + testsuite/tests/typecheck/should_compile/T23135.hs - testsuite/tests/typecheck/should_compile/all.T - utils/ghc-toolchain/exe/Main.hs - utils/ghc-toolchain/src/GHC/Toolchain/Program.hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/f6bcebb0c1b26572b7ee4cc4258b33… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/f6bcebb0c1b26572b7ee4cc4258b33… You're receiving this email because of your account on gitlab.haskell.org.
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • ...
  • 1071
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.