summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-12-27 17:38:27 (GMT)
committerBen Gamari <ben@smart-cactus.org>2019-12-27 20:00:54 (GMT)
commit0398c938ff3c9ca5c125d9f414d4561bbcb55a36 (patch)
treeb8539df9d10b382a6efdbbd1510a9141ce884c2e
parent334290b6681796dd141c964b88c541da13ce03c7 (diff)
downloadghc-wip/local-symbols.zip
ghc-wip/local-symbols.tar.gz
ghc-wip/local-symbols.tar.bz2
codeGen: Produce local symbols for module-internal functionswip/local-symbols
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-all-symbols` flag. With this `perf record` can finally be used against Haskell executables. Even more, with `-g3` `perf annotate` provides inline source code.
-rw-r--r--compiler/basicTypes/Name.hs5
-rw-r--r--compiler/cmm/CLabel.hs8
-rw-r--r--compiler/main/DynFlags.hs5
-rw-r--r--docs/users_guide/phases.rst14
4 files changed, 26 insertions, 6 deletions
diff --git a/compiler/basicTypes/Name.hs b/compiler/basicTypes/Name.hs
index 2cbd50e..9798617 100644
--- a/compiler/basicTypes/Name.hs
+++ b/compiler/basicTypes/Name.hs
@@ -567,7 +567,10 @@ pprExternal sty uniq mod occ is_wired is_builtin
pprInternal :: PprStyle -> Unique -> OccName -> SDoc
pprInternal sty uniq occ
- | codeStyle sty = pprUniqueAlways uniq
+ | codeStyle sty = sdocWithDynFlags $ \dflags ->
+ if gopt Opt_ExposeAllSymbols dflags
+ then char '_' <> ppr_z_occ_name occ <> ppr_underscore_unique uniq
+ else pprUniqueAlways uniq
| debugStyle sty = ppr_occ_name occ <> braces (hsep [pprNameSpaceBrief (occNameSpace occ),
pprUnique uniq])
| dumpStyle sty = ppr_occ_name occ <> ppr_underscore_unique uniq
diff --git a/compiler/cmm/CLabel.hs b/compiler/cmm/CLabel.hs
index 9452b5f..1a9e14c 100644
--- a/compiler/cmm/CLabel.hs
+++ b/compiler/cmm/CLabel.hs
@@ -1302,8 +1302,8 @@ pprCLbl (RtsLabel (RtsSlowFastTickyCtr pat))
pprCLbl (ForeignLabel str _ _ _)
= ftext str
-pprCLbl (IdLabel name _cafs flavor) =
- internalNamePrefix name <> ppr name <> ppIdFlavor flavor
+pprCLbl (IdLabel name _cafs flavor)
+ = internalNamePrefix name <> ppr name <> ppIdFlavor flavor
pprCLbl (CC_Label cc) = ppr cc
pprCLbl (CCS_Label ccs) = ppr ccs
@@ -1347,8 +1347,8 @@ instance Outputable ForeignLabelSource where
ForeignLabelInExternalPackage -> parens $ text "external package"
internalNamePrefix :: Name -> SDoc
-internalNamePrefix name = getPprStyle $ \ sty ->
- if asmStyle sty && isRandomGenerated then
+internalNamePrefix name = sdocWithDynFlags $ \dflags -> getPprStyle $ \ sty ->
+ if asmStyle sty && isRandomGenerated && not (gopt Opt_ExposeAllSymbols dflags) then
sdocWithPlatform $ \platform ->
ptext (asmTempLabelPrefix platform)
else
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 94cee4a..65e5f77 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -656,6 +656,7 @@ data GeneralFlag
-- forwards all -L flags to the collect2 command without using a
-- response file and as such breaking apart.
| Opt_SingleLibFolder
+ | Opt_ExposeAllSymbols
| Opt_KeepCAFs
| Opt_KeepGoing
| Opt_ByteCode
@@ -4220,6 +4221,7 @@ fFlagsDeps = [
flagSpec "error-spans" Opt_ErrorSpans,
flagSpec "excess-precision" Opt_ExcessPrecision,
flagSpec "expose-all-unfoldings" Opt_ExposeAllUnfoldings,
+ flagSpec "expose-all-symbols" Opt_ExposeAllSymbols,
flagSpec "external-dynamic-refs" Opt_ExternalDynamicRefs,
flagSpec "external-interpreter" Opt_ExternalInterpreter,
flagSpec "flat-cache" Opt_FlatCache,
@@ -4589,7 +4591,8 @@ defaultFlags settings
Opt_RPath,
Opt_SharedImplib,
Opt_SimplPreInlining,
- Opt_VersionMacros
+ Opt_VersionMacros,
+ Opt_ExposeAllSymbols
]
++ [f | (ns,f) <- optLevelFlags, 0 `elem` ns]
diff --git a/docs/users_guide/phases.rst b/docs/users_guide/phases.rst
index d0afe80..705d16c 100644
--- a/docs/users_guide/phases.rst
+++ b/docs/users_guide/phases.rst
@@ -652,6 +652,20 @@ Options affecting code generation
and ``-dynhisuf`` are the counterparts of ``-o``, ``-osuf``, and
``-hisuf`` respectively, but applying to the dynamic compilation.
+.. ghc-flag:: -fexpose-all-symbols
+ :shortdesc: Produce symbols for all functions, including internal functions.
+ :type: dynamic
+ :category: codegen
+ :default: on
+
+ By default, GHC emits verbose symbol tables which include local symbols for
+ module-internal functions. These can be useful for tools like :ref:`perf
+ <https://perf.wiki.kernel.org/>` but increase object file sizes.
+
+ :ghc-flag:`-fno-expose-all-symbols` suppresses all non-global symbol table
+ entries, resulting in smaller object file sizes at the expense of
+ debuggability.
+
.. _options-linker:
Options affecting linking