Andrea Vezzosi pushed to branch wip/andrea/splitsections at Glasgow Haskell Compiler / GHC
Commits:
-
4aa3f2d1
by Andrea Vezzosi at 2026-11-03T12:43:38+01:00
13 changed files:
- + changelog.d/split-sections-dynamic
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Platform/Ways.hs
- docs/users_guide/phases.rst
- testsuite/tests/codeGen/should_gen_asm/all.T
- + testsuite/tests/codeGen/should_gen_asm/split-sections-dynamic1.asm
- + testsuite/tests/codeGen/should_gen_asm/split-sections-dynamic1.hs
- + testsuite/tests/codeGen/should_gen_asm/split-sections-dynamic2.asm
- + testsuite/tests/codeGen/should_gen_asm/split-sections-dynamic2.hs
- testsuite/tests/llvm/should_compile/all.T
- + testsuite/tests/llvm/should_compile/split-sections-darwin.hs
Changes:
| 1 | +section: compiler
|
|
| 2 | +synopsis: ``-fsplit-sections`` is no longer disabled by ``-dynamic``
|
|
| 3 | +description:
|
|
| 4 | + ``-dynamic`` used to unset ``-fsplit-sections``, but only when
|
|
| 5 | + ``-fsplit-sections`` appeared earlier on the command line, so the flag meant
|
|
| 6 | + different things depending on the order of the two. Both orders now split
|
|
| 7 | + sections, as do the dynamic outputs of ``-dynamic-too``.
|
|
| 8 | + |
|
| 9 | + On Darwin, ``-fsplit-sections`` is now always ignored with a warning: Mach-O
|
|
| 10 | + has poor support for split sections and instead offers
|
|
| 11 | + ``.subsections_via_symbols``, which GHC uses where it's able to.
|
|
| 12 | + |
|
| 13 | +mrs: !16915
|
|
| 14 | +issues: #28061 |
| ... | ... | @@ -1638,10 +1638,7 @@ enableCodeGenWhen logger tmpfs staticLife dynLife unit_env mod_graph = do |
| 1638 | 1638 | dflags_b = foldl gopt_set dflags_a
|
| 1639 | 1639 | $ concatMap (wayGeneralFlags platform)
|
| 1640 | 1640 | hostFullWays
|
| 1641 | - dflags_c = foldl gopt_unset dflags_b
|
|
| 1642 | - $ concatMap (wayUnsetGeneralFlags platform)
|
|
| 1643 | - hostFullWays
|
|
| 1644 | - in dflags_c
|
|
| 1641 | + in dflags_b
|
|
| 1645 | 1642 | |
| 1646 | 1643 | {- Note [-fno-code mode]
|
| 1647 | 1644 | ~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1079,16 +1079,13 @@ dopt_unset dfs f = dfs{ dumpFlags = EnumSet.delete f (dumpFlags dfs) } |
| 1079 | 1079 | -- | Test whether a 'GeneralFlag' is set
|
| 1080 | 1080 | --
|
| 1081 | 1081 | -- Note that `dynamicNow` (i.e., dynamic objects built with `-dynamic-too`)
|
| 1082 | --- always implicitly enables Opt_PIC, Opt_ExternalDynamicRefs, and disables
|
|
| 1082 | +-- always implicitly enables Opt_PIC and Opt_ExternalDynamicRefs.
|
|
| 1083 | 1083 | --
|
| 1084 | 1084 | gopt :: GeneralFlag -> DynFlags -> Bool
|
| 1085 | 1085 | gopt Opt_PIC dflags
|
| 1086 | 1086 | | dynamicNow dflags = True
|
| 1087 | 1087 | gopt Opt_ExternalDynamicRefs dflags
|
| 1088 | 1088 | | dynamicNow dflags = True
|
| 1089 | - | dynamicNow dflags = True
|
|
| 1090 | -gopt Opt_SplitSections dflags
|
|
| 1091 | 1089 | gopt f dflags = f `EnumSet.member` generalFlags dflags
|
| 1092 | 1090 | |
| 1093 | 1091 | -- | Set a 'GeneralFlag'
|
| ... | ... | @@ -2985,9 +2985,7 @@ addWay' w dflags0 = |
| 2985 | 2985 | dflags1 = dflags0 { targetWays_ = addWay w (targetWays_ dflags0) }
|
| 2986 | 2986 | dflags2 = foldr setGeneralFlag' dflags1
|
| 2987 | 2987 | (wayGeneralFlags platform w)
|
| 2988 | - dflags3 = foldr unSetGeneralFlag' dflags2
|
|
| 2989 | - (wayUnsetGeneralFlags platform w)
|
|
| 2990 | - in dflags3
|
|
| 2988 | + in dflags2
|
|
| 2991 | 2989 | |
| 2992 | 2990 | removeWayDynP :: Way -> DynP ()
|
| 2993 | 2991 | removeWayDynP w = upd (\dfs -> dfs { targetWays_ = removeWay w (targetWays_ dfs) })
|
| ... | ... | @@ -3806,6 +3804,20 @@ In the checks and fixes performed by `makeDynFlagsConsistent`, the choice |
| 3806 | 3804 | between the two does not seem uniform. TODO: Make this choice more evident and uniform.
|
| 3807 | 3805 | -}
|
| 3808 | 3806 | |
| 3807 | +{- Note [Split sections are not supported on Darwin]
|
|
| 3808 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 3809 | +On Darwin, split sections are either ignored by the backends (NCG, C) or would
|
|
| 3810 | +cause errors (LLVM, see split-sections-darwin test).
|
|
| 3811 | + |
|
| 3812 | +The `.subsections_via_symbols` feature of Mach-O is used instead (see Note
|
|
| 3813 | +[Subsections Via Symbols]). This works on x86_64, but not yet on aarch64 (c.f
|
|
| 3814 | +#24962 #23672).
|
|
| 3815 | + |
|
| 3816 | +`makeDynFlagsConsistent` then disables split-sections on darwin unconditionally.
|
|
| 3817 | +This is redundant on x86_64, because of the `platformHasSubsectionsViaSymbols`
|
|
| 3818 | +check, but harmless.
|
|
| 3819 | +-}
|
|
| 3820 | + |
|
| 3809 | 3821 | -- | Resolve any internal inconsistencies in a set of 'DynFlags'.
|
| 3810 | 3822 | -- Returns the consistent 'DynFlags' as well as a list of warnings
|
| 3811 | 3823 | -- to report to the user, and a list of verbose info msgs.
|
| ... | ... | @@ -3835,6 +3847,13 @@ makeDynFlagsConsistent dflags |
| 3835 | 3847 | "since it uses subsections-via-symbols. Ignoring."
|
| 3836 | 3848 | in loop dflags' warn
|
| 3837 | 3849 | |
| 3850 | + -- See Note [Split sections are not supported on Mach-O]
|
|
| 3851 | + | gopt Opt_SplitSections dflags
|
|
| 3852 | + , os == OSDarwin
|
|
| 3853 | + = let dflags' = gopt_unset dflags Opt_SplitSections
|
|
| 3854 | + warn = "-fsplit-sections is not supported on Mach-O. Ignoring."
|
|
| 3855 | + in loop dflags' warn
|
|
| 3856 | + |
|
| 3838 | 3857 | -- Via-C backend only supports unregisterised ABI. Switch to a backend
|
| 3839 | 3858 | -- supporting it if possible.
|
| 3840 | 3859 | | backendUnregisterisedAbiOnly (backend dflags) &&
|
| ... | ... | @@ -3950,10 +3969,7 @@ makeDynFlagsConsistent dflags |
| 3950 | 3969 | dflags_b = foldl gopt_set dflags_a
|
| 3951 | 3970 | $ concatMap (wayGeneralFlags platform)
|
| 3952 | 3971 | hostFullWays
|
| 3953 | - dflags_c = foldl gopt_unset dflags_b
|
|
| 3954 | - $ concatMap (wayUnsetGeneralFlags platform)
|
|
| 3955 | - hostFullWays
|
|
| 3956 | - in dflags_c
|
|
| 3972 | + in dflags_b
|
|
| 3957 | 3973 | |
| 3958 | 3974 | | gopt Opt_InfoTableMap dflags
|
| 3959 | 3975 | , NotValid msg <- backendInfoTableMapValidity (backend dflags)
|
| ... | ... | @@ -28,7 +28,6 @@ module GHC.Platform.Ways |
| 28 | 28 | , removeWay
|
| 29 | 29 | , allowed_combination
|
| 30 | 30 | , wayGeneralFlags
|
| 31 | - , wayUnsetGeneralFlags
|
|
| 32 | 31 | , wayOptc
|
| 33 | 32 | , wayOptcxx
|
| 34 | 33 | , wayOptl
|
| ... | ... | @@ -164,16 +163,6 @@ wayGeneralFlags platform WayProf |
| 164 | 163 | - https://gitlab.haskell.org/ghc/ghc/-/issues/26994 -}
|
| 165 | 164 | wayGeneralFlags _ WayProf = []
|
| 166 | 165 | |
| 167 | --- | Turn these flags off when enabling this way
|
|
| 168 | -wayUnsetGeneralFlags :: Platform -> Way -> [GeneralFlag]
|
|
| 169 | -wayUnsetGeneralFlags _ (WayCustom {}) = []
|
|
| 170 | -wayUnsetGeneralFlags _ WayThreaded = []
|
|
| 171 | -wayUnsetGeneralFlags _ WayDebug = []
|
|
| 172 | -wayUnsetGeneralFlags _ WayDyn = [Opt_SplitSections]
|
|
| 173 | - -- There's no point splitting when we're going to be dynamically linking.
|
|
| 174 | - -- Plus it breaks compilation on OSX x86.
|
|
| 175 | -wayUnsetGeneralFlags _ WayProf = []
|
|
| 176 | - |
|
| 177 | 166 | -- | Pass these options to the C compiler when enabling this way
|
| 178 | 167 | wayOptc :: Platform -> Way -> [String]
|
| 179 | 168 | wayOptc _ (WayCustom {}) = []
|
| ... | ... | @@ -1063,6 +1063,10 @@ for example). |
| 1063 | 1063 | When linking, the linker can automatically remove all unreferenced sections
|
| 1064 | 1064 | and thus produce smaller executables.
|
| 1065 | 1065 | |
| 1066 | + This flag is ignored on Darwin as the Mach-O object format is not suitable
|
|
| 1067 | + for split sections. The ``.subsections_via_symbols`` directive and the
|
|
| 1068 | + linker's ``-dead_strip`` are used where supported, regardless of this flag.
|
|
| 1069 | + |
|
| 1066 | 1070 | .. ghc-flag:: -static
|
| 1067 | 1071 | :shortdesc: Use static Haskell libraries
|
| 1068 | 1072 | :type: dynamic
|
| ... | ... | @@ -11,6 +11,22 @@ test('bytearray-memset-unroll', is_amd64_codegen, compile_grep_asm, ['hs', True, |
| 11 | 11 | test('bytearray-memcpy-unroll', is_amd64_codegen, compile_grep_asm, ['hs', True, ''])
|
| 12 | 12 | test('T18137', [when(opsys('darwin'), skip), only_ways(llvm_ways)], compile_grep_asm, ['hs', False, '-fllvm -split-sections'])
|
| 13 | 13 | |
| 14 | +# -fsplit-sections used to be silently unset by -dynamic, but only when it
|
|
| 15 | +# appeared before -dynamic on the command line. Check that both orders split.
|
|
| 16 | +# Mach-O has no split sections at all, and COFF names subsections with '$'.
|
|
| 17 | +split_sections_dynamic = [
|
|
| 18 | + unless(have_dynamic(), skip),
|
|
| 19 | + when(opsys('darwin'), skip),
|
|
| 20 | + when(opsys('mingw32'), skip),
|
|
| 21 | + when(unregisterised(), skip),
|
|
| 22 | + only_ways(['normal']),
|
|
| 23 | +]
|
|
| 24 | + |
|
| 25 | +test('split-sections-dynamic1', split_sections_dynamic, compile_grep_asm,
|
|
| 26 | + ['hs', False, '-fsplit-sections -dynamic'])
|
|
| 27 | +test('split-sections-dynamic2', split_sections_dynamic, compile_grep_asm,
|
|
| 28 | + ['hs', False, '-dynamic -fsplit-sections'])
|
|
| 29 | + |
|
| 14 | 30 | test('T24941', [only_ways(['optasm'])], compile, ['-fregs-graph'])
|
| 15 | 31 | |
| 16 | 32 | test('msse-option-order', [unless(arch('x86_64') or arch('i386'), skip),
|
| 1 | +\.section\s+\.text\.SplitSectionsDyn_ |
|
| \ No newline at end of file |
| 1 | +-- -fsplit-sections before -dynamic; split-sections-dynamic2 is the other order.
|
|
| 2 | +module SplitSectionsDyn (f, g) where
|
|
| 3 | + |
|
| 4 | +f :: Int -> Int
|
|
| 5 | +f x = x + 1
|
|
| 6 | + |
|
| 7 | +g :: Int -> Int
|
|
| 8 | +g = (* 2) |
| 1 | +\.section\s+\.text\.SplitSectionsDyn_ |
|
| \ No newline at end of file |
| 1 | +-- -dynamic before -fsplit-sections; split-sections-dynamic1 is the other order.
|
|
| 2 | +module SplitSectionsDyn (f, g) where
|
|
| 3 | + |
|
| 4 | +f :: Int -> Int
|
|
| 5 | +f x = x + 1
|
|
| 6 | + |
|
| 7 | +g :: Int -> Int
|
|
| 8 | +g = (* 2) |
| ... | ... | @@ -23,3 +23,8 @@ test('T17920fail', cmm_src, compile_fail, ['-no-hs-main']) |
| 23 | 23 | test('T25019', unless((arch('x86_64') or arch('i386')) and have_cpu_feature('sse4_2'),skip), compile, ['-msse4.2'])
|
| 24 | 24 | test('T25353', unless((arch('x86_64') or arch('i386')) and have_cpu_feature('sse4_2'),skip), compile_grep_asm, ['hs', True, '-msse4.2'])
|
| 25 | 25 | test('T25606', normal, compile, [''])
|
| 26 | + |
|
| 27 | +test('split-sections-darwin',
|
|
| 28 | + [unless(opsys('darwin'), skip),
|
|
| 29 | + normalise_errmsg_fun(ignore_llvm_and_vortex)],
|
|
| 30 | + compile, ['-fsplit-sections -Wno-inconsistent-flags']) |
| 1 | +-- -fsplit-sections must be ignored on Darwin; see
|
|
| 2 | +-- Note [Split sections are not supported on Mach-O] in GHC.Driver.Session.
|
|
| 3 | +--
|
|
| 4 | +-- Mach-O cannot name a section after a symbol, so GHC ignores -fsplit-sections
|
|
| 5 | +-- on Darwin. Without that, llvmFunSection emits ELF-style ".text.<label>" names
|
|
| 6 | +-- and LLVM rejects them. Only reproduces on AArch64/Darwin: on
|
|
| 7 | +-- x86_64/Darwin the flag is already dropped for subsections-via-symbols.
|
|
| 8 | +-- -Wno-inconsistent-flags suppresses the "Ignoring" warning, whose wording
|
|
| 9 | +-- differs between the two Darwin platforms.
|
|
| 10 | +module SplitSectionsDarwin (f) where
|
|
| 11 | + |
|
| 12 | +f :: Int -> Int
|
|
| 13 | +f x = x + 1 |