[project @ 2005-01-23 06:10:15 by wolfgang]
authorwolfgang <unknown>
Sun, 23 Jan 2005 06:10:24 +0000 (06:10 +0000)
committerwolfgang <unknown>
Sun, 23 Jan 2005 06:10:24 +0000 (06:10 +0000)
Add support for the dead code stripping feature of recent Apple linkers.
If your code is compiled using the NCG, you can now specify
-optl-W,-dead_strip on the GHC command line when linking.
It will have basically the same effect as using split-objs to build the
libraries.

Advantages over split-objs:
    * No evil perl script involved
    * Requires no special handling when building libraries

Disadvantages:
    * The current version of Apple's linker is slow when given the
      -dead_strip flag. _REALLY_ slow.
    * Mac OS X only.

This works by making the NCG emit the .subsections_via_symbols directive.
Additionally, we have to add an extra label at the top of every info table,
and make sure that the entry code references it (otherwise the info table
will be considered part of the preceding entry code).
The mangler just removes the .subsections_via_symbols directive.

configure.ac
ghc/compiler/cmm/CLabel.hs
ghc/compiler/nativeGen/AsmCodeGen.lhs
ghc/compiler/nativeGen/PprMach.hs
ghc/driver/mangler/ghc-asm.lprl
ghc/rts/StgCRun.c

index 7351b39..76e961d 100644 (file)
@@ -1245,6 +1245,22 @@ dnl ** check for ld, whether it has an -x option, and if it is GNU ld
 FP_PROG_LD_X
 FP_PROG_LD_IS_GNU
 
+dnl ** check for Apple-style dead-stripping support
+dnl    (.subsections-via-symbols assembler directive)
+
+
+AC_MSG_CHECKING(for .subsections_via_symbols)
+AC_TRY_COMPILE(,[__asm__ (".subsections_via_symbols");],
+    [
+        AC_MSG_RESULT(yes)
+        AC_DEFINE([HAVE_SUBSECTIONS_VIA_SYMBOLS],[1],
+            [Define to 1 if Apple-style dead-stripping is supported.])
+    ],
+    [
+        AC_DEFINE([HAVE_SUBSECTIONS_VIA_SYMBOLS],[0],
+            [Define to 1 if Apple-style dead-stripping is supported.])
+    ])
+
 AC_CONFIG_FILES([mk/config.mk])
 AC_CONFIG_COMMANDS([mk/stamp-h],[echo timestamp > mk/stamp-h])
 AC_OUTPUT
