summaryrefslogtreecommitdiff
path: root/compiler/GHC/Cmm/CLabel.hs
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-12-27 12:38:27 -0500
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-11-11 03:20:00 -0500
commitc6264a2d652517954b7cd076c7bc4487ed17c97d (patch)
treebd11c475186c63a147f5b58958458c9fc4eef68e /compiler/GHC/Cmm/CLabel.hs
parent6e23695e7d84aa248e7ca20bdb8d133f9b356548 (diff)
downloadhaskell-c6264a2d652517954b7cd076c7bc4487ed17c97d.tar.gz
codeGen: Produce local symbols for module-internal functions
It turns out that some important native debugging/profiling tools (e.g. perf) rely only on symbol tables for function name resolution (as opposed to using DWARF DIEs). However, previously GHC would emit temporary symbols (e.g. `.La42b`) to identify module-internal entities. Such symbols are dropped during linking and therefore not visible to runtime tools (in addition to having rather un-helpful unique names). For instance, `perf report` would often end up attributing all cost to the libc `frame_dummy` symbol since Haskell code was no covered by any proper symbol (see #17605). We now rather follow the model of C compilers and emit descriptively-named local symbols for module internal things. Since this will increase object file size this behavior can be disabled with the `-fno-expose-internal-symbols` flag. With this `perf record` can finally be used against Haskell executables. Even more, with `-g3` `perf annotate` provides inline source code.
Diffstat (limited to 'compiler/GHC/Cmm/CLabel.hs')
-rw-r--r--compiler/GHC/Cmm/CLabel.hs34
1 files changed, 34 insertions, 0 deletions
diff --git a/compiler/GHC/Cmm/CLabel.hs b/compiler/GHC/Cmm/CLabel.hs
index 3d21855ec2..d5df2dd1c5 100644
--- a/compiler/GHC/Cmm/CLabel.hs
+++ b/compiler/GHC/Cmm/CLabel.hs
@@ -118,6 +118,7 @@ module GHC.Cmm.CLabel (
LabelStyle (..),
pprDebugCLabel,
pprCLabel,
+ ppInternalProcLabel,
-- * Others
dynamicLinkerLabelInfo,
@@ -1360,6 +1361,39 @@ pprCLabel platform sty lbl =
CmmLabel _ _ fs CmmRet -> maybe_underscore $ ftext fs <> text "_ret"
CmmLabel _ _ fs CmmClosure -> maybe_underscore $ ftext fs <> text "_closure"
+-- Note [Internal proc labels]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- Some tools (e.g. the `perf` utility on Linux) rely on the symbol table
+-- for resolution of function names. To help these tools we provide the
+-- (enabled by default) -fexpose-all-symbols flag which causes GHC to produce
+-- symbols even for symbols with are internal to a module (although such
+-- symbols will have only local linkage).
+--
+-- Note that these labels are *not* referred to by code. They are strictly for
+-- diagnostics purposes.
+--
+-- To avoid confusion, it is desireable to add a module-qualifier to the
+-- symbol name. However, the Name type's Internal constructor doesn't carry
+-- knowledge of the current Module. Consequently, we have to pass this around
+-- explicitly.
+
+-- | Generate a label for a procedure internal to a module (if
+-- 'Opt_ExposeAllSymbols' is enabled).
+-- See Note [Internal proc labels].
+ppInternalProcLabel :: Module -- ^ the current module
+ -> CLabel
+ -> Maybe SDoc -- ^ the internal proc label
+ppInternalProcLabel this_mod (IdLabel nm _ flavour)
+ | isInternalName nm
+ = Just
+ $ text "_" <> ppr this_mod
+ <> char '_'
+ <> ztext (zEncodeFS (occNameFS (occName nm)))
+ <> char '_'
+ <> pprUniqueAlways (getUnique nm)
+ <> ppIdFlavor flavour
+ppInternalProcLabel _ _ = Nothing
ppIdFlavor :: IdLabelInfo -> SDoc
ppIdFlavor x = pp_cSEP <> case x of