[Git][ghc/ghc][wip/romes/hadrian-cross-stage2-rebase_SVEN_FINAL] Delete libffi-tarballs
by Sven Tennie (@supersven) 17 Feb '26
by Sven Tennie (@supersven) 17 Feb '26
17 Feb '26
Sven Tennie pushed to branch wip/romes/hadrian-cross-stage2-rebase_SVEN_FINAL at Glasgow Haskell Compiler / GHC
Commits:
9de31886 by Sven Tennie at 2026-02-17T18:04:52+01:00
Delete libffi-tarballs
Must have been an accidential commit...
- - - - -
1 changed file:
- − libffi-tarballs
Changes:
=====================================
libffi-tarballs deleted
=====================================
@@ -1 +0,0 @@
-Subproject commit 7c51059557b68d29820a0a87cebfa6fe73c8adf5
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9de31886ed836ae3251f8df8334fc17…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9de31886ed836ae3251f8df8334fc17…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/hadrian-cross-stage2-rebase_SVEN_FINAL] 2 commits: No more cross stage special cases
by Sven Tennie (@supersven) 17 Feb '26
by Sven Tennie (@supersven) 17 Feb '26
17 Feb '26
Sven Tennie pushed to branch wip/romes/hadrian-cross-stage2-rebase_SVEN_FINAL at Glasgow Haskell Compiler / GHC
Commits:
aadf21d5 by Sven Tennie at 2026-02-16T19:42:57+01:00
No more cross stage special cases
- - - - -
fb1b050a by Sven Tennie at 2026-02-17T17:16:21+01:00
Try another variant of interpreter configuration
- - - - -
2 changed files:
- hadrian/src/Settings/Packages.hs
- hadrian/src/Settings/Program.hs
Changes:
=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -25,14 +25,11 @@ packageArgs = do
-- immediately and may lead to cyclic dependencies.
-- See: https://gitlab.haskell.org/ghc/ghc/issues/16809.
cross = flag CrossCompiling
- haveCurses = any (/= "") <$> traverse (flip buildSetting stage) [ CursesIncludeDir, CursesLibDir ]
-
- -- Check if the bootstrap compiler has the same version as the one we
- -- are building. This is used to build cross-compilers
- bootCross = (==) <$> ghcVersionStage (stage0InTree) <*> ghcVersionStage Stage1
+ haveCurses = any (/= "") <$> traverse (`buildSetting` stage) [ CursesIncludeDir, CursesLibDir ]
compilerStageOption f = buildingCompilerStage' . f =<< expr flavour
+ isCrossStage <- staged crossStage
cursesIncludeDir <- staged (buildSetting CursesIncludeDir)
cursesLibraryDir <- staged (buildSetting CursesLibDir)
ffiIncludeDir <- staged (buildSetting FfiIncludeDir)
@@ -53,7 +50,7 @@ packageArgs = do
-- for Stage0 only so we can link ghc-pkg against it, so there is little
-- reason to spend the effort to optimise it.
, package cabal ?
- andM [stage0, expr(notM cross)] ? builder Ghc ? arg "-O0"
+ stage0 ? builder Ghc ? arg "-O0"
------------------------------- compiler -------------------------------
, package compiler ? mconcat
@@ -71,7 +68,7 @@ packageArgs = do
-- These files take a very long time to compile with -O1,
-- so we use -O0 for them just in Stage0 to speed up the
-- build but not affect Stage1+ executables
- , inputs ["**/GHC/Hs/Instances.hs", "**/GHC/Driver/Session.hs"] ? andM [stage0, expr(notM cross)] ?
+ , inputs ["**/GHC/Hs/Instances.hs", "**/GHC/Driver/Session.hs"] ? stage0 ?
pure ["-O0"] ]
, builder (Cabal Setup) ? mconcat
@@ -91,7 +88,7 @@ packageArgs = do
-- on the host and must rely on external interpreter to load
-- target code, otherwise enable for stage2 since that runs on
-- the target and can use target's own ghci object linker
- [ andM [expr (ghcWithInterpreter stage), orM [expr (notM cross), stage2]] `cabalFlag` "internal-interpreter"
+ [ expr (ghcWithInterpreter stage) `cabalFlag` "internal-interpreter"
, orM [ notM cross, haveCurses ] `cabalFlag` "terminfo"
, arg "-build-tool-depends"
, staged (buildFlag UseLibzstd) `cabalFlag` "with-libzstd"
@@ -113,8 +110,8 @@ packageArgs = do
, compilerStageOption ghcDebugAssertions ? arg "-DDEBUG" ]
, builder (Cabal Flags) ? mconcat
- [ andM [expr (ghcWithInterpreter stage), orM [expr (notM cross), stage1]] `cabalFlag` "interpreter"
- , andM [expr (ghcWithInterpreter stage), notM (expr cross)] `cabalFlag` "internal-interpreter"
+ [ expr (ghcWithInterpreter stage) `cabalFlag` "interpreter"
+ , andM [expr (ghcWithInterpreter stage), notM (pure isCrossStage)] `cabalFlag` "internal-interpreter"
, ifM stage0
-- We build a threaded stage 1 if the bootstrapping compiler
-- supports it.
@@ -165,10 +162,8 @@ packageArgs = do
--
builder (Cabal Setup) ? cabalExtraDirs ffiIncludeDir ffiLibraryDir
, builder (Cabal Flags) ? mconcat
- [ ifM stage0
- (andM [cross, bootCross] `cabalFlag` "internal-interpreter")
- (arg "internal-interpreter")
- , stage0 `cabalFlag` "bootstrap"
+ [ stage0 `cabalFlag` "bootstrap",
+ andM [expr (ghcWithInterpreter stage), notM (pure isCrossStage)] `cabalFlag` "internal-interpreter"
]
]
=====================================
hadrian/src/Settings/Program.hs
=====================================
@@ -6,7 +6,6 @@ module Settings.Program
import Base
import Context
import Oracles.Flavour
-import Oracles.Flag
import Packages
import GHC.Platform.ArchOS
@@ -40,7 +39,6 @@ programContext stage pkg = do
-- Also checks whether the target supports GHCi.
ghcWithInterpreter :: Stage -> Action Bool
ghcWithInterpreter stage = do
- is_cross <- flag CrossCompiling
goodOs <- anyTargetOs stage [ OSMinGW32, OSLinux, OSSolaris2
, OSFreeBSD, OSDragonFly, OSNetBSD, OSOpenBSD
, OSDarwin, OSKFreeBSD
@@ -58,6 +56,4 @@ ghcWithInterpreter stage = do
-- fall back on dynamic linking:
dynamicGhcProgs <- askDynGhcPrograms stage
- -- Maybe this should just be false for cross compilers. But for now
- -- I've kept the old behaviour where it will say yes. (See #25939)
- return $ ((goodOs && goodArch) || dynamicGhcProgs) && (stage >= Stage1 || is_cross)
+ return $ ((goodOs && goodArch) || dynamicGhcProgs) && (stage >= Stage2)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/20a054035434d8e2b881abfb02860a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/20a054035434d8e2b881abfb02860a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fendor/linkable-usage] Add linkable regression test
by Hannes Siebenhandl (@fendor) 17 Feb '26
by Hannes Siebenhandl (@fendor) 17 Feb '26
17 Feb '26
Hannes Siebenhandl pushed to branch wip/fendor/linkable-usage at Glasgow Haskell Compiler / GHC
Commits:
47420bcb by fendor at 2026-02-17T15:03:49+01:00
Add linkable regression test
- - - - -
5 changed files:
- + testsuite/ghc-config/ghc-config
- testsuite/tests/bytecode/TLinkable/Makefile
- testsuite/tests/bytecode/TLinkable/all.T
- + testsuite/tests/bytecode/TLinkable/genSplices2
- + testsuite/tests/bytecode/TLinkable/linkable_bytecodelib.stdout
Changes:
=====================================
testsuite/ghc-config/ghc-config
=====================================
Binary files /dev/null and b/testsuite/ghc-config/ghc-config differ
=====================================
testsuite/tests/bytecode/TLinkable/Makefile
=====================================
@@ -11,3 +11,20 @@ TLinkable_Prep:
TLinkable2_Prep:
./genSplices TLinkable2
'$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) --make -fprefer-byte-code -fwrite-byte-code -v0 TLinkable2.hs
+
+.PHONY: linkable_bytecodelib_Prep linkable_bytecodelib
+PKGCONF01=bytecode.package.conf
+LOCAL_GHC_PKG01='$(GHC_PKG)' --no-user-package-db -f $(PKGCONF01)
+MAIN_MOD=BytecodeUsage
+linkable_bytecodelib_Prep:
+ $(LOCAL_GHC_PKG01) init $(PKGCONF01)
+ mkdir outdir
+ cd outdir && ../genSplices2 $(MAIN_MOD)
+ mv outdir/$(MAIN_MOD).hs $(MAIN_MOD).hs
+ cd outdir && $(TEST_HC) -bytecodelib -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -o testpkg-1.2.3.4-XXX.bytecodelib -fbyte-code -fwrite-interface -fwrite-byte-code -this-unit-id=testpkg-1.2.3.4-XXX \
+ *.hs
+ $(LOCAL_GHC_PKG01) register --force outdir/bytecode.pkg
+
+linkable_bytecodelib:
+ $(TEST_HC) $(TEST_HC_OPTS) $(ghcThWayFlags) --make -fprefer-byte-code $(MAIN_MOD) -package testpkg -package-db $(PKGCONF01) +RTS -l -hT -i0.001 -RTS
=====================================
testsuite/tests/bytecode/TLinkable/all.T
=====================================
@@ -2,6 +2,9 @@
# Bytecode libraries
# Depend on that bytecode, look at the bytecode library tests to make sure this ends up in the EPS
+def normaliseDynlibNames(str):
+ return re.sub(r'-ghc[0-9.]+\.', '-ghc<VERSION>.', str)
+
test('TLinkable',
[ collect_compiler_stats('bytes allocated',2),
pre_cmd('$MAKE -s --no-print-directory TLinkable_Prep'),
@@ -19,3 +22,12 @@ test('TLinkable2',
],
compile,
['-fprefer-byte-code -fforce-recomp ' + config.ghc_th_way_flags])
+
+test('linkable_bytecodelib',
+ [ extra_files(["genSplices2"])
+ , normalise_errmsg_fun(normaliseDynlibNames)
+ , pre_cmd('$MAKE -s --no-print-directory linkable_bytecodelib_Prep')
+ , copy_files
+ , req_bco ],
+ makefile_test,
+ [])
=====================================
testsuite/tests/bytecode/TLinkable/genSplices2
=====================================
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+MODNAME=${1}
+NMOD=${2:-20} # Default 20 modules
+NDEF=${3:-50} # Default 50 functions per module
+
+# Generate the modules
+for ((i=1; i<=NMOD; i++)); do
+ module_name="Module$(printf "%03d" $i)"
+ file_path="${module_name}.hs"
+
+ cat > "$file_path" << EOF
+module ${module_name} where
+
+EOF
+
+ for ((j=1; j<=NDEF; j++)); do
+ func_name="func$(printf "%03d" $j)"
+ cat >> "$file_path" << EOF
+{-# NOINLINE ${func_name} #-}
+${func_name} :: Int -> Int
+${func_name} x = x + ${j}
+
+EOF
+ done
+done
+
+# Generate imports section
+imports=""
+for ((i=1; i<=NMOD; i++)); do
+ imports="${imports}import splice Module$(printf "%03d" $i)
+"
+done
+
+# Generate the hard-coded TH expression
+# Build: Module001.func001 1 + Module001.func002 2 + ... + Module{NMOD}.func{NDEF} {NMOD*NDEF}
+expressions=""
+all_mods=""
+for ((i=1; i<=NMOD; i++)); do
+ mod_name="Module$(printf "%03d" $i)"
+ all_mods="${all_mods} ${mod_name}"
+ single_expression=""
+ count=1
+ for ((j=1; j<=NDEF; j++)); do
+ func_name="func$(printf "%03d" $j)"
+ if [ $count -gt 1 ]; then
+ single_expression="${single_expression} + "
+ fi
+ single_expression="${single_expression}${mod_name}.${func_name} ${count}"
+ ((count++))
+ done
+
+ expressions="comp$(printf "%03d" $i) = \$(lift \$ ${single_expression})\\n\\n${expressions}"
+done
+
+# Generate the TH splice file
+cat > bytecode.pkg << EOF
+name: testpkg
+version: 1.2.3.4
+id: testpkg-1.2.3.4-XXX
+key: testpkg-1.2.3.4-XXX
+license: BSD3
+copyright: (c) The Univsersity of Glasgow 2004
+maintainer: glasgow-haskell-users(a)haskell.org
+stability: stable
+homepage: http://www.haskell.org/ghc
+package-url: http://www.haskell.org/ghc
+description: A Test Package
+category: none
+author: simonmar(a)microsoft.com
+exposed: True
+exposed-modules: ${all_mods}
+import-dirs: \${pkgroot}/outdir
+library-dirs: \${pkgroot}/outdir
+include-dirs:
+bytecode-library-dirs: \${pkgroot}/outdir
+hs-libraries: testpkg-1.2.3.4-XXX
+EOF
+
+# Generate the TH splice file
+cat > "${MODNAME}".hs << EOF
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE NumericUnderscores #-}
+{-# LANGUAGE ExplicitLevelImports #-}
+
+module ${MODNAME} where
+
+import splice Language.Haskell.TH.Syntax (Lift(..))
+import Control.Concurrent (threadDelay)
+import splice Prelude (Num(..), ($), Monad(..), pure)
+
+-- Import all generated modules
+${imports}
+
+-- Use from each module
+$(echo -e -n "${expressions}")
+
+EOF
=====================================
testsuite/tests/bytecode/TLinkable/linkable_bytecodelib.stdout
=====================================
@@ -0,0 +1 @@
+[1 of 1] Compiling BytecodeUsage ( BytecodeUsage.hs, BytecodeUsage.o )
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/47420bcbe490a7a36bbcb04fc329ab4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/47420bcbe490a7a36bbcb04fc329ab4…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fendor/stack-annotation-ty] 3 commits: Support more x86 extensions: AVX-512 {BW,DQ,VL} and GFNI
by Hannes Siebenhandl (@fendor) 17 Feb '26
by Hannes Siebenhandl (@fendor) 17 Feb '26
17 Feb '26
Hannes Siebenhandl pushed to branch wip/fendor/stack-annotation-ty at Glasgow Haskell Compiler / GHC
Commits:
14f485ee by ARATA Mizuki at 2026-02-17T09:09:24+09:00
Support more x86 extensions: AVX-512 {BW,DQ,VL} and GFNI
Also, mark AVX-512 ER and PF as deprecated.
AVX-512 instructions can be used for certain 64-bit integer vector operations.
GFNI can be used to implement bitReverse (currently not used by NCG, but LLVM may use it).
Closes #26406
Addresses #26509
- - - - -
016f79d5 by fendor at 2026-02-17T09:16:16-05:00
Hide implementation details from base exception stack traces
Ensure we hide the implementation details of the exception throwing mechanisms:
* `undefined`
* `throwSTM`
* `throw`
* `throwIO`
* `error`
The `HasCallStackBacktrace` should always have a length of exactly 1,
not showing internal implementation details in the stack trace, as these
are vastly distracting to end users.
CLC proposal [#387](https://github.com/haskell/core-libraries-committee/issues/387)
- - - - -
624a8cb5 by fendor at 2026-02-17T15:22:09+01:00
Add optional `SrcLoc` to `StackAnnotation` class
`StackAnnotation`s give access to an optional `SrcLoc` field that
user-added stack annotations can use to provide better backtraces in both error
messages and when decoding the callstack.
We update builtin stack annotations such as `StringAnnotation` and
`ShowAnnotation` to also capture the `SrcLoc` of the current `CallStack`
to improve backtraces by default (if stack annotations are used).
This change is backwards compatible with GHC 9.14.1.
- - - - -
67 changed files:
- compiler/GHC/CmmToAsm/Config.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/Driver/Config/CmmToAsm.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/SysTools/Cpp.hs
- docs/users_guide/9.16.1-notes.rst
- docs/users_guide/phases.rst
- docs/users_guide/using.rst
- libraries/base/changelog.md
- libraries/ghc-experimental/CHANGELOG.md
- libraries/ghc-experimental/src/GHC/Stack/Annotation/Experimental.hs
- + libraries/ghc-experimental/tests/Makefile
- + libraries/ghc-experimental/tests/all.T
- + libraries/ghc-experimental/tests/backtraces/Makefile
- + libraries/ghc-experimental/tests/backtraces/T26806a.hs
- + libraries/ghc-experimental/tests/backtraces/T26806a.stderr
- + libraries/ghc-experimental/tests/backtraces/T26806b.hs
- + libraries/ghc-experimental/tests/backtraces/T26806b.stderr
- + libraries/ghc-experimental/tests/backtraces/T26806c.hs
- + libraries/ghc-experimental/tests/backtraces/T26806c.stderr
- + libraries/ghc-experimental/tests/backtraces/all.T
- libraries/ghc-internal/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/STM.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- + libraries/ghc-internal/tests/backtraces/T15395.hs
- + libraries/ghc-internal/tests/backtraces/T15395.stdout
- libraries/ghc-internal/tests/backtraces/all.T
- libraries/ghc-internal/tests/stack-annotation/ann_frame001.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame002.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame003.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame004.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- testsuite/driver/cpu_features.py
- testsuite/tests/arrows/should_compile/T21301.stderr
- testsuite/tests/codeGen/should_gen_asm/all.T
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.hs
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.hs
- + testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.hs
- testsuite/tests/deSugar/should_fail/DsStrictFail.stderr
- testsuite/tests/deSugar/should_run/T20024.stderr
- testsuite/tests/deSugar/should_run/dsrun005.stderr
- testsuite/tests/deSugar/should_run/dsrun007.stderr
- testsuite/tests/deSugar/should_run/dsrun008.stderr
- testsuite/tests/deriving/should_run/T9576.stderr
- testsuite/tests/ghci/scripts/Defer02.stderr
- testsuite/tests/ghci/scripts/T15325.stderr
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/patsyn/should_run/ghci.stderr
- testsuite/tests/quotes/LiftErrMsgDefer.stderr
- testsuite/tests/safeHaskell/safeLanguage/SafeLang15.stderr
- testsuite/tests/simd/should_run/all.T
- testsuite/tests/type-data/should_run/T22332a.stderr
- testsuite/tests/typecheck/should_run/T10284.stderr
- testsuite/tests/typecheck/should_run/T13838.stderr
- testsuite/tests/typecheck/should_run/T9497a-run.stderr
- testsuite/tests/typecheck/should_run/T9497b-run.stderr
- testsuite/tests/typecheck/should_run/T9497c-run.stderr
- testsuite/tests/unsatisfiable/T23816.stderr
- testsuite/tests/unsatisfiable/UnsatDefer.stderr
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d40ddcc09a573c99485ee110c7db12…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d40ddcc09a573c99485ee110c7db12…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Hide implementation details from base exception stack traces
by Marge Bot (@marge-bot) 17 Feb '26
by Marge Bot (@marge-bot) 17 Feb '26
17 Feb '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
016f79d5 by fendor at 2026-02-17T09:16:16-05:00
Hide implementation details from base exception stack traces
Ensure we hide the implementation details of the exception throwing mechanisms:
* `undefined`
* `throwSTM`
* `throw`
* `throwIO`
* `error`
The `HasCallStackBacktrace` should always have a length of exactly 1,
not showing internal implementation details in the stack trace, as these
are vastly distracting to end users.
CLC proposal [#387](https://github.com/haskell/core-libraries-committee/issues/387)
- - - - -
27 changed files:
- libraries/base/changelog.md
- libraries/ghc-internal/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/STM.hs
- + libraries/ghc-internal/tests/backtraces/T15395.hs
- + libraries/ghc-internal/tests/backtraces/T15395.stdout
- libraries/ghc-internal/tests/backtraces/all.T
- libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- testsuite/tests/arrows/should_compile/T21301.stderr
- testsuite/tests/deSugar/should_fail/DsStrictFail.stderr
- testsuite/tests/deSugar/should_run/T20024.stderr
- testsuite/tests/deSugar/should_run/dsrun005.stderr
- testsuite/tests/deSugar/should_run/dsrun007.stderr
- testsuite/tests/deSugar/should_run/dsrun008.stderr
- testsuite/tests/deriving/should_run/T9576.stderr
- testsuite/tests/ghci/scripts/Defer02.stderr
- testsuite/tests/ghci/scripts/T15325.stderr
- testsuite/tests/patsyn/should_run/ghci.stderr
- testsuite/tests/quotes/LiftErrMsgDefer.stderr
- testsuite/tests/safeHaskell/safeLanguage/SafeLang15.stderr
- testsuite/tests/type-data/should_run/T22332a.stderr
- testsuite/tests/typecheck/should_run/T10284.stderr
- testsuite/tests/typecheck/should_run/T13838.stderr
- testsuite/tests/typecheck/should_run/T9497a-run.stderr
- testsuite/tests/typecheck/should_run/T9497b-run.stderr
- testsuite/tests/typecheck/should_run/T9497c-run.stderr
- testsuite/tests/unsatisfiable/T23816.stderr
- testsuite/tests/unsatisfiable/UnsatDefer.stderr
Changes:
=====================================
libraries/base/changelog.md
=====================================
@@ -25,6 +25,7 @@
* Export `labelThread` from `Control.Concurrent`.([CLC proposal #376](https://github.com/haskell/core-libraries-committee/issues/376))
* Add a new module `System.IO.OS` with operations for obtaining operating-system handles (file descriptors, Windows handles). ([CLC proposal #369](https://github.com/haskell/core-libraries-committee/issues/369))
* Evaluate backtraces for "error" exceptions at the moment they are thrown. ([CLC proposal #383](https://github.com/haskell/core-libraries-committee/issues/383))
+ * Hide implementation details when throwing exceptions in throw and throwSTM. ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387))
## 4.22.0.0 *TBA*
* Shipped with GHC 9.14.1
=====================================
libraries/ghc-internal/src/GHC/Internal/Exception.hs
=====================================
@@ -87,7 +87,7 @@ throw e =
-- Note also the absolutely crucial `noinine` in the RHS!
-- See Note [Hiding precise exception signature in throw]
let se :: SomeException
- !se = noinline (unsafePerformIO (toExceptionWithBacktrace e))
+ !se = noinline (unsafePerformIO (withFrozenCallStack $ toExceptionWithBacktrace e))
in raise# se
-- Note [Capturing the backtrace in throw]
@@ -162,7 +162,12 @@ throw e =
-- primops which allow more precise guidance of the demand analyser's heuristic
-- (e.g. #23847).
--- | @since base-4.20.0.0
+-- | Collect a Backtrace and attach it to the 'Exception'.
+--
+-- It is recommended to use 'withFrozenCallStack' when calling this function
+-- in order to avoid leaking implementation details of 'toExceptionWithBacktrace'.
+--
+-- @since base-4.20.0.0
toExceptionWithBacktrace :: (HasCallStack, Exception e)
=> e -> IO SomeException
toExceptionWithBacktrace e
=====================================
libraries/ghc-internal/src/GHC/Internal/STM.hs
=====================================
@@ -28,7 +28,7 @@ import GHC.Internal.Base
import GHC.Internal.Exception (Exception, toExceptionWithBacktrace, fromException, addExceptionContext)
import GHC.Internal.Exception.Context (ExceptionAnnotation)
import GHC.Internal.Exception.Type (WhileHandling(..))
-import GHC.Internal.Stack (HasCallStack)
+import GHC.Internal.Stack (HasCallStack, withFrozenCallStack)
-- TVars are shared memory locations which support atomic memory
-- transactions.
@@ -187,7 +187,7 @@ throwSTM e = do
-- N.B. Typically use of unsafeIOToSTM is very much frowned upon as this
-- is an easy way to end up with nested transactions. However, we can be
-- certain that toExceptionWithBacktrace will not initiate a transaction.
- se <- unsafeIOToSTM (toExceptionWithBacktrace e)
+ se <- unsafeIOToSTM (withFrozenCallStack $ toExceptionWithBacktrace e)
STM $ raiseIO# se
-- | Exception handling within STM actions.
=====================================
libraries/ghc-internal/tests/backtraces/T15395.hs
=====================================
@@ -0,0 +1,85 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE TypeApplications #-}
+
+import GHC.Internal.Control.Exception
+import GHC.Internal.Data.Foldable (traverse_)
+import GHC.Internal.Exception.Backtrace
+import GHC.Internal.Exception.Context
+import GHC.Internal.Exception.Type
+import GHC.Internal.STM (atomically, throwSTM)
+import qualified GHC.Internal.Stack as HCS
+import qualified GHC.Internal.Stack.Types as HCS
+import Control.Monad (when)
+import qualified Data.List as List
+import System.Exit (exitFailure)
+
+main :: IO ()
+main = do
+ -- Make sure there are HasCallStackBacktraces
+ setBacktraceMechanismState HasCallStackBacktrace True
+ mapM_ (uncurry runCase)
+ [ ("throw", throwAction)
+ , ("throwIO", throwIOAction)
+ , ("error", errorAction)
+ , ("throwSTM", throwSTMAction)
+ , ("undefined", undefinedAction)
+ ]
+
+runCase :: String -> IO () -> IO ()
+runCase name act = do
+ putStrLn $ "=== Validate stack size of '" ++ name ++ "' has length 1"
+ catchAndVerifyStackTraceLength name act
+ putStrLn ""
+
+throwAction :: IO ()
+throwAction = evaluate $ throw $ ErrorCall "my throw error"
+
+throwIOAction :: IO ()
+throwIOAction = throwIO $ ErrorCall "my throwIO error"
+
+errorAction :: IO ()
+errorAction = error "plain error"
+
+throwSTMAction :: IO ()
+throwSTMAction = atomically $ throwSTM $ ErrorCall "my throwSTM error"
+
+undefinedAction :: IO ()
+undefinedAction = evaluate undefined
+
+catchAndVerifyStackTraceLength :: String -> IO () -> IO ()
+catchAndVerifyStackTraceLength name act = do
+ try act >>= \ case
+ Right _ -> do
+ putStrLn $ "Exception expected but got a result for '" ++ name ++ "'"
+ exitFailure
+ Left exc ->
+ verifyBacktraceSize name exc
+
+verifyBacktraceSize :: String -> SomeException -> IO ()
+verifyBacktraceSize label se = do
+ message <- evaluate (displayException se)
+ putStrLn "==== Caught exception:"
+ putStrLn message
+ putStrLn "==== Exception Backtraces:"
+ let backtraces = getExceptionAnnotations @Backtraces $ someExceptionContext se
+ traverse_ validateBacktrace backtraces
+
+validateBacktrace :: Backtraces -> IO ()
+validateBacktrace bt =
+ case btrHasCallStack bt of
+ Nothing -> pure ()
+ Just cs -> do
+ let stack = HCS.getCallStack cs
+
+ traverse_ mustNotReferenceInternalPackages stack
+ traverse_ (putStrLn . prettyCallSite) stack
+ where
+ prettyCallSite (f, loc) = "- " ++ f ++ ", called at " ++ HCS.prettySrcLoc loc
+
+ mustNotReferenceInternalPackages (_, loc) =
+ case List.find (HCS.srcLocPackage loc ==) internalPackages of
+ Just val -> fail $ "Stack trace must not reference '" ++ val ++ "' package."
+ Nothing -> pure ()
+
+internalPackages :: [String]
+internalPackages = ["base", "ghc", "ghc-internal", "ghc-experimental"]
=====================================
libraries/ghc-internal/tests/backtraces/T15395.stdout
=====================================
@@ -0,0 +1,30 @@
+=== Validate stack size of 'throw' has length 1
+==== Caught exception:
+my throw error
+==== Exception Backtraces:
+- throw, called at T15395.hs:35:26 in main:Main
+
+=== Validate stack size of 'throwIO' has length 1
+==== Caught exception:
+my throwIO error
+==== Exception Backtraces:
+- throwIO, called at T15395.hs:38:17 in main:Main
+
+=== Validate stack size of 'error' has length 1
+==== Caught exception:
+plain error
+==== Exception Backtraces:
+- error, called at T15395.hs:41:15 in main:Main
+
+=== Validate stack size of 'throwSTM' has length 1
+==== Caught exception:
+my throwSTM error
+==== Exception Backtraces:
+- throwSTM, called at T15395.hs:44:31 in main:Main
+
+=== Validate stack size of 'undefined' has length 1
+==== Caught exception:
+Prelude.undefined
+==== Exception Backtraces:
+- undefined, called at T15395.hs:47:28 in main:Main
+
=====================================
libraries/ghc-internal/tests/backtraces/all.T
=====================================
@@ -4,3 +4,7 @@ test('T26507', [ when(have_profiling(), extra_ways(['prof']))
, when(js_arch(), skip)
, when(ghc_with_ipe(), skip) # IPE builds include an IPE backtrace section on stderr.
, exit_code(1)], compile_and_run, [''])
+
+# Stack traces shouldn't expose implementation details
+test('T15395', [ when(have_profiling(), extra_ways(['prof']))
+ , when(js_arch(), skip)], compile_and_run, [''])
=====================================
libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
=====================================
@@ -39,7 +39,5 @@ Exception context:
- catch site for throwSTM
- annotateCallStackIO, called at ann_frame005.hs:26:3 in main:Main
- HasCallStack backtrace:
-- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:170:37 in ghc-internal:GHC.Internal.Exception
-- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/STM.hs:190:26 in ghc-internal:GHC.Internal.STM
- throwSTM, called at ann_frame005.hs:55:9 in main:Main
Handler annotation not present in context
=====================================
testsuite/tests/arrows/should_compile/T21301.stderr
=====================================
@@ -4,7 +4,5 @@ T21301.hs:(8,7)-(10,6): Non-exhaustive patterns in case
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/deSugar/should_fail/DsStrictFail.stderr
=====================================
@@ -4,7 +4,5 @@ DsStrictFail.hs:4:12-23: Non-exhaustive patterns in False
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/deSugar/should_run/T20024.stderr
=====================================
@@ -4,7 +4,5 @@ T20024.hs:2:12-32: Non-exhaustive guards in pattern binding
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:431:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/deSugar/should_run/dsrun005.stderr
=====================================
@@ -4,7 +4,5 @@ dsrun005.hs:42:1-18: Non-exhaustive patterns in function f
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/deSugar/should_run/dsrun007.stderr
=====================================
@@ -4,7 +4,5 @@ dsrun007.hs:5:23-25: Missing field in record construction
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:432:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/deSugar/should_run/dsrun008.stderr
=====================================
@@ -4,7 +4,5 @@ dsrun008.hs:2:32-36: Non-exhaustive patterns in (2, x)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/deriving/should_run/T9576.stderr
=====================================
@@ -13,7 +13,5 @@ T9576.hs:6:31: error: [GHC-39999]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/ghci/scripts/Defer02.stderr
=====================================
@@ -71,8 +71,6 @@ Defer01.hs:49:5: warning: [GHC-83865] [-Wdeferred-type-errors (in -Wdefault)]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
*** Exception: Defer01.hs:13:5: error: [GHC-83865]
@@ -82,8 +80,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
*** Exception: Defer01.hs:17:9: error: [GHC-39999]
@@ -93,8 +89,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
<interactive>:10:11: error: [GHC-83865]
@@ -113,8 +107,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
*** Exception: Defer01.hs:30:5: error: [GHC-83865]
@@ -127,8 +119,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
*** Exception: Defer01.hs:33:8: error: [GHC-25897]
@@ -146,8 +136,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
*** Exception: Defer01.hs:38:17: error: [GHC-83865]
@@ -161,8 +149,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
*** Exception: Defer01.hs:42:5: error: [GHC-39999]
@@ -172,8 +158,6 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
<interactive>:16:8: error: [GHC-18872]
@@ -192,7 +176,5 @@ HasCallStack backtrace:
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/ghci/scripts/T15325.stderr
=====================================
@@ -24,7 +24,5 @@ T15325.hs:11:9: warning: [GHC-39999] [-Wdeferred-type-errors (in -Wdefault)]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/patsyn/should_run/ghci.stderr
=====================================
@@ -2,7 +2,5 @@
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/quotes/LiftErrMsgDefer.stderr
=====================================
@@ -11,7 +11,5 @@ LiftErrMsgDefer.hs:14:12: warning: [GHC-28914] [-Wdeferred-type-errors (in -Wdef
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/safeHaskell/safeLanguage/SafeLang15.stderr
=====================================
@@ -4,7 +4,5 @@ SafeLang15.hs:22:9-37: Non-exhaustive patterns in Just p'
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/type-data/should_run/T22332a.stderr
=====================================
@@ -4,7 +4,5 @@ T22332a.hs:18:1-35: Non-exhaustive patterns in Just eq
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:434:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/typecheck/should_run/T10284.stderr
=====================================
@@ -7,7 +7,5 @@ T10284.hs:7:5: error: [GHC-83865]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/typecheck/should_run/T13838.stderr
=====================================
@@ -9,7 +9,5 @@ T13838.hs:6:1: error: [GHC-83865]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/typecheck/should_run/T9497a-run.stderr
=====================================
@@ -19,7 +19,5 @@ T9497a-run.hs:2:8: error: [GHC-88464]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/typecheck/should_run/T9497b-run.stderr
=====================================
@@ -19,7 +19,5 @@ T9497b-run.hs:2:8: error: [GHC-88464]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/typecheck/should_run/T9497c-run.stderr
=====================================
@@ -19,7 +19,5 @@ T9497c-run.hs:2:8: error: [GHC-88464]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/unsatisfiable/T23816.stderr
=====================================
@@ -8,7 +8,5 @@ T23816.hs:18:15: error: [GHC-22250]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
=====================================
testsuite/tests/unsatisfiable/UnsatDefer.stderr
=====================================
@@ -7,7 +7,5 @@ UnsatDefer.hs:20:7: error: [GHC-22250]
(deferred type error)
HasCallStack backtrace:
- collectExceptionAnnotation, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
- toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:89:42 in ghc-internal:GHC.Internal.Exception
throw, called at libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs:435:30 in ghc-internal:GHC.Internal.Control.Exception.Base
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/016f79d54d482de01dd396bd9bf79f9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/016f79d54d482de01dd396bd9bf79f9…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Support more x86 extensions: AVX-512 {BW,DQ,VL} and GFNI
by Marge Bot (@marge-bot) 17 Feb '26
by Marge Bot (@marge-bot) 17 Feb '26
17 Feb '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
14f485ee by ARATA Mizuki at 2026-02-17T09:09:24+09:00
Support more x86 extensions: AVX-512 {BW,DQ,VL} and GFNI
Also, mark AVX-512 ER and PF as deprecated.
AVX-512 instructions can be used for certain 64-bit integer vector operations.
GFNI can be used to implement bitReverse (currently not used by NCG, but LLVM may use it).
Closes #26406
Addresses #26509
- - - - -
21 changed files:
- compiler/GHC/CmmToAsm/Config.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/Driver/Config/CmmToAsm.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/SysTools/Cpp.hs
- docs/users_guide/9.16.1-notes.rst
- docs/users_guide/phases.rst
- docs/users_guide/using.rst
- testsuite/driver/cpu_features.py
- testsuite/tests/codeGen/should_gen_asm/all.T
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.hs
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.hs
- + testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.hs
- testsuite/tests/simd/should_run/all.T
Changes:
=====================================
compiler/GHC/CmmToAsm/Config.hs
=====================================
@@ -31,6 +31,9 @@ data NCGConfig = NCGConfig
, ncgDoConstantFolding :: !Bool -- ^ Perform CMM constant folding
, ncgSseAvxVersion :: Maybe SseAvxVersion -- ^ (x86) SSE and AVX instructions
, ncgAvx512fEnabled :: !Bool
+ , ncgAvx512vlEnabled :: !Bool
+ , ncgAvx512bwEnabled :: !Bool
+ , ncgAvx512dqEnabled :: !Bool
, ncgBmiVersion :: Maybe BmiVersion -- ^ (x86) BMI instructions
, ncgDumpRegAllocStages :: !Bool
, ncgDumpAsmStats :: !Bool
=====================================
compiler/GHC/CmmToAsm/X86/CodeGen.hs
=====================================
@@ -134,6 +134,12 @@ avx2Enabled = do
config <- getConfig
return (ncgSseAvxVersion config >= Just AVX2)
+avx512vlEnabled :: NatM Bool
+avx512vlEnabled = ncgAvx512vlEnabled <$> getConfig
+
+avx512dqEnabled :: NatM Bool
+avx512dqEnabled = ncgAvx512dqEnabled <$> getConfig
+
cmmTopCodeGen
:: RawCmmDecl
-> NatM [NatCmmDecl (Alignment, RawCmmStatics) Instr]
@@ -1314,6 +1320,8 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
sse4_1 <- sse4_1Enabled
sse4_2 <- sse4_2Enabled
avx <- avxEnabled
+ avx512vl <- avx512vlEnabled
+ avx512dq <- avx512dqEnabled
case mop of
MO_F_Eq _ -> condFltReg is32Bit EQQ x y
MO_F_Ne _ -> condFltReg is32Bit NE x y
@@ -1432,57 +1440,76 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
MO_V_Sub l w | l * widthInBits w == 128 -> vector_int_op_sse PSUB l w x y
| otherwise -> needLlvm mop
MO_V_Mul 16 W8 -> vector_int8x16_mul_sse2 x y
- MO_V_Mul l@8 w@W16 -> vector_int_op_sse PMULL l w x y -- PMULLW (SSE2)
- MO_V_Mul l@4 w@W32 | sse4_1 -> vector_int_op_sse PMULL l w x y -- PMULLD (SSE4.1)
+ MO_V_Mul l@8 w@W16 | avx -> vector_int_op_avx VPMULL l w x y -- VPMULLW (AVX)
+ | otherwise -> vector_int_op_sse PMULL l w x y -- PMULLW (SSE2)
+ MO_V_Mul l@4 w@W32 | avx -> vector_int_op_avx VPMULL l w x y -- VPMULLD (AVX)
+ | sse4_1 -> vector_int_op_sse PMULL l w x y -- PMULLD (SSE4.1)
| otherwise -> vector_int32x4_mul_sse2 x y
- MO_V_Mul 2 W64 -> vector_int64x2_mul_sse2 x y
+ MO_V_Mul l@2 w@W64 | avx512dq && avx512vl -> vector_int_op_avx VPMULL l w x y -- VPMULLQ (AVX512DQ+VL)
+ | otherwise -> vector_int64x2_mul_sse2 x y
MO_V_Mul {} -> needLlvm mop
MO_VU_Min l@16 w@W8
- -> vector_int_op_sse (MINMAX Min (IntVecMinMax False)) l w x y -- PMINUB (SSE2)
+ | avx -> vector_int_op_avx (VMINMAX Min (IntVecMinMax False)) l w x y -- VPMINUB (AVX)
+ | otherwise -> vector_int_op_sse (MINMAX Min (IntVecMinMax False)) l w x y -- PMINUB (SSE2)
MO_VU_Min l@8 w@W16
+ | avx -> vector_int_op_avx (VMINMAX Min (IntVecMinMax False)) l w x y -- VPMINUW (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Min (IntVecMinMax False)) l w x y -- PMINUW (SSE4.1)
| otherwise -> vector_word_minmax_sse Min l w x y
MO_VU_Min l@4 w@W32
+ | avx -> vector_int_op_avx (VMINMAX Min (IntVecMinMax False)) l w x y -- VPMINUD (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Min (IntVecMinMax False)) l w x y -- PMINUD (SSE4.1)
| otherwise -> vector_word_minmax_sse Min l w x y
MO_VU_Min l@2 w@W64
+ | avx512vl -> vector_int_op_avx (VMINMAX Min (IntVecMinMax False)) l w x y -- VPMINUQ (AVX512F+VL)
| sse4_2 -> vector_word_minmax_sse Min l w x y -- PCMPGTQ requires SSE4.2
-- The SSE2 version is implemented as a C call (MO_W64X2_Min)
MO_VU_Min {} -> needLlvm mop
MO_VU_Max l@16 w@W8
- -> vector_int_op_sse (MINMAX Max (IntVecMinMax False)) l w x y -- PMAXUB (SSE2)
+ | avx -> vector_int_op_avx (VMINMAX Max (IntVecMinMax False)) l w x y -- VPMAXUB (AVX)
+ | otherwise -> vector_int_op_sse (MINMAX Max (IntVecMinMax False)) l w x y -- PMAXUB (SSE2)
MO_VU_Max l@8 w@W16
+ | avx -> vector_int_op_avx (VMINMAX Max (IntVecMinMax False)) l w x y -- VPMAXUW (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Max (IntVecMinMax False)) l w x y -- PMAXUW (SSE4.1)
| otherwise -> vector_word_minmax_sse Max l w x y
MO_VU_Max l@4 w@W32
+ | avx -> vector_int_op_avx (VMINMAX Max (IntVecMinMax False)) l w x y -- VPMAXUD (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Max (IntVecMinMax False)) l w x y -- PMAXUD (SSE4.1)
| otherwise -> vector_word_minmax_sse Max l w x y
MO_VU_Max l@2 w@W64
+ | avx512vl -> vector_int_op_avx (VMINMAX Max (IntVecMinMax False)) l w x y -- VPMAXUQ (AVX512F+VL)
| sse4_2 -> vector_word_minmax_sse Max l w x y -- PCMPGTQ requires SSE4.2
-- The SSE2 version is implemented as a C call (MO_W64X2_Max)
MO_VU_Max {} -> needLlvm mop
MO_VS_Min l@16 w@W8
+ | avx -> vector_int_op_avx (VMINMAX Min (IntVecMinMax True)) l w x y -- VPMINSB (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Min (IntVecMinMax True)) l w x y -- PMINSB (SSE4.1)
| otherwise -> vector_int_minmax_sse Min l w x y
MO_VS_Min l@8 w@W16
- -> vector_int_op_sse (MINMAX Min (IntVecMinMax True)) l w x y -- PMINSW (SSE2)
+ | avx -> vector_int_op_avx (VMINMAX Min (IntVecMinMax True)) l w x y -- VPMINSW (AVX)
+ | otherwise -> vector_int_op_sse (MINMAX Min (IntVecMinMax True)) l w x y -- PMINSW (SSE2)
MO_VS_Min l@4 w@W32
+ | avx -> vector_int_op_avx (VMINMAX Min (IntVecMinMax True)) l w x y -- VPMINSD (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Min (IntVecMinMax True)) l w x y -- PMINSD (SSE4.1)
| otherwise -> vector_int_minmax_sse Min l w x y
MO_VS_Min l@2 w@W64
+ | avx512vl -> vector_int_op_avx (VMINMAX Min (IntVecMinMax True)) l w x y -- VPMINSQ (AVX512F+VL)
| sse4_2 -> vector_int_minmax_sse Min l w x y -- PCMPGTQ requires SSE4.2
-- The SSE2 version is implemented as a C call (MO_I64X2_Min)
MO_VS_Min {} -> needLlvm mop
MO_VS_Max l@16 w@W8
+ | avx -> vector_int_op_avx (VMINMAX Max (IntVecMinMax True)) l w x y -- VPMAXSB (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Max (IntVecMinMax True)) l w x y -- PMAXSB (SSE4.1)
| otherwise -> vector_int_minmax_sse Max l w x y
MO_VS_Max l@8 w@W16
- -> vector_int_op_sse (MINMAX Max (IntVecMinMax True)) l w x y -- PMAXSW (SSE2)
+ | avx -> vector_int_op_avx (VMINMAX Max (IntVecMinMax True)) l w x y -- VPMAXSW (AVX)
+ | otherwise -> vector_int_op_sse (MINMAX Max (IntVecMinMax True)) l w x y -- PMAXSW (SSE2)
MO_VS_Max l@4 w@W32
+ | avx -> vector_int_op_avx (VMINMAX Max (IntVecMinMax True)) l w x y -- VPMAXSD (AVX)
| sse4_1 -> vector_int_op_sse (MINMAX Max (IntVecMinMax True)) l w x y -- PMAXSD (SSE4.1)
| otherwise -> vector_int_minmax_sse Max l w x y
MO_VS_Max l@2 w@W64
+ | avx512vl -> vector_int_op_avx (VMINMAX Max (IntVecMinMax True)) l w x y -- VPMAXSQ (AVX512F+VL)
| sse4_2 -> vector_int_minmax_sse Max l w x y -- PCMPGTQ requires SSE4.2
-- The SSE2 version is implemented as a C call (MO_I64X2_Max)
MO_VS_Max {} -> needLlvm mop
@@ -1975,7 +2002,6 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
(PUNPCKLDQ format (OpReg tmpOdd1) dst) -- dst <- (dst[0],tmpOdd1[0],dst[1],tmpOdd1[1])
return (Any format code)
- -- TODO: We could use `VPMULLQ` if AVX-512 or AVX10.1 is available.
vector_int64x2_mul_sse2 :: CmmExpr -> CmmExpr -> NatM Register
vector_int64x2_mul_sse2 expr1 expr2 = do
-- implement 64 bit multiplication using 32-bit PMULUDQ multiplication instructions
=====================================
compiler/GHC/CmmToAsm/X86/Instr.hs
=====================================
@@ -338,6 +338,7 @@ data Instr
| PADD Format Operand Reg
| PSUB Format Operand Reg
| PMULL Format Operand Reg
+ | VPMULL Format Operand Reg Reg
| PMULUDQ Format Operand Reg
-- SIMD compare
@@ -601,6 +602,7 @@ regUsageOfInstr platform instr
PADD fmt src dst -> mkRU (use_R fmt src [mk fmt dst]) [mk fmt dst]
PSUB fmt src dst -> mkRU (use_R fmt src [mk fmt dst]) [mk fmt dst]
PMULL fmt src dst -> mkRU (use_R fmt src [mk fmt dst]) [mk fmt dst]
+ VPMULL fmt s1 s2 dst -> mkRU (use_R fmt s1 [mk fmt s2]) [mk fmt dst]
PMULUDQ fmt src dst -> mkRU (use_R fmt src [mk fmt dst]) [mk fmt dst]
PCMPGT fmt src dst -> mkRU (use_R fmt src [mk fmt dst]) [mk fmt dst]
@@ -912,6 +914,7 @@ patchRegsOfInstr platform instr env
PADD fmt src dst -> PADD fmt (patchOp src) (env dst)
PSUB fmt src dst -> PSUB fmt (patchOp src) (env dst)
PMULL fmt src dst -> PMULL fmt (patchOp src) (env dst)
+ VPMULL fmt s1 s2 dst -> VPMULL fmt (patchOp s1) (env s2) (env dst)
PMULUDQ fmt src dst -> PMULUDQ fmt (patchOp src) (env dst)
PCMPGT fmt src dst -> PCMPGT fmt (patchOp src) (env dst)
=====================================
compiler/GHC/CmmToAsm/X86/Ppr.hs
=====================================
@@ -1012,6 +1012,8 @@ pprInstr platform i = case i of
-> pprFormatOpReg (text "psub") format src dst
PMULL format src dst
-> pprFormatOpReg (text "pmull") format src dst
+ VPMULL format s1 s2 dst
+ -> pprFormatOpRegReg (text "vpmull") format s1 s2 dst
PMULUDQ format src dst
-> pprOpReg (text "pmuludq") format src dst
PCMPGT format src dst
@@ -1574,7 +1576,8 @@ pprInstr platform i = case i of
pprMinMax wantV minOrMax mmTy fmt regs
= line $ hcat ( instr : intersperse comma ( map ( pprOperand platform fmt ) regs ) )
where
- instr = (if wantV then text "v" else empty)
+ instr = char '\t'
+ <> (if wantV then text "v" else empty)
<> (case mmTy of { IntVecMinMax {} -> text "p"; FloatMinMax -> empty })
<> (case minOrMax of { Min -> text "min"; Max -> text "max" })
<> (case mmTy of { IntVecMinMax wantSigned -> if wantSigned then text "s" else text "u"; FloatMinMax -> empty })
=====================================
compiler/GHC/Driver/Config/CmmToAsm.hs
=====================================
@@ -65,6 +65,9 @@ initNCGConfig dflags this_mod = NCGConfig
ArchX86 -> v
_ -> Nothing
, ncgAvx512fEnabled = isAvx512fEnabled dflags
+ , ncgAvx512vlEnabled = isAvx512vlEnabled dflags
+ , ncgAvx512bwEnabled = isAvx512bwEnabled dflags
+ , ncgAvx512dqEnabled = isAvx512dqEnabled dflags
, ncgLa664Enabled = isLa664Enabled dflags
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -83,11 +83,15 @@ module GHC.Driver.DynFlags (
isSse4_2Enabled,
isAvxEnabled,
isAvx2Enabled,
+ isAvx512bwEnabled,
isAvx512cdEnabled,
+ isAvx512dqEnabled,
isAvx512erEnabled,
isAvx512fEnabled,
isAvx512pfEnabled,
+ isAvx512vlEnabled,
isFmaEnabled,
+ isGfniEnabled,
isBmiEnabled,
isBmi2Enabled,
-- For LoongArch platform
@@ -454,12 +458,16 @@ data DynFlags = DynFlags {
-- | Machine dependent flags (-m\<blah> stuff)
sseAvxVersion :: Maybe SseAvxVersion,
bmiVersion :: Maybe BmiVersion,
- avx512cd :: Bool, -- Enable AVX-512 Conflict Detection Instructions.
- avx512er :: Bool, -- Enable AVX-512 Exponential and Reciprocal Instructions.
- avx512f :: Bool, -- Enable AVX-512 instructions.
- avx512pf :: Bool, -- Enable AVX-512 PreFetch Instructions.
+ avx512bw :: Bool, -- ^ Enable AVX-512BW Instructions.
+ avx512cd :: Bool, -- ^ Enable AVX-512 Conflict Detection Instructions.
+ avx512dq :: Bool, -- ^ Enable AVX-512DQ Instructions.
+ avx512er :: Bool, -- ^ Enable AVX-512 Exponential and Reciprocal Instructions.
+ avx512f :: Bool, -- ^ Enable AVX-512 instructions.
+ avx512pf :: Bool, -- ^ Enable AVX-512 PreFetch Instructions.
+ avx512vl :: Bool, -- ^ Enable AVX-512VL Instructions.
fma :: Bool, -- ^ Enable FMA instructions.
- la664 :: Bool, -- Enable LA664 instructions
+ gfni :: Bool, -- ^ Enable GFNI Instructions.
+ la664 :: Bool, -- ^ Enable LA664 instructions
-- Constants used to control the amount of optimization done.
@@ -737,12 +745,16 @@ defaultDynFlags mySettings =
interactivePrint = Nothing,
sseAvxVersion = Nothing,
bmiVersion = Nothing,
+ avx512bw = False,
avx512cd = False,
+ avx512dq = False,
avx512er = False,
avx512f = False,
avx512pf = False,
+ avx512vl = False,
-- Use FMA by default on AArch64
fma = (platformArch . sTargetPlatform $ mySettings) == ArchAArch64,
+ gfni = False,
-- For LoongArch, la464 is used by default.
la664 = False,
@@ -1616,18 +1628,27 @@ isAvxEnabled dflags = sseAvxVersion dflags >= Just AVX1 || (isX86 && fma dflags)
isAvx2Enabled :: DynFlags -> Bool
isAvx2Enabled dflags = sseAvxVersion dflags >= Just AVX2 || isAvx512fEnabled dflags
+isAvx512bwEnabled :: DynFlags -> Bool
+isAvx512bwEnabled dflags = avx512bw dflags
+
isAvx512cdEnabled :: DynFlags -> Bool
isAvx512cdEnabled dflags = avx512cd dflags
+isAvx512dqEnabled :: DynFlags -> Bool
+isAvx512dqEnabled dflags = avx512dq dflags
+
isAvx512erEnabled :: DynFlags -> Bool
isAvx512erEnabled dflags = avx512er dflags
isAvx512fEnabled :: DynFlags -> Bool
-isAvx512fEnabled dflags = avx512f dflags || avx512cd dflags || avx512er dflags || avx512pf dflags
+isAvx512fEnabled dflags = avx512f dflags || avx512bw dflags || avx512cd dflags || avx512dq dflags || avx512er dflags || avx512pf dflags || avx512vl dflags
isAvx512pfEnabled :: DynFlags -> Bool
isAvx512pfEnabled dflags = avx512pf dflags
+isAvx512vlEnabled :: DynFlags -> Bool
+isAvx512vlEnabled dflags = avx512vl dflags
+
isFmaEnabled :: DynFlags -> Bool
isFmaEnabled dflags = fma dflags || (isX86 && isAvx512fEnabled dflags)
where
@@ -1637,6 +1658,9 @@ isFmaEnabled dflags = fma dflags || (isX86 && isAvx512fEnabled dflags)
ArchX86 -> True
_ -> False
+isGfniEnabled :: DynFlags -> Bool
+isGfniEnabled dflags = gfni dflags
+
{- Note [Implications between X86 CPU feature flags]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Many X86 CPU feature flags (such as -mavx, -mfma or -msse4) imply other
@@ -1649,7 +1673,7 @@ structures:
together with other implications such as
3. FMA -> AVX
- 4. AVX512{CD,ED,PF} -> AVX512F -> AVX2
+ 4. AVX512{BW,CD,DQ,ER,PF,VL} -> AVX512F -> AVX2
We handle this as follows:
=====================================
compiler/GHC/Driver/Pipeline/Execute.hs
=====================================
@@ -984,13 +984,17 @@ llvmOptions llvm_config llvm_version dflags =
-- It may become deprecated in a future LLVM version, though.
++ ["+avx2" | isAvx2Enabled dflags ]
++ ["+avx" | isAvxEnabled dflags ]
+ ++ ["+avx512bw"| isAvx512bwEnabled dflags ]
++ ["+avx512cd"| isAvx512cdEnabled dflags ]
+ ++ ["+avx512dq"| isAvx512dqEnabled dflags ]
++ ["+avx512er"| isAvx512erEnabled dflags ]
++ ["+avx512pf"| isAvx512pfEnabled dflags ]
- -- For Arch64 +fma is not a option (it's unconditionally available).
+ ++ ["+avx512vl"| isAvx512vlEnabled dflags ]
+ -- For AArch64 +fma is not a option (it's unconditionally available).
++ ["+fma" | isFmaEnabled dflags && (arch /= ArchAArch64) ]
++ ["+bmi" | isBmiEnabled dflags ]
++ ["+bmi2" | isBmi2Enabled dflags ]
+ ++ ["+gfni" | isGfniEnabled dflags ]
abi :: String
abi = case platformArch (targetPlatform dflags) of
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -212,11 +212,15 @@ module GHC.Driver.Session (
isBmi2Enabled,
isAvxEnabled,
isAvx2Enabled,
+ isAvx512bwEnabled,
isAvx512cdEnabled,
+ isAvx512dqEnabled,
isAvx512erEnabled,
isAvx512fEnabled,
isAvx512pfEnabled,
+ isAvx512vlEnabled,
isFmaEnabled,
+ isGfniEnabled,
-- LoongArch: ISA version: la664, la464(default)
isLa664Enabled,
@@ -1723,14 +1727,17 @@ dynamic_flags_deps = [
d { sseAvxVersion = max (Just AVX1) (sseAvxVersion d) }))
, make_ord_flag defGhcFlag "mavx2" (noArg (\d ->
d { sseAvxVersion = max (Just AVX2) (sseAvxVersion d) }))
- , make_ord_flag defGhcFlag "mavx512cd" (noArg (\d ->
- d { avx512cd = True }))
- , make_ord_flag defGhcFlag "mavx512er" (noArg (\d ->
- d { avx512er = True }))
+ , make_ord_flag defGhcFlag "mavx512bw" (noArg (\d -> d { avx512bw = True }))
+ , make_ord_flag defGhcFlag "mavx512cd" (noArg (\d -> d { avx512cd = True }))
+ , make_ord_flag defGhcFlag "mavx512dq" (noArg (\d -> d { avx512dq = True }))
+ , make_dep_flag defGhcFlag "mavx512er" (noArg (\d -> d { avx512er = True }))
+ "AVX-512ER was only available on Xeon Phi"
, make_ord_flag defGhcFlag "mavx512f" (noArg (\d -> d { avx512f = True }))
- , make_ord_flag defGhcFlag "mavx512pf" (noArg (\d ->
- d { avx512pf = True }))
+ , make_dep_flag defGhcFlag "mavx512pf" (noArg (\d -> d { avx512pf = True }))
+ "AVX-512PF was only available on Xeon Phi"
+ , make_ord_flag defGhcFlag "mavx512vl" (noArg (\d -> d { avx512vl = True }))
, make_ord_flag defGhcFlag "mfma" (noArg (\d -> d { fma = True }))
+ , make_ord_flag defGhcFlag "mgfni" (noArg (\d -> d { gfni = True }))
, make_ord_flag defGhcFlag "mla664" (noArg (\d -> d { la664 = True }))
=====================================
compiler/GHC/SysTools/Cpp.hs
=====================================
@@ -165,10 +165,16 @@ doCpp logger tmpfs dflags unit_env opts input_fn output_fn = do
let avx_defs =
[ "-D__AVX__" | isAvxEnabled dflags ] ++
[ "-D__AVX2__" | isAvx2Enabled dflags ] ++
+ [ "-D__AVX512BW__" | isAvx512bwEnabled dflags ] ++
[ "-D__AVX512CD__" | isAvx512cdEnabled dflags ] ++
+ [ "-D__AVX512DQ__" | isAvx512dqEnabled dflags ] ++
[ "-D__AVX512ER__" | isAvx512erEnabled dflags ] ++
[ "-D__AVX512F__" | isAvx512fEnabled dflags ] ++
- [ "-D__AVX512PF__" | isAvx512pfEnabled dflags ]
+ [ "-D__AVX512PF__" | isAvx512pfEnabled dflags ] ++
+ [ "-D__AVX512VL__" | isAvx512vlEnabled dflags ]
+
+ let gfni_def =
+ [ "-D__GFNI__" | isGfniEnabled dflags ]
backend_defs <- applyCDefs (backendCDefs $ backend dflags) logger dflags
@@ -209,6 +215,7 @@ doCpp logger tmpfs dflags unit_env opts input_fn output_fn = do
++ map GHC.SysTools.Option sse_defs
++ map GHC.SysTools.Option fma_def
++ map GHC.SysTools.Option avx_defs
+ ++ map GHC.SysTools.Option gfni_def
++ map GHC.SysTools.Option io_manager_defs
++ mb_macro_include
++ line_pragmas
=====================================
docs/users_guide/9.16.1-notes.rst
=====================================
@@ -101,6 +101,9 @@ to
See :ghc-ticket:`25345`.
+- Add several options for x86 extensions: :ghc-flag:`-mavx512bw`,
+ :ghc-flag:`-mavx512dq`, :ghc-flag:`-mavx512vl`, and :ghc-flag:`-mgfni`.
+
GHCi
~~~~
=====================================
docs/users_guide/phases.rst
=====================================
@@ -553,8 +553,10 @@ SIMD macros
These are defined conditionally based on the SIMD
flags used for compilation:
- ``__SSE__``, ``__SSE2__``, ``__SSE4_2__``, ``__FMA__``,
- ``__AVX__``, ``__AVX2__``, ``__AVX512CD__``, ``__AVX512ER__``, ``__AVX512F__``, ``__AVX512PF__``,
+ ``__SSE__``, ``__SSE2__``, ``__SSE3__``, ``__SSSE3__``,
+ ``__SSE4_1__``, ``__SSE4_2__``, ``__FMA__``, ``__AVX__``, ``__AVX2__``,
+ ``__AVX512BW__``, ``__AVX512CD__``, ``__AVX512DQ__``, ``__AVX512ER__``,
+ ``__AVX512F__``, ``__AVX512PF__``, ``__AVX512VL__``, ``__GFNI__``
.. _cpp-string-gaps:
=====================================
docs/users_guide/using.rst
=====================================
@@ -1601,7 +1601,7 @@ Some flags only make sense for particular target platforms.
:implies: :ghc-flag:`-msse4.2`
(x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
- or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86_64 AVX instructions.
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX instructions.
.. ghc-flag:: -mavx2
:shortdesc: (x86 only) Enable support for AVX2 SIMD extensions
@@ -1611,47 +1611,84 @@ Some flags only make sense for particular target platforms.
:implies: :ghc-flag:`-mavx`
(x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
- or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86_64 AVX2 instructions.
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX2 instructions.
+
+.. ghc-flag:: -mavx512bw
+ :shortdesc: (x86 only) Enable support for AVX-512BW SIMD extensions
+ :type: dynamic
+ :category: platform-options
+
+ :since: 9.16.1
+ :implies: :ghc-flag:`-mavx512f`
+
+ (x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512BW instructions.
.. ghc-flag:: -mavx512cd
- :shortdesc: (x86 only) Enable support for AVX512-CD SIMD extensions
+ :shortdesc: (x86 only) Enable support for AVX-512CD SIMD extensions
:type: dynamic
:category: platform-options
:implies: :ghc-flag:`-mavx512f`
(x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
- or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86_64 AVX512-CD instructions.
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512CD instructions.
+
+.. ghc-flag:: -mavx512dq
+ :shortdesc: (x86 only) Enable support for AVX-512DQ SIMD extensions
+ :type: dynamic
+ :category: platform-options
+
+ :since: 9.16.1
+ :implies: :ghc-flag:`-mavx512f`
+
+ (x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512DQ instructions.
.. ghc-flag:: -mavx512er
- :shortdesc: (x86 only) Enable support for AVX512-ER SIMD extensions
+ :shortdesc: (x86 only, deprecated) Enable support for AVX-512ER SIMD extensions
:type: dynamic
:category: platform-options
:implies: :ghc-flag:`-mavx512f`
(x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
- or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86_64 AVX512-ER instructions.
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512ER instructions.
+
+ The AVX-512ER extension is deprecated and not supported by newer LLVM versions.
.. ghc-flag:: -mavx512f
- :shortdesc: (x86 only) Enable support for AVX512-F SIMD extensions
+ :shortdesc: (x86 only) Enable support for AVX-512F SIMD extensions
:type: dynamic
:category: platform-options
:implies: :ghc-flag:`-mavx2`, :ghc-flag:`-mfma`
(x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
- or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86_64 AVX512-F instructions.
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512F instructions.
.. ghc-flag:: -mavx512pf
- :shortdesc: (x86 only) Enable support for AVX512-PF SIMD extensions
+ :shortdesc: (x86 only, deprecated) Enable support for AVX-512PF SIMD extensions
:type: dynamic
:category: platform-options
:implies: :ghc-flag:`-mavx512f`
(x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
- or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86_64 AVX512-PF instructions.
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512PF instructions.
+
+ The AVX-512PF extension is deprecated and not supported by newer LLVM versions.
+
+.. ghc-flag:: -mavx512vl
+ :shortdesc: (x86 only) Enable support for AVX-512VL SIMD extensions
+ :type: dynamic
+ :category: platform-options
+
+ :since: 9.16.1
+ :implies: :ghc-flag:`-mavx512f`
+
+ (x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 AVX-512VL instructions.
.. ghc-flag:: -msse
:shortdesc: (x86 only) Use SSE for floating-point operations
@@ -1714,13 +1751,13 @@ Some flags only make sense for particular target platforms.
or the :ref:`LLVM backend <llvm-code-gen>`).
.. ghc-flag:: -msse4
- :shortdesc: (x86 only) Use SSE4 for floating-point operations
+ :shortdesc: (x86 only) Use SSE4.1 for floating-point operations
:type: dynamic
:category: platform-options
:implies: :ghc-flag:`-mssse3`
- (x86 only) Use the SSE4 instruction set to
+ (x86 only) Use the SSE4.1 instruction set to
implement some floating point and bit operations(whether using the :ref:`native code generator <native-code-gen>`
or the :ref:`LLVM backend <llvm-code-gen>`).
@@ -1781,6 +1818,16 @@ Some flags only make sense for particular target platforms.
multiply-add, which might perform non-IEEE-compliant software emulation on
some platforms (depending on the implementation of the C standard library).
+.. ghc-flag:: -mgfni
+ :shortdesc: (x86 only) Use GFNI for advanced bit manipulations
+ :type: dynamic
+ :category: platform-options
+
+ :since: 9.16.1
+
+ (x86 only) This flag allows the code generator (whether the :ref:`native code generator <native-code-gen>`
+ or the :ref:`LLVM backend <llvm-code-gen>`) to emit x86 GFNI instructions.
+
.. ghc-flag:: -mla664
:shortdesc: (LoongArch only) Used for new instructions for la664 uarch
:type: dynamic
=====================================
testsuite/driver/cpu_features.py
=====================================
@@ -9,9 +9,9 @@ SUPPORTED_CPU_FEATURES = {
# x86:
'sse', 'sse2', 'sse3', 'pni', 'ssse3', 'sse4_1', 'sse4_2',
- 'avx', 'avx2', 'avx512f',
+ 'avx', 'avx2', 'avx512f', 'avx512vl', 'avx512bw', 'avx512dq',
'fma',
- 'popcnt', 'bmi1', 'bmi2'
+ 'popcnt', 'bmi1', 'bmi2', 'gfni',
}
cpu_feature_cache = None
=====================================
testsuite/tests/codeGen/should_gen_asm/all.T
=====================================
@@ -17,3 +17,9 @@ test('msse-option-order', [unless(arch('x86_64') or arch('i386'), skip),
when(unregisterised(), skip)], compile_grep_asm, ['hs', False, '-msse4.2 -msse2'])
test('mavx-should-enable-popcnt', [unless(arch('x86_64') or arch('i386'), skip),
when(unregisterised(), skip)], compile_grep_asm, ['hs', False, '-mavx'])
+test('avx512-int64-mul', [unless(arch('x86_64'), skip),
+ when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512dq -mavx512vl'])
+test('avx512-int64-minmax', [unless(arch('x86_64'), skip),
+ when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512vl'])
+test('avx512-word64-minmax', [unless(arch('x86_64'), skip),
+ when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512vl'])
=====================================
testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.asm
=====================================
@@ -0,0 +1,2 @@
+vpminsq
+vpmaxsq
=====================================
testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.hs
=====================================
@@ -0,0 +1,27 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ExtendedLiterals #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+import GHC.Exts
+import GHC.Prim
+import GHC.Int
+
+{-# NOINLINE f #-}
+f :: Int64X2# -> Int64X2# -> Int64X2# -> Int64X2#
+f x y z = minInt64X2# x (plusInt64X2# y z)
+
+{-# NOINLINE g #-}
+g :: Int64X2# -> Int64X2# -> Int64X2# -> Int64X2#
+g x y z = maxInt64X2# x (plusInt64X2# y z)
+
+main :: IO ()
+main = do
+ let !x = packInt64X2# (# 1#Int64, 10#Int64 #)
+ !y = packInt64X2# (# 4#Int64, 2#Int64 #)
+ !z = broadcastInt64X2# 5#Int64
+ !w = f x y z
+ (# w0, w1 #) = unpackInt64X2# w
+ !v = g x y z
+ (# v0, v1 #) = unpackInt64X2# v
+ print (I64# w0, I64# w1)
+ print (I64# v0, I64# v1)
=====================================
testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.asm
=====================================
@@ -0,0 +1 @@
+vpmullq
=====================================
testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.hs
=====================================
@@ -0,0 +1,19 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ExtendedLiterals #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+import GHC.Exts
+import GHC.Int
+
+{-# NOINLINE f #-}
+f :: Int64X2# -> Int64X2# -> Int64X2# -> Int64X2#
+f x y z = timesInt64X2# x (plusInt64X2# y z)
+
+main :: IO ()
+main = do
+ let !x = packInt64X2# (# 1#Int64, 3#Int64 #)
+ !y = packInt64X2# (# 4#Int64, 2#Int64 #)
+ !z = broadcastInt64X2# 5#Int64
+ !w = f x y z
+ (# w0, w1 #) = unpackInt64X2# w
+ print (I64# w0, I64# w1)
=====================================
testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.asm
=====================================
@@ -0,0 +1,2 @@
+vpminuq
+vpmaxuq
=====================================
testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.hs
=====================================
@@ -0,0 +1,27 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ExtendedLiterals #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+import GHC.Exts
+import GHC.Prim
+import GHC.Word
+
+{-# NOINLINE f #-}
+f :: Word64X2# -> Word64X2# -> Word64X2# -> Word64X2#
+f x y z = minWord64X2# x (plusWord64X2# y z)
+
+{-# NOINLINE g #-}
+g :: Word64X2# -> Word64X2# -> Word64X2# -> Word64X2#
+g x y z = maxWord64X2# x (plusWord64X2# y z)
+
+main :: IO ()
+main = do
+ let !x = packWord64X2# (# 1#Word64, 10#Word64 #)
+ !y = packWord64X2# (# 4#Word64, 2#Word64 #)
+ !z = broadcastWord64X2# 5#Word64
+ !w = f x y z
+ (# w0, w1 #) = unpackWord64X2# w
+ !v = g x y z
+ (# v0, v1 #) = unpackWord64X2# v
+ print (W64# w0, W64# w1)
+ print (W64# v0, W64# v1)
=====================================
testsuite/tests/simd/should_run/all.T
=====================================
@@ -66,6 +66,9 @@ setTestOpts(
, when(have_cpu_feature('avx'), extra_hc_opts('-mavx'))
, when(have_cpu_feature('avx2'), extra_hc_opts('-mavx2'))
, when(have_cpu_feature('avx512f'), extra_hc_opts('-mavx512f'))
+ , when(have_cpu_feature('avx512vl'), extra_hc_opts('-mavx512vl'))
+ , when(have_cpu_feature('avx512bw'), extra_hc_opts('-mavx512bw'))
+ , when(have_cpu_feature('avx512dq'), extra_hc_opts('-mavx512dq'))
])
test('simd000', [], compile_and_run, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/14f485ee92ee8bcb25d083c3298c93a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/14f485ee92ee8bcb25d083c3298c93a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/26852] compiler/ffi: Collapse void pointer chains in capi wrappers
by Zubin (@wz1000) 17 Feb '26
by Zubin (@wz1000) 17 Feb '26
17 Feb '26
Zubin pushed to branch wip/26852 at Glasgow Haskell Compiler / GHC
Commits:
d3d034af by Zubin Duggal at 2026-02-17T18:44:40+05:30
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
- - - - -
5 changed files:
- compiler/GHC/HsToCore/Foreign/C.hs
- + 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
Changes:
=====================================
compiler/GHC/HsToCore/Foreign/C.hs
=====================================
@@ -328,37 +328,73 @@ dsFCall fn_id co fcall mDeclHeader = do
toCName :: Id -> String
toCName i = showSDocOneLine defaultSDocContext (pprCode (ppr (idName i)))
+{- Note [Collapsing void pointer chains]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When translating Haskell types like (Ptr (Ptr Abstract)) to C types for capi
+wrappers, where Abstract has no CType annotation, naively we would produce
+"void**". This is problematic because in C, only void* has implicit conversion
+to any pointer type -- void** does NOT implicitly convert to specific_type**.
+Modern compilers (gcc, clang) treat -Wincompatible-pointer-types as an error
+by default (#26852), causing compilation failures for capi wrappers.
+
+The fix is to collapse void pointer chains: whenever the inner type of a
+Ptr/FunPtr resolves to void (i.e. the Haskell type has no known C
+representation), we return void* instead of void**, void***, etc.
+This works because void* implicitly converts to any pointer type in C.
+
+The internal helper f returns a Bool alongside the C type, indicating whether
+the result was void-based (True) or a known concrete type (False). When the
+Ptr/FunPtr case sees isVoid=True from its recursive call, it returns void*
+directly instead of appending another *.
+
+Examples:
+ Ptr Abstract => void*
+ Ptr (Ptr Abstract) => void* (used to be void**)
+ Ptr (Ptr (Ptr Abstract)) => void*
+ Ptr (Ptr CInt) => int** (CInt has CType "int", don't collapse)
+-}
+
+-- | See Note [Collapsing void pointer chains]
toCType :: Type -> (Maybe (Header GhcTc), SDoc)
-toCType = f False
- where f voidOK t
- -- First, if we have (Ptr t) of (FunPtr t), then we need to
+toCType t = case f False t of
+ (mh, _, cType) -> (mh, cType)
+ where
+ -- The Bool in the return type indicates whether the C type is
+ -- "void" due to an unknown Haskell type (True = void-based).
+ f :: Bool -> Type -> (Maybe (Header GhcTc), Bool, SDoc)
+ f voidOK t
+ -- First, if we have (Ptr t) or (FunPtr t), then we need to
-- convert t to a C type and put a * after it. If we don't
-- know a type for t, then "void" is fine, though.
+ -- If the inner type is void-based, we collapse the pointer
+ -- chain to just "void*". See Note [Collapsing void pointer chains].
| Just (ptr, [t']) <- splitTyConApp_maybe t
, tyConName ptr `elem` [ptrTyConName, funPtrTyConName]
= case f True t' of
- (mh, cType') ->
- (mh, cType' <> char '*')
+ (mh, True, _) ->
+ (mh, True, text "void*")
+ (mh, False, cType') ->
+ (mh, False, cType' <> char '*')
-- Otherwise, if we have a type constructor application, then
-- see if there is a C type associated with that constructor.
-- Note that we aren't looking through type synonyms or
-- anything, as it may be the synonym that is annotated.
| Just tycon <- tyConAppTyConPicky_maybe t
, Just (CType _ mHeader cType) <- tyConCType_maybe tycon
- = (mHeader, ftext cType)
+ = (mHeader, False, ftext cType)
-- If we don't know a C type for this type, then try looking
-- through one layer of type synonym etc.
| Just t' <- coreView t
= f voidOK t'
- -- Handle 'UnliftedFFITypes' argument
+ -- Handle 'UnliftedFFITypes' argument
| Just tyCon <- tyConAppTyConPicky_maybe t
, isPrimTyCon tyCon
, Just cType <- ppPrimTyConStgType tyCon
- = (Nothing, text cType)
+ = (Nothing, False, text cType)
-- Otherwise we don't know the C type. If we are allowing
-- void then return that; otherwise something has gone wrong.
- | voidOK = (Nothing, text "void")
+ | voidOK = (Nothing, True, text "void")
| otherwise
= pprPanic "toCType" (ppr t)
=====================================
testsuite/tests/ffi/should_compile/T26852.h
=====================================
@@ -0,0 +1,7 @@
+typedef struct abstract abstract;
+
+void blah(abstract** x);
+abstract** get_abstract(void);
+abstract*** get_abstract3(void);
+abstract* get_simple(void);
+int** get_int_pp(void);
=====================================
testsuite/tests/ffi/should_compile/T26852.hs
=====================================
@@ -0,0 +1,22 @@
+{-# LANGUAGE CApiFFI #-}
+module T26852 where
+
+import Foreign.Ptr
+import Foreign.C.Types
+
+data Abstract
+
+foreign import capi "T26852.h blah"
+ c_blah :: Ptr (Ptr Abstract) -> IO ()
+
+foreign import capi "T26852.h get_abstract"
+ c_get_abstract :: IO (Ptr (Ptr Abstract))
+
+foreign import capi "T26852.h get_abstract3"
+ c_get_abstract3 :: IO (Ptr (Ptr (Ptr Abstract)))
+
+foreign import capi "T26852.h get_simple"
+ c_get_simple :: IO (Ptr Abstract)
+
+foreign import capi "T26852.h get_int_pp"
+ c_get_int_pp :: IO (Ptr (Ptr CInt))
=====================================
testsuite/tests/ffi/should_compile/T26852.stderr
=====================================
@@ -0,0 +1,18 @@
+
+==================== Foreign export header file ====================
+
+
+
+==================== Foreign export stubs ====================
+#include "T26852.h"
+int** ghczuwrapperZC0ZCmainZCT26852ZCgetzuintzupp(void) {return get_int_pp();}
+#include "T26852.h"
+void* ghczuwrapperZC1ZCmainZCT26852ZCgetzusimple(void) {return get_simple();}
+#include "T26852.h"
+void* ghczuwrapperZC2ZCmainZCT26852ZCgetzuabstract3(void) {return get_abstract3();}
+#include "T26852.h"
+void* ghczuwrapperZC3ZCmainZCT26852ZCgetzuabstract(void) {return get_abstract();}
+#include "T26852.h"
+void ghczuwrapperZC4ZCmainZCT26852ZCblah(void* a1) {blah(a1);}
+
+
=====================================
testsuite/tests/ffi/should_compile/all.T
=====================================
@@ -43,3 +43,4 @@ test('T22774', [unless(js_arch() or arch('wasm32'), expect_fail)], compile, ['']
test('T24034', normal, compile, [''])
test('T25255', normal, compile, ['-dppr-debug'])
+test('T26852', [filter_stdout_lines(r'.*ghczuwrapper.*')], compile, ['-ddump-foreign'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d3d034af7b94689b57e734ddce9628e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d3d034af7b94689b57e734ddce9628e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Zubin pushed new branch wip/26852 at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/26852
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/mangoiv/backports-9.12] 24 commits: Use tcMkScaledFunTys in matchExpectedFunTys
by Zubin (@wz1000) 17 Feb '26
by Zubin (@wz1000) 17 Feb '26
17 Feb '26
Zubin pushed to branch wip/mangoiv/backports-9.12 at Glasgow Haskell Compiler / GHC
Commits:
65d4b8e4 by sheaf at 2026-02-17T18:04:37+05:30
Use tcMkScaledFunTys in matchExpectedFunTys
We should use tcMkScaledFunTys rather than mkScaledFunTys in
GHC.Tc.Utils.Unify.matchExpectedFunTys, as the latter crashes
when the kind of the result type is a bare metavariable.
We know the result is always Type-like, so we don't need scaledFunTys
to try to rediscover that from the kind.
Fixes #26277
(cherry picked from commit 624afa4a65caa8ec23f85e70574dfb606f90c173)
- - - - -
ffa32138 by sheaf at 2026-02-17T18:04:37+05:30
Improve Notes about disambiguating record updates
This commit updates the notes [Disambiguating record updates] and
[Type-directed record disambiguation], in particular adding more
information about the deprecation status of type-directed disambiguation
of record updates.
(cherry picked from commit a2d9d7c2073867ee0cabb8d49f93246d95ec0b09)
- - - - -
9493fd96 by sheaf at 2026-02-17T18:04:37+05:30
Add test for #26216
(cherry picked from commit 2e73f3426ab6e3cf1938b53831005593f3fd351c)
- - - - -
3f575881 by Vladislav Zavialov at 2026-02-17T18:04:37+05:30
Fix PREP_MAYBE_LIBRARY in prep_target_file.m4
This change fixes a configure error introduced in:
commit 8235dd8c4945db9cb03e3be3c388d729d576ed1e
ghc-toolchain: Move UseLibdw to per-Target file
Now the build no longer fails with:
acghc-toolchain: Failed to read a valid Target value from hadrian/cfg/default.target
(cherry picked from commit 1480872af6b80db1b035a44409188416df041048)
- - - - -
27ef06e5 by Cheng Shao at 2026-02-17T18:04:37+05:30
rts: remove obsolete CC_SUPPORTS_TLS logic
This patch removes obsolete CC_SUPPORTS_TLS logic throughout the rts,
given __thread is now uniformly supported by C toolchains of all
platforms we currently support.
(cherry picked from commit 0f034942724233e1457549123b46880f7b93e805)
- - - - -
28fbd4f9 by Cheng Shao at 2026-02-17T18:04:37+05:30
rts: remove obsolete HAS_VISIBILITY_HIDDEN logic
This patch removes obsolete HAS_VISIBILITY_HIDDEN logic throughout the
rts, given __attribute__((visibility("hidden"))) is uniformly
supported by C toolchains of all platforms we currently support.
(cherry picked from commit ef7056554df5603ec4d1e33193abe953970e6ab3)
- - - - -
cfaa5904 by Cheng Shao at 2026-02-17T18:04:37+05:30
rts: remove -O3 pragma hack in Hash.c
This patch removes an obsolete gcc pragma to specify -O3 in Hash.c.
Hadrian already passes the right flag.
(cherry picked from commit 9fdc1f7d855cc61f90de909875f6ae0d6798dca7)
- - - - -
6e1fd477 by Cheng Shao at 2026-02-17T18:04:37+05:30
wasm: fix dyld handling for forward declared GOT.func items
This patch fixes wasm shared linker's handling of forward declared
GOT.func items, see linked issue for details. Also adds T26430 test to
witness the fix. Fixes #26430.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 867c26755e8855c6df949e65df0c2aebc9da64c3)
- - - - -
a3e53502 by Cheng Shao at 2026-02-17T18:04:37+05:30
rts: remove obsolete __GNUC__ related logic
This patch removes obsolete `__GNUC__` related logic, given on any
currently supported platform and toolchain, `__GNUC__ >= 4` is
universally true. Also pulls some other weeds and most notably, use
`__builtin___clear_cache` for clang as well, since clang has supported
this gcc intrinsic since 2014, see
https://github.com/llvm/llvm-project/commit/c491a8d4577052bc6b3b4c72a7db6a7….
(cherry picked from commit 67de53a6ced23caad640d2c7421089242f0dfb76)
- - - - -
466675a2 by Cheng Shao at 2026-02-17T18:04:37+05:30
hadrian: fix GHC.Platform.Host generation for cross stage1
This patch fixes incorrectly GHC.Platform.Host generation logic for
cross stage1 in hadrian (#26449). Also adds T26449 test case to
witness the fix.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 8cbe006ad09d5a64e4a3cdf4c91a8b81ff1511be)
- - - - -
8954d56f by Luite Stegeman at 2026-02-17T18:04:37+05:30
rts: Fix lost wakeups in threadPaused for threads blocked on black holes
The lazy blackholing code in threadPaused could overwrite closures
that were already eagerly blackholed, and as such wouldn't have a
marked update frame. If the black hole was overwritten by its
original owner, this would lead to an undetected collision, and
the contents of any existing blocking queue being lost.
This adds a check for eagerly blackholed closures and avoids
overwriting their contents.
Fixes #26324
(cherry picked from commit a1de535f762bc23d4cf23a5b1853591dda12cdc9)
- - - - -
44bb797e by Luite Stegeman at 2026-02-17T18:04:37+05:30
rts: push the correct update frame in stg_AP_STACK
The frame contains an eager black hole (__stg_EAGER_BLACKHOLE_info) so
we should push an stg_bh_upd_frame_info instead of an stg_upd_frame_info.
(cherry picked from commit b7e21e498d39e0ee764e3237544b4c39ddf98467)
- - - - -
3af4f71e by Cheng Shao at 2026-02-17T18:04:37+05:30
testsuite: remove unused expected output files
This patch removes unused expected output files in the testsuites on
platforms that we no longer support.
(cherry picked from commit 6992ac097b9da989f125f896afe21b75dba8b4c9)
- - - - -
dac282c5 by Ben Gamari at 2026-02-17T18:04:37+05:30
rts/posix: Enforce iteration limit on heap reservation logic
Previously we could loop indefinitely when attempting to get an address
space reservation for our heap. Limit the logic to 8 iterations to
ensure we instead issue a reasonable error message.
Addresses #26151.
(cherry picked from commit ff1650c96c61af02e193854312a9ccd303968e47)
- - - - -
7bd9a307 by Ben Gamari at 2026-02-17T18:04:37+05:30
rts/posix: Hold on to low reservations when reserving heap
Previously when the OS gave us an address space reservation in low
memory we would immediately release it and try again. However, on some
platforms this meant that we would get the same allocation again in the
next iteration (since mmap's `hint` argument is just that, a hint).
Instead we now hold on to low reservations until we have found a
suitable heap reservation.
Fixes #26151.
(cherry picked from commit 0184455728f841a699648f879fdb29128081fc6b)
- - - - -
099deccb by Julian Ospald at 2026-02-17T18:04:37+05:30
ghc-toolchain: Drop `ld.gold` from merge object command
It's deprecated.
Also see #25716
(cherry picked from commit c58f9a615f05e9d43629f6e846ae22cad2a6163d)
- - - - -
47aa35e2 by Ben Gamari at 2026-02-17T18:04:37+05:30
gitlab-ci: Make RELEASE_JOB an input
Rather than an undocumented variable.
(cherry picked from commit f9790ca81deb8b14ff2eabf701aecbcfd6501963)
- - - - -
d64f88be by Cheng Shao at 2026-02-17T18:04:37+05:30
testsuite: fix T3586 for non-SSE3 platforms
`T3586.hs` contains `-fvia-C -optc-msse3` which I think is a
best-effort basis to harvest the C compiler's auto vectorization
optimizations via the C backend back when the test was added. The
`-fvia-C` part is now a deprecated no-op because GHC can't fall back
to the C backend on a non-unregisterised build, and `-optc-msse3`
might actually cause the test to fail on non x86/x64 platforms, e.g.
recent builds of wasi-sdk would report `wasm32-wasi-clang: error:
unsupported option '-msse3' for target 'wasm32-unknown-wasi'`.
So this patch cleans up this historical cruft. `-fvia-C` is removed,
and `-optc-msse3` is only passed when cpuid contains `pni` (which
indicates support of SSE3).
(cherry picked from commit 70ee825a516bcf7aac762bfedb4a017d35f8dcf3)
- - - - -
583b8be7 by Julian Ospald at 2026-02-17T18:04:38+05:30
Improve error handling in 'getPackageArchives'
When the library dirs in the package conf files are not set up correctly,
the JS linker will happily ignore such packages and not link against them,
although they're part of the link plan.
Fixes #26383
(cherry picked from commit 91b6be10bd58c2bfc1c7c22e81b06ab3be583228)
- - - - -
07bf37e3 by Ben Gamari at 2026-02-17T18:04:38+05:30
rts: Annotate BCOs with their Name
This introduces a new bytecode instruction, `BCO_NAME`, to aid in debugging
bytecode execution. This instruction is injected by `mkProtoBCO` and
captures the Haskell name of the BCO. It is then printed by the
disassembler, allowing ready correlation with STG dumps.
(cherry picked from commit 5192a75fe9b272e8b1ef290fa834714c81bd1f79)
- - - - -
8bd22849 by sheaf at 2026-02-17T18:04:38+05:30
Bad record update msg: allow out-of-scope datacons
This commit ensures that, when we encounter an invalid record update
(because no constructor exists which contains all of the record fields
mentioned in the record update), we graciously handle the situation in
which the constructors themselves are not in scope. In that case,
instead of looking up the constructors in the GlobalRdrEnv, directly
look up their GREInfo using the lookupGREInfo function.
Fixes #26391
(cherry picked from commit cef8938f3c0d22583f01d5ea29e6109bccd36040)
- - - - -
d82ff48b by Cheng Shao at 2026-02-17T18:04:38+05:30
rts: remove obsolete COMPILING_WINDOWS_DLL logic
This patch removes obsolete COMPILING_WINDOWS_DLL logic throughout the
rts. They were once used for compiling to win32 DLLs, but we haven't
been able to compile Haskell units to win32 DLLs for many years now,
due to PE format's restriction of no more than 65536 exported symbols
in a single DLL.
(cherry picked from commit b8cfa8f741729ef123569fb321c4b2ab4a1a941c)
- - - - -
757f33b7 by Julian Ospald at 2026-02-17T18:04:38+05:30
Skip uniques test if sources are not available
(cherry picked from commit 5dc2e9eaf60fd72771bf2e8112aec182665461a1)
- - - - -
58aefd21 by Julian Ospald at 2026-02-17T18:04:38+05:30
rts: remove unneccesary cabal flags
We perform those checks via proper autoconf macros
instead that do the right thing and then add those
libs to the rts buildinfo.
(cherry picked from commit 643ce801a8b559071683cad0e5adbc26b9fc8385)
- - - - -
84 changed files:
- .gitlab-ci.yml
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Unit/Info.hs
- compiler/ghc.cabal.in
- docs/users_guide/debugging.rst
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Rts.hs
- m4/fp_check_pthreads.m4
- − m4/fp_visibility_hidden.m4
- m4/prep_target_file.m4
- rts/Apply.cmm
- rts/BeginPrivate.h
- rts/Disassembler.c
- rts/EndPrivate.h
- rts/Hash.c
- rts/Interpreter.c
- − rts/RtsDllMain.c
- − rts/RtsDllMain.h
- rts/RtsStartup.c
- rts/RtsSymbols.c
- rts/Task.c
- rts/Task.h
- rts/ThreadPaused.c
- rts/configure.ac
- rts/include/Rts.h
- rts/include/RtsAPI.h
- rts/include/Stg.h
- rts/include/rts/OSThreads.h
- rts/include/rts/Types.h
- rts/include/stg/DLL.h
- rts/posix/OSMem.c
- rts/posix/OSThreads.c
- rts/prim/atomic.c
- rts/prim/ctz.c
- + rts/rts.buildinfo.in
- rts/rts.cabal
- rts/sm/BlockAlloc.c
- rts/sm/Evac.c
- rts/sm/Evac.h
- rts/sm/GCTDecl.h
- rts/sm/GCThread.h
- rts/sm/Storage.c
- rts/win32/OSThreads.c
- testsuite/driver/cpu_features.py
- + testsuite/tests/bytecode/T26216.hs
- + testsuite/tests/bytecode/T26216.script
- + testsuite/tests/bytecode/T26216.stdout
- + testsuite/tests/bytecode/T26216_aux.hs
- testsuite/tests/bytecode/all.T
- + testsuite/tests/cross/should_run/T26449.hs
- + testsuite/tests/cross/should_run/all.T
- + testsuite/tests/ghci-wasm/Makefile
- + testsuite/tests/ghci-wasm/T26430.hs
- + testsuite/tests/ghci-wasm/T26430A.c
- + testsuite/tests/ghci-wasm/T26430B.c
- + testsuite/tests/ghci-wasm/all.T
- testsuite/tests/linters/all.T
- + testsuite/tests/overloadedrecflds/should_fail/T26391.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26391.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/perf/should_run/T3586.hs
- testsuite/tests/perf/should_run/all.T
- − testsuite/tests/process/process010.stdout-i386-unknown-solaris2
- − testsuite/tests/rts/linker/T11223/T11223_link_order_a_b_2_fail.stderr-ws-32-mingw32
- − testsuite/tests/rts/linker/T11223/T11223_simple_duplicate_lib.stderr-ws-32-mingw32
- − testsuite/tests/rts/outofmem.stderr-i386-apple-darwin
- − testsuite/tests/rts/outofmem.stderr-i386-unknown-mingw32
- − testsuite/tests/rts/outofmem.stderr-powerpc-apple-darwin
- testsuite/tests/th/T10279.hs
- testsuite/tests/th/T10279.stderr
- + testsuite/tests/typecheck/should_compile/T26277.hs
- testsuite/tests/typecheck/should_compile/all.T
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/MergeObjs.hs
- utils/jsffi/dyld.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/8a81ec147a5284f902ae62df3ec9d9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/8a81ec147a5284f902ae62df3ec9d9…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/26853] hadrian: Add a flag for debugging --hash-unit-ids. Prints out the inputs of...
by Zubin (@wz1000) 17 Feb '26
by Zubin (@wz1000) 17 Feb '26
17 Feb '26
Zubin pushed to branch wip/26853 at Glasgow Haskell Compiler / GHC
Commits:
f93e9415 by Zubin Duggal at 2026-02-17T18:08:58+05:30
hadrian: Add a flag for debugging --hash-unit-ids. Prints out the inputs of the hash to stdout and a file.
- - - - -
2 changed files:
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Haskell/Hash.hs
Changes:
=====================================
hadrian/src/CommandLine.hs
=====================================
@@ -1,7 +1,7 @@
module CommandLine (
optDescrs, cmdLineArgsMap, cmdFlavour, lookupFreeze1, lookupFreeze2, lookupSkipDepends,
cmdBignum, cmdBignumCheck, cmdProgressInfo, cmdCompleteSetting,
- cmdDocsArgs, cmdUnitIdHash, lookupBuildRoot, TestArgs(..), TestSpeed(..), defaultTestArgs,
+ cmdDocsArgs, cmdUnitIdHash, cmdDebugHashInputs, lookupBuildRoot, TestArgs(..), TestSpeed(..), defaultTestArgs,
cmdPrefix, DocArgs(..), defaultDocArgs
) where
@@ -37,7 +37,8 @@ data CommandLineArgs = CommandLineArgs
, docsArgs :: DocArgs
, docTargets :: DocTargets
, prefix :: Maybe FilePath
- , completeStg :: Maybe String }
+ , completeStg :: Maybe String
+ , debugHashInputs :: Bool }
deriving (Eq, Show)
-- | Default values for 'CommandLineArgs'.
@@ -57,7 +58,8 @@ defaultCommandLineArgs = CommandLineArgs
, docsArgs = defaultDocArgs
, docTargets = Set.fromList [minBound..maxBound]
, prefix = Nothing
- , completeStg = Nothing }
+ , completeStg = Nothing
+ , debugHashInputs = False }
-- | These arguments are used by the `test` target.
data TestArgs = TestArgs
@@ -143,6 +145,9 @@ readUnitIdHash = Right $ \flags ->
trace "--hash-unit-ids is deprecated. It is enabled by release flavour or +hash_unit_ids flavour transformer" $
flags { unitIdHash = True }
+readDebugHashInputs :: Either String (CommandLineArgs -> CommandLineArgs)
+readDebugHashInputs = Right $ \flags -> flags { debugHashInputs = True }
+
readProgressInfo :: String -> Either String (CommandLineArgs -> CommandLineArgs)
readProgressInfo ms =
case lower ms of
@@ -278,6 +283,8 @@ optDescrs =
"Freeze Stage2 GHC."
, Option [] ["hash-unit-ids"] (NoArg readUnitIdHash)
"Include package hashes in unit ids."
+ , Option [] ["debug-hash-inputs"] (NoArg readDebugHashInputs)
+ "Debug: print and log hash inputs for each package."
, Option [] ["skip-depends"] (NoArg readSkipDepends)
"Skip rebuilding dependency information."
, Option [] ["bignum"] (OptArg readBignum "BACKEND")
@@ -401,5 +408,8 @@ cmdBignumCheck = bignumCheck <$> cmdLineArgs
cmdProgressInfo :: Action ProgressInfo
cmdProgressInfo = progressInfo <$> cmdLineArgs
+cmdDebugHashInputs :: Action Bool
+cmdDebugHashInputs = debugHashInputs <$> cmdLineArgs
+
cmdDocsArgs :: Action DocTargets
cmdDocsArgs = docTargets <$> cmdLineArgs
=====================================
hadrian/src/Hadrian/Haskell/Hash.hs
=====================================
@@ -34,6 +34,8 @@ import Control.Monad
import Base
import System.Directory.Extra (listFilesRecursive)
import Control.Arrow (first)
+import CommandLine (cmdDebugHashInputs)
+import System.Directory (createDirectoryIfMissing)
-- | Read a Cabal file and return the package identifier, e.g. @base-4.10.0.0-abcd@.
@@ -165,15 +167,25 @@ pkgHashOracle = void $ addOracleCache $ \(PkgHashKey (stag, pkg)) -> do
need files
files_hash <- liftIO (SHA256.finalize <$> hashFiles (SHA256.init) files)
- return $ BS.unpack $ Base16.encode $ SHA256.hash $
- renderPackageHashInputs $ PackageHashInputs
- {
- pkgHashPkgId = name
- , pkgHashComponent = pkgType pkg
- , pkgHashSourceHash = files_hash
- , pkgHashDirectDeps = Set.fromList depsHashes
- , pkgHashOtherConfig = other_config
- }
+ let hashInputs = PackageHashInputs
+ { pkgHashPkgId = name
+ , pkgHashComponent = pkgType pkg
+ , pkgHashSourceHash = files_hash
+ , pkgHashDirectDeps = Set.fromList depsHashes
+ , pkgHashOtherConfig = other_config
+ }
+ rendered = renderPackageHashInputs hashInputs
+
+ debugHash <- cmdDebugHashInputs
+ when debugHash $ do
+ root <- buildRoot
+ let debugDir = root -/- "hash-inputs"
+ debugFile = debugDir -/- name <.> "txt"
+ liftIO $ createDirectoryIfMissing True debugDir
+ liftIO $ BS.writeFile debugFile rendered
+ putNormal $ "Hash inputs for " ++ name ++ ":\n" ++ BS.unpack rendered
+
+ return $ BS.unpack $ Base16.encode $ SHA256.hash rendered
allFilesInDirectory :: FilePath -> Action [FilePath]
allFilesInDirectory dir = liftIO $ listFilesRecursive dir
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f93e9415c7fdd01cb6b6ccb910bf903…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f93e9415c7fdd01cb6b6ccb910bf903…
You're receiving this email because of your account on gitlab.haskell.org.
1
0