index 6f95be9..0fd4ba4 100644 (file)
@@ -87,6 +87,7 @@ module CLabel (
         dynamicLinkerLabelInfo,
         
         mkPicBaseLabel,
+        mkDeadStripPreventer,
 
        infoLblToEntryLbl, entryLblToInfoLbl,
        needsCDecl, isAsmTemp, externallyVisibleCLabel,
@@ -197,6 +198,9 @@ data CLabel
                                 -- as 1b, referring to the previous definition
                                 -- of 1: in the assembler source file.
 
+  | DeadStripPreventer CLabel
+    -- label before an info table to prevent excessive dead-stripping on darwin
+
   deriving (Eq, Ord)
 
 data IdLabelInfo
@@ -402,6 +406,9 @@ dynamicLinkerLabelInfo _ = Nothing
 mkPicBaseLabel :: CLabel
 mkPicBaseLabel = PicBaseLabel
 
+mkDeadStripPreventer :: CLabel -> CLabel
+mkDeadStripPreventer lbl = DeadStripPreventer lbl
+
 -- -----------------------------------------------------------------------------
 -- Converting info labels to entry labels.
 
@@ -619,6 +626,9 @@ pprCLabel (DynamicLinkerLabel info lbl)
    
 pprCLabel PicBaseLabel
    = ptext SLIT("1b")
+   
+pprCLabel (DeadStripPreventer lbl)
+   = pprCLabel lbl <> ptext SLIT("_dsp")
 #endif
 
 pprCLabel lbl = 
index b8fd0e3..5844c89 100644 (file)
@@ -121,7 +121,14 @@ nativeCodeGen dflags cmms us
           returnUs (Cmm cmms, my_vcat docs, concat imps)
     in do
     dumpIfSet_dyn dflags Opt_D_dump_opt_cmm "Optimised Cmm" (pprCmms [ppr_cmms])
-    return (insn_sdoc Pretty.$$ dyld_stubs imports)
+    return (insn_sdoc Pretty.$$ dyld_stubs imports
+#if HAVE_SUBSECTIONS_VIA_SYMBOLS
+                -- On recent versions of Darwin, the linker supports
+                -- dead-stripping of code and data on a per-symbol basis.
+                -- There's a hack to make this work in PprMach.pprNatCmmTop.
+            Pretty.$$ Pretty.text ".subsections_via_symbols"
+#endif
+            )
 
   where
 
index b1547f1..9c73def 100644 (file)
@@ -27,6 +27,9 @@ import MachInstrs
 
 import CLabel          ( CLabel, pprCLabel, externallyVisibleCLabel,
                          labelDynamic, mkAsmTempLabel, entryLblToInfoLbl )
+#if HAVE_SUBSECTIONS_VIA_SYMBOLS
+import CLabel       ( mkDeadStripPreventer )
+#endif
 
 import Panic           ( panic )
 import Unique          ( pprUnique )
@@ -68,8 +71,13 @@ pprNatCmmTop (CmmProc [] lbl _ []) = pprLabel lbl
 pprNatCmmTop (CmmProc info lbl params blocks) = 
   pprSectionHeader Text $$
   (if not (null info)
-       then vcat (map pprData info) 
-               $$ pprLabel (entryLblToInfoLbl lbl)
+       then
+#if HAVE_SUBSECTIONS_VIA_SYMBOLS
+            pprCLabel_asm (mkDeadStripPreventer $ entryLblToInfoLbl lbl)
+                <> char ':' $$
+#endif
+            vcat (map pprData info) $$
+            pprLabel (entryLblToInfoLbl lbl)
        else empty) $$
   (case blocks of
        [] -> empty
@@ -77,7 +85,22 @@ pprNatCmmTop (CmmProc info lbl params blocks) =
                (if null info then pprLabel lbl else empty) $$
                -- the first block doesn't get a label:
                vcat (map pprInstr instrs) $$
-               vcat (map pprBasicBlock rest))
+               vcat (map pprBasicBlock rest)
+  )
+#if HAVE_SUBSECTIONS_VIA_SYMBOLS
+        -- If we are using the .subsections_via_symbols directive
+        -- (available on recent versions of Darwin),
+        -- we have to make sure that there is some kind of reference
+        -- from the entry code to a label on the _top_ of of the info table,
+        -- so that the linker will not think it is unreferenced and dead-strip
+        -- it. That's why the label is called a DeadStripPreventer (_dsp).
+  $$ if not (null info)
+                   then text "\t.long "
+                     <+> pprCLabel_asm (entryLblToInfoLbl lbl)
+                     <+> char '-'
+                     <+> pprCLabel_asm (mkDeadStripPreventer $ entryLblToInfoLbl lbl)
+                   else empty
+#endif
 
 
 pprBasicBlock :: NatBasicBlock -> Doc
index 886ada8..77010c8 100644 (file)
@@ -533,7 +533,12 @@ sub mangle_asm {
        } elsif ( /\.\.ng:$/ && $TargetPlatform =~ /^alpha-/ ) {
            # Alphas: Local labels not to be confused with new chunks
            $chk[$i] .= $_;
-  
+        } elsif ( $TargetPlatform =~ /-darwin/
+                && /^\t\.subsections_via_symbols/) {
+            # Don't allow Apple's linker to do any dead-stripping of symbols
+            # in this file, because it will mess up info-tables in mangled
+            # code.
+
        # NB: all the rest start with a non-space
 
        } elsif ( $TargetPlatform =~ /^mips-/
index b835a49..dc29597 100644 (file)
@@ -534,6 +534,11 @@ extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg);
 #ifdef darwin_TARGET_OS
 static void StgRunIsImplementedInAssembler(void)
 {
+#if HAVE_SUBSECTIONS_VIA_SYMBOLS
+            // if the toolchain supports deadstripping, we have to
+            // prevent it here (it tends to get confused here).
+        __asm__ volatile (".no_dead_strip _StgRunIsImplementedInAssembler");
+#endif
        __asm__ volatile (
                "\n.globl _StgRun\n"
                "_StgRun:\n"