diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-02-08 19:04:41 -0500 |
---|---|---|
committer | Matthew Pickering <matthewtpickering@gmail.com> | 2022-04-01 10:34:39 +0100 |
commit | 5beeff46972b8b52e9f2572fff8b1ad9ace38cd8 (patch) | |
tree | f3fb4084554f8de4b2f9d8b0b6144cbc9ad1f342 /compiler/GHC/Iface | |
parent | 6793a20fe0cd1f04dabad46b87e86018abf73e54 (diff) | |
download | haskell-5beeff46972b8b52e9f2572fff8b1ad9ace38cd8.tar.gz |
Refactor handling of global initializers
GHC uses global initializers for a number of things including
cost-center registration, info-table provenance registration, and setup
of foreign exports. Previously, the global initializer arrays which
referenced these initializers would live in the object file of the C
stub, which would then be merged into the main object file of the
module.
Unfortunately, this approach is no longer tenable with the move to
Clang/LLVM on Windows (see #21019). Specifically, lld's PE backend does
not support object merging (that is, the -r flag). Instead we are now
rather packaging a module's object files into a static library. However,
this is problematic in the case of initializers as there are no
references to the C stub object in the archive, meaning that the linker
may drop the object from the final link.
This patch refactors our handling of global initializers to instead
place initializer arrays within the object file of the module to which
they belong. We do this by introducing a Cmm data declaration containing
the initializer array in the module's Cmm stream. While the initializer
functions themselves remain in separate C stub objects, the reference
from the module's object ensures that they are not dropped from the
final link.
In service of #21068.
Diffstat (limited to 'compiler/GHC/Iface')
-rw-r--r-- | compiler/GHC/Iface/Tidy/StaticPtrTable.hs | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/compiler/GHC/Iface/Tidy/StaticPtrTable.hs b/compiler/GHC/Iface/Tidy/StaticPtrTable.hs index ab29a395da..3107a593b1 100644 --- a/compiler/GHC/Iface/Tidy/StaticPtrTable.hs +++ b/compiler/GHC/Iface/Tidy/StaticPtrTable.hs @@ -240,11 +240,12 @@ sptCreateStaticBinds opts this_mod binds = do -- its fingerprint. sptModuleInitCode :: Platform -> Module -> [SptEntry] -> CStub sptModuleInitCode _ _ [] = mempty -sptModuleInitCode platform this_mod entries = CStub $ vcat - [ text "static void hs_spt_init_" <> ppr this_mod - <> text "(void) __attribute__((constructor));" - , text "static void hs_spt_init_" <> ppr this_mod <> text "(void)" - , braces $ vcat $ +sptModuleInitCode platform this_mod entries = + initializerCStub platform init_fn_nm empty init_fn_body `mappend` + finalizerCStub platform fini_fn_nm empty fini_fn_body + where + init_fn_nm = mkInitializerStubLabel this_mod "spt" + init_fn_body = vcat [ text "static StgWord64 k" <> int i <> text "[2] = " <> pprFingerprint fp <> semi $$ text "extern StgPtr " @@ -258,17 +259,15 @@ sptModuleInitCode platform this_mod entries = CStub $ vcat <> semi | (i, SptEntry n fp) <- zip [0..] entries ] - , text "static void hs_spt_fini_" <> ppr this_mod - <> text "(void) __attribute__((destructor));" - , text "static void hs_spt_fini_" <> ppr this_mod <> text "(void)" - , braces $ vcat $ + + fini_fn_nm = mkFinalizerStubLabel this_mod "spt" + fini_fn_body = vcat [ text "StgWord64 k" <> int i <> text "[2] = " <> pprFingerprint fp <> semi $$ text "hs_spt_remove" <> parens (char 'k' <> int i) <> semi | (i, (SptEntry _ fp)) <- zip [0..] entries ] - ] - where + pprFingerprint :: Fingerprint -> SDoc pprFingerprint (Fingerprint w1 w2) = braces $ hcat $ punctuate comma |