[lld] r310617 - Garbage-collect common symbols.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 10 08:54:27 PDT 2017


Author: ruiu
Date: Thu Aug 10 08:54:27 2017
New Revision: 310617

URL: http://llvm.org/viewvc/llvm-project?rev=310617&view=rev
Log:
Garbage-collect common symbols.

Liveness is usually a notion of input sections, but this patch adds
"liveness" bit to common symbols because they don't belong to any
input section.

This patch is based on https://reviews.llvm.org/D36520

Differential Revision: https://reviews.llvm.org/D36546

Added:
    lld/trunk/test/ELF/common-gc.s
    lld/trunk/test/ELF/common-gc2.s
Modified:
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=310617&r1=310616&r2=310617&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Thu Aug 10 08:54:27 2017
@@ -72,6 +72,12 @@ template <class ELFT, class RelT>
 static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
                          std::function<void(ResolvedReloc)> Fn) {
   SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
+
+  if (auto *Sym = dyn_cast<DefinedCommon>(&B)) {
+    Sym->Live = true;
+    return;
+  }
+
   if (auto *D = dyn_cast<DefinedRegular>(&B)) {
     if (!D->Section)
       return;
@@ -79,10 +85,12 @@ static void resolveReloc(InputSectionBas
     if (D->isSection())
       Offset += getAddend<ELFT>(Sec, Rel);
     Fn({cast<InputSectionBase>(D->Section), Offset});
-  } else if (auto *U = dyn_cast<Undefined>(&B)) {
+    return;
+  }
+
+  if (auto *U = dyn_cast<Undefined>(&B))
     for (InputSectionBase *Sec : CNamedSections.lookup(U->getName()))
       Fn({Sec, 0});
-  }
 }
 
 // Calls Fn for each section that Sec refers to via relocations.
@@ -218,10 +226,14 @@ template <class ELFT> void elf::markLive
       Q.push_back(S);
   };
 
-  auto MarkSymbol = [&](const SymbolBody *Sym) {
-    if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym))
+  auto MarkSymbol = [&](SymbolBody *Sym) {
+    if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) {
       if (auto *IS = cast_or_null<InputSectionBase>(D->Section))
         Enqueue({IS, D->Value});
+      return;
+    }
+    if (auto *S = dyn_cast_or_null<DefinedCommon>(Sym))
+      S->Live = true;
   };
 
   // Add GC root symbols.
@@ -235,7 +247,7 @@ template <class ELFT> void elf::markLive
 
   // Preserve externally-visible symbols if the symbols defined by this
   // file can interrupt other ELF file's symbols at runtime.
-  for (const Symbol *S : Symtab->getSymbols())
+  for (Symbol *S : Symtab->getSymbols())
     if (S->includeInDynsym())
       MarkSymbol(S->body());
 

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=310617&r1=310616&r2=310617&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Aug 10 08:54:27 2017
@@ -273,7 +273,7 @@ DefinedCommon::DefinedCommon(StringRef N
                              uint8_t StOther, uint8_t Type)
     : Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther,
               Type),
-      Alignment(Alignment), Size(Size) {}
+      Live(!Config->GcSections), Alignment(Alignment), Size(Size) {}
 
 // If a shared symbol is referred via a copy relocation, its alignment
 // becomes part of the ABI. This function returns a symbol alignment.

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=310617&r1=310616&r2=310617&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu Aug 10 08:54:27 2017
@@ -161,13 +161,17 @@ public:
     return S->kind() == SymbolBody::DefinedCommonKind;
   }
 
-  // The output offset of this common symbol in the output bss. Computed by the
-  // writer.
-  uint64_t Offset;
+  // True if this symbol is not GC'ed. Liveness is usually a notion of
+  // input sections and not of symbols, but since common symbols don't
+  // belong to any input section, their liveness is managed by this bit.
+  bool Live;
 
   // The maximum alignment we have seen for this symbol.
   uint32_t Alignment;
 
+  // The output offset of this common symbol in the output bss.
+  // Computed by the writer.
+  uint64_t Offset;
   uint64_t Size;
 };
 

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=310617&r1=310616&r2=310617&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Aug 10 08:54:27 2017
@@ -77,9 +77,11 @@ template <class ELFT> InputSection *elf:
                      return A->Alignment > B->Alignment;
                    });
 
+  // Allocate space for common symbols.
   BssSection *Sec = make<BssSection>("COMMON");
   for (DefinedCommon *Sym : Syms)
-    Sym->Offset = Sec->reserveSpace(Sym->Size, Sym->Alignment);
+    if (Sym->Live)
+      Sym->Offset = Sec->reserveSpace(Sym->Size, Sym->Alignment);
   return Sec;
 }
 

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=310617&r1=310616&r2=310617&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Aug 10 08:54:27 2017
@@ -451,7 +451,11 @@ static bool includeInSymtab(const Symbol
     if (auto *S = dyn_cast<MergeInputSection>(Sec))
       if (!S->getSectionPiece(D->Value)->Live)
         return false;
+    return true;
   }
+
+  if (auto *Sym = dyn_cast<DefinedCommon>(&B))
+    return Sym->Live;
   return true;
 }
 

Added: lld/trunk/test/ELF/common-gc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/common-gc.s?rev=310617&view=auto
==============================================================================
--- lld/trunk/test/ELF/common-gc.s (added)
+++ lld/trunk/test/ELF/common-gc.s Thu Aug 10 08:54:27 2017
@@ -0,0 +1,41 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck %s --check-prefix=NOGC
+
+# NOGC:      Name: .bss
+# NOGC-NEXT: Type:
+# NOGC-NEXT: Flags [
+# NOGC-NEXT:   SHF_ALLOC
+# NOGC-NEXT:   SHF_WRITE
+# NOGC-NEXT: ]
+# NOGC-NEXT: Address:
+# NOGC-NEXT: Offset:
+# NOGC-NEXT: Size: 8
+
+# NOGC: Name: bar
+# NOGC: Name: foo
+
+# RUN: ld.lld -gc-sections %t -o %t1
+# RUN: llvm-readobj -sections -symbols %t1 | FileCheck %s --check-prefix=GC
+
+# GC:      Name: .bss
+# GC-NEXT: Type:
+# GC-NEXT: Flags [
+# GC-NEXT:   SHF_ALLOC
+# GC-NEXT:   SHF_WRITE
+# GC-NEXT: ]
+# GC-NEXT: Address:
+# GC-NEXT: Offset:
+# GC-NEXT: Size: 4
+
+# GC-NOT: Name: bar
+
+.comm foo,4,4
+.comm bar,4,4
+
+.text
+.globl _start
+_start:
+ .quad foo

Added: lld/trunk/test/ELF/common-gc2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/common-gc2.s?rev=310617&view=auto
==============================================================================
--- lld/trunk/test/ELF/common-gc2.s (added)
+++ lld/trunk/test/ELF/common-gc2.s Thu Aug 10 08:54:27 2017
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+# RUN: ld.lld -gc-sections -export-dynamic %t -o %t1
+# RUN: llvm-readobj --dyn-symbols %t1 | FileCheck %s
+
+# CHECK: Name: bar@
+# CHECK: Name: foo@
+
+.comm foo,4,4
+.comm bar,4,4
+
+.text
+.globl _start
+_start:
+ .quad foo




More information about the llvm-commits mailing list