[Git][ghc/ghc][wip/symbolizer] 3 commits: compiler: fix closure C type in SPT init code
Cheng Shao pushed to branch wip/symbolizer at Glasgow Haskell Compiler / GHC
Commits:
f38fcd9b by Cheng Shao at 2025-08-16T13:57:20+02:00
compiler: fix closure C type in SPT init code
This patch fixes the closure C type in SPT init code to StgClosure,
instead of the previously incorrect StgPtr. Having an incorrect C type
makes SPT init code not compatible with other foreign stub generation
logic, which may also emit their own extern declarations for the same
closure symbols and thus will clash with the incorrect prototypes in
SPT init code.
- - - - -
107feea4 by Cheng Shao at 2025-08-16T13:57:20+02:00
rts: remove libbfd logic
- - - - -
fd415c7a by Cheng Shao at 2025-08-16T13:57:20+02:00
compiler/rts: add debug symbolizer
- - - - -
18 changed files:
- + compiler/GHC/Cmm/GenerateDebugSymbolStub.hs
- compiler/GHC/Driver/CodeOutput.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/ghc.cabal.in
- configure.ac
- hadrian/cfg/system.config.in
- hadrian/src/Oracles/Flag.hs
- hadrian/src/Settings/Packages.hs
- − m4/fp_bfd_support.m4
- rts/Printer.c
- rts/Printer.h
- rts/RtsStartup.c
- rts/configure.ac
- rts/include/Rts.h
- rts/include/rts/Config.h
- + rts/include/rts/Debug.h
- rts/rts.cabal
Changes:
=====================================
compiler/GHC/Cmm/GenerateDebugSymbolStub.hs
=====================================
@@ -0,0 +1,138 @@
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE Strict #-}
+
+module GHC.Cmm.GenerateDebugSymbolStub
+ ( generateDebugSymbolStub,
+ )
+where
+
+import Control.Monad
+import Control.Monad.IO.Class
+import Data.Foldable
+import Data.Functor
+import Data.IORef
+import Data.List (isSuffixOf)
+import Data.Map.Strict qualified as Map
+import Data.Maybe
+import GHC.Cmm
+import GHC.Cmm.CLabel
+import GHC.Cmm.Dataflow.Label qualified as H
+import GHC.Data.FastString
+import GHC.Data.Stream (Stream)
+import GHC.Data.Stream qualified as Stream
+import GHC.Platform
+import GHC.Prelude
+import GHC.Types.ForeignStubs
+import GHC.Unit.Types
+import GHC.Utils.Outputable
+
+generateDebugSymbolStub ::
+ (MonadIO m) =>
+ Platform ->
+ Module ->
+ Stream m RawCmmGroup r ->
+ Stream m RawCmmGroup (r, CStub)
+generateDebugSymbolStub platform this_mod rawcmms0 = do
+ (lbls_ref, per_group) <- liftIO $ do
+ lbls_ref <- newIORef Map.empty
+ let per_group decls = for_ decls per_decl $> decls
+ per_decl (CmmData _ (CmmStaticsRaw lbl _)) =
+ liftIO
+ $ when (externallyVisibleCLabel lbl)
+ $ modifyIORef' lbls_ref
+ $ Map.insert lbl (data_label_type lbl)
+ per_decl (CmmProc h lbl _ _) = case H.mapToList h of
+ [] ->
+ liftIO
+ $ when (externallyVisibleCLabel lbl)
+ $ modifyIORef' lbls_ref
+ $ Map.insert lbl (proc_label_type lbl)
+ hs -> for_ hs $ \(_, CmmStaticsRaw lbl _) ->
+ liftIO
+ $ when (externallyVisibleCLabel lbl)
+ $ modifyIORef' lbls_ref
+ $ Map.insert lbl (data_label_type lbl)
+ data_label_type lbl
+ | "_closure"
+ `isSuffixOf` str
+ && not
+ (str `elem` ["stg_CHARLIKE_closure", "stg_INTLIKE_closure"]) =
+ Just ("extern StgClosure ", "")
+ | "_str" `isSuffixOf` str =
+ Just ("EB_(", ")")
+ | str
+ `elem` [ "stg_arg_bitmaps",
+ "stg_ap_stack_entries",
+ "stg_stack_save_entries"
+ ] =
+ Just ("ERO_(", ")")
+ | str
+ `elem` [ "no_break_on_exception",
+ "stg_scheduler_loop_epoch",
+ "stg_scheduler_loop_tid"
+ ] =
+ Just ("ERW_(", ")")
+ | str
+ `elem` [ "stg_gc_prim_p_ll_info",
+ "stg_gc_prim_pp_ll_info",
+ "stg_JSVAL_info",
+ "stg_scheduler_loop_info"
+ ] =
+ Just ("extern const StgInfoTable ", "")
+ | not $ needsCDecl lbl =
+ Nothing
+ | "_cc" `isSuffixOf` str =
+ Just ("extern CostCentre ", "[]")
+ | "_ccs" `isSuffixOf` str =
+ Just ("extern CostCentreStack ", "[]")
+ | "_ipe_buf" `isSuffixOf` str =
+ Just ("extern IpeBufferListNode ", "")
+ | otherwise =
+ Just ("ERW_(", ")")
+ where
+ str =
+ showSDocOneLine defaultSDocContext {sdocStyle = PprCode}
+ $ pprCLabel platform lbl
+ proc_label_type _ = Just ("EF_(", ")")
+ pure (lbls_ref, per_group)
+ r <- Stream.mapM per_group rawcmms0
+ liftIO $ do
+ lbls <- Map.toList <$> readIORef lbls_ref
+ let ctor_lbl = mkInitializerStubLabel this_mod $ fsLit "symbolizer"
+ entries_lbl =
+ mkInitializerStubLabel this_mod $ fsLit "symbolizer_entries"
+ ctor_decls =
+ vcat
+ [ text lbl_type_l
+ <> pprCLabel platform lbl
+ <> text lbl_type_r
+ <> semi
+ | (lbl, maybe_lbl_type) <- lbls,
+ (lbl_type_l, lbl_type_r) <- maybeToList maybe_lbl_type
+ ]
+ <> text "static const DebugSymbolEntry "
+ <> pprCLabel platform entries_lbl
+ <> text "[] = "
+ <> braces
+ ( hsep
+ $ punctuate
+ comma
+ [ braces
+ $ text ".addr = (void*)&"
+ <> pprCLabel platform lbl
+ <> comma
+ <> text ".sym = "
+ <> doubleQuotes (pprCLabel platform lbl)
+ | (lbl, _) <- lbls
+ ]
+ )
+ <> semi
+ ctor_body =
+ text "registerDebugSymbol"
+ <> parens
+ (pprCLabel platform entries_lbl <> comma <> int (length lbls))
+ <> semi
+ cstub = case lbls of
+ [] -> mempty
+ _ -> initializerCStub platform ctor_lbl ctor_decls ctor_body
+ pure (r, cstub)
=====================================
compiler/GHC/Driver/CodeOutput.hs
=====================================
@@ -26,6 +26,7 @@ import GHC.CmmToC ( cmmToC )
import GHC.Cmm.Lint ( cmmLint )
import GHC.Cmm
import GHC.Cmm.CLabel
+import GHC.Cmm.GenerateDebugSymbolStub
import GHC.StgToCmm.CgUtils (CgStream)
@@ -76,7 +77,8 @@ import qualified Data.Set as Set
codeOutput
:: forall a.
- Logger
+ Platform
+ -> Logger
-> TmpFs
-> LlvmConfigCache
-> DynFlags
@@ -95,7 +97,7 @@ codeOutput
(Bool{-stub_h_exists-}, Maybe FilePath{-stub_c_exists-}),
[(ForeignSrcLang, FilePath)]{-foreign_fps-},
a)
-codeOutput logger tmpfs llvm_config dflags unit_state this_mod filenm location genForeignStubs foreign_fps pkg_deps dus0
+codeOutput platform logger tmpfs llvm_config dflags unit_state this_mod filenm location genForeignStubs foreign_fps pkg_deps dus0
cmm_stream
=
do {
@@ -119,10 +121,12 @@ codeOutput logger tmpfs llvm_config dflags unit_state this_mod filenm location g
; return cmm
}
+ debug_cmm_stream = generateDebugSymbolStub platform this_mod linted_cmm_stream
+
; let final_stream :: CgStream RawCmmGroup (ForeignStubs, a)
final_stream = do
- { a <- linted_cmm_stream
- ; let stubs = genForeignStubs a
+ { (a, debug_cstub) <- debug_cmm_stream
+ ; let stubs = genForeignStubs a `appendStubC` debug_cstub
; emitInitializerDecls this_mod stubs
; return (stubs, a) }
=====================================
compiler/GHC/Driver/Main.hs
=====================================
@@ -2094,7 +2094,7 @@ hscGenHardCode hsc_env cgguts mod_loc output_filename = do
(output_filename, (_stub_h_exists, stub_c_exists), foreign_fps, cmm_cg_infos)
<- {-# SCC "codeOutput" #-}
- codeOutput logger tmpfs llvm_config dflags (hsc_units hsc_env) this_mod output_filename mod_loc
+ codeOutput platform logger tmpfs llvm_config dflags (hsc_units hsc_env) this_mod output_filename mod_loc
foreign_stubs foreign_files dependencies (initDUniqSupply 'n' 0) rawcmms1
return ( output_filename, stub_c_exists, foreign_fps
, Just stg_cg_infos, Just cmm_cg_infos)
@@ -2248,7 +2248,7 @@ hscCompileCmmFile hsc_env original_filename filename output_filename = runHsc hs
in NoStubs `appendStubC` ip_init
| otherwise = NoStubs
(_output_filename, (_stub_h_exists, stub_c_exists), _foreign_fps, _caf_infos)
- <- codeOutput logger tmpfs llvm_config dflags (hsc_units hsc_env) cmm_mod output_filename no_loc foreign_stubs [] S.empty
+ <- codeOutput platform logger tmpfs llvm_config dflags (hsc_units hsc_env) cmm_mod output_filename no_loc foreign_stubs [] S.empty
dus1 rawCmms
return stub_c_exists
where
=====================================
compiler/GHC/Iface/Tidy/StaticPtrTable.hs
=====================================
@@ -17,18 +17,18 @@
-- > static void hs_hpc_init_Main(void) {
-- >
-- > static StgWord64 k0[2] = {16252233372134256ULL,7370534374096082ULL};
--- > extern StgPtr Main_r2wb_closure;
+-- > extern StgClosure Main_r2wb_closure;
-- > hs_spt_insert(k0, &Main_r2wb_closure);
-- >
-- > static StgWord64 k1[2] = {12545634534567898ULL,5409674567544151ULL};
--- > extern StgPtr Main_r2wc_closure;
+-- > extern StgClosure Main_r2wc_closure;
-- > hs_spt_insert(k1, &Main_r2wc_closure);
-- >
-- > }
--
-- where the constants are fingerprints produced from the static forms.
--
--- The linker must find the definitions matching the @extern StgPtr <name>@
+-- The linker must find the definitions matching the @extern StgClosure <name>@
-- declarations. For this to work, the identifiers of static pointers need to be
-- exported. This is done in 'GHC.Core.Opt.SetLevels.newLvlVar'.
--
@@ -256,7 +256,7 @@ sptModuleInitCode platform this_mod entries
init_fn_body = vcat
[ text "static StgWord64 k" <> int i <> text "[2] = "
<> pprFingerprint fp <> semi
- $$ text "extern StgPtr "
+ $$ text "extern StgClosure "
<> (pprCLabel platform $ mkClosureLabel (idName n) (idCafInfo n)) <> semi
$$ text "hs_spt_insert" <> parens
(hcat $ punctuate comma
=====================================
compiler/ghc.cabal.in
=====================================
@@ -242,6 +242,7 @@ Library
GHC.Cmm.Dataflow.Label
GHC.Cmm.DebugBlock
GHC.Cmm.Expr
+ GHC.Cmm.GenerateDebugSymbolStub
GHC.Cmm.GenericOpt
GHC.Cmm.Graph
GHC.Cmm.Info
=====================================
configure.ac
=====================================
@@ -876,9 +876,6 @@ AC_SUBST([UseLibm])
TargetHasLibm=$UseLibm
AC_SUBST(TargetHasLibm)
-FP_BFD_FLAG
-AC_SUBST([UseLibbfd])
-
dnl ################################################################
dnl Check for libraries
dnl ################################################################
=====================================
hadrian/cfg/system.config.in
=====================================
@@ -120,7 +120,6 @@ use-lib-numa = @UseLibNuma@
use-lib-m = @UseLibm@
use-lib-rt = @UseLibrt@
use-lib-dl = @UseLibdl@
-use-lib-bfd = @UseLibbfd@
use-lib-pthread = @UseLibpthread@
need-libatomic = @NeedLibatomic@
=====================================
hadrian/src/Oracles/Flag.hs
=====================================
@@ -36,7 +36,6 @@ data Flag = CrossCompiling
| UseLibm
| UseLibrt
| UseLibdl
- | UseLibbfd
| UseLibpthread
| NeedLibatomic
| UseGhcToolchain
@@ -60,7 +59,6 @@ flag f = do
UseLibm -> "use-lib-m"
UseLibrt -> "use-lib-rt"
UseLibdl -> "use-lib-dl"
- UseLibbfd -> "use-lib-bfd"
UseLibpthread -> "use-lib-pthread"
NeedLibatomic -> "need-libatomic"
UseGhcToolchain -> "use-ghc-toolchain"
=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -442,7 +442,6 @@ rtsPackageArgs = package rts ? do
, useSystemFfi `cabalFlag` "use-system-libffi"
, useLibffiForAdjustors `cabalFlag` "libffi-adjustors"
, flag UseLibpthread `cabalFlag` "need-pthread"
- , flag UseLibbfd `cabalFlag` "libbfd"
, flag NeedLibatomic `cabalFlag` "need-atomic"
, flag UseLibdw `cabalFlag` "libdw"
, flag UseLibnuma `cabalFlag` "libnuma"
=====================================
m4/fp_bfd_support.m4 deleted
=====================================
@@ -1,59 +0,0 @@
-# FP_BFD_SUPPORT()
-# ----------------------
-# Whether to use libbfd for debugging RTS
-#
-# Sets:
-# UseLibbfd: [YES|NO]
-AC_DEFUN([FP_BFD_FLAG], [
- UseLibbfd=NO
- AC_ARG_ENABLE(bfd-debug,
- [AS_HELP_STRING([--enable-bfd-debug],
- [Enable symbol resolution for -debug rts ('+RTS -Di') via binutils' libbfd [default=no]])],
- [UseLibbfd=YES],
- [UseLibbfd=NO])
-])
-
-# FP_WHEN_ENABLED_BFD
-# ----------------------
-# Checks for libraries in the default way, which will define various
-# `HAVE_*` macros.
-AC_DEFUN([FP_WHEN_ENABLED_BFD], [
- # don't pollute general LIBS environment
- save_LIBS="$LIBS"
- AC_CHECK_HEADERS([bfd.h])
- dnl ** check whether this machine has BFD and libiberty installed (used for debugging)
- dnl the order of these tests matters: bfd needs libiberty
- AC_CHECK_LIB(iberty, xmalloc)
- dnl 'bfd_init' is a rare non-macro in libbfd
- AC_CHECK_LIB(bfd, bfd_init)
-
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM(
- [[#include
participants (1)
-
Cheng Shao (@TerrorJack)