[lld] r323842 - [WebAssembly] Add support for --gc-sections

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 30 17:45:47 PST 2018


Author: sbc
Date: Tue Jan 30 17:45:47 2018
New Revision: 323842

URL: http://llvm.org/viewvc/llvm-project?rev=323842&view=rev
Log:
[WebAssembly] Add support for --gc-sections

In this initial version we only GC symbols with `hidden` visibility since
other symbols we export to the embedder.

We could potentially modify this the future and only use symbols
explicitly passed via `--export` as GC roots.

This version of the code only does GC of data and code. GC for the
types section is coming soon.

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

Added:
    lld/trunk/test/wasm/gc-sections.ll
    lld/trunk/wasm/MarkLive.cpp   (with props)
    lld/trunk/wasm/MarkLive.h   (with props)
Modified:
    lld/trunk/test/wasm/call-indirect.ll
    lld/trunk/test/wasm/comdats.ll
    lld/trunk/test/wasm/data-layout.ll
    lld/trunk/test/wasm/entry.ll
    lld/trunk/test/wasm/local-symbols.ll
    lld/trunk/test/wasm/weak-symbols.ll
    lld/trunk/wasm/CMakeLists.txt
    lld/trunk/wasm/Config.h
    lld/trunk/wasm/Driver.cpp
    lld/trunk/wasm/InputChunks.h
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/InputFiles.h
    lld/trunk/wasm/Options.td
    lld/trunk/wasm/Writer.cpp

Modified: lld/trunk/test/wasm/call-indirect.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/call-indirect.ll?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/test/wasm/call-indirect.ll (original)
+++ lld/trunk/test/wasm/call-indirect.ll Tue Jan 30 17:45:47 2018
@@ -1,6 +1,6 @@
 ; RUN: llc -filetype=obj %p/Inputs/call-indirect.ll -o %t2.o
 ; RUN: llc -filetype=obj %s -o %t.o
-; RUN: lld -flavor wasm -o %t.wasm %t2.o %t.o
+; RUN: lld -flavor wasm -no-gc-sections -o %t.wasm %t2.o %t.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
 ; bitcode generated from the following C code:

Modified: lld/trunk/test/wasm/comdats.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/comdats.ll?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/test/wasm/comdats.ll (original)
+++ lld/trunk/test/wasm/comdats.ll Tue Jan 30 17:45:47 2018
@@ -1,7 +1,7 @@
 ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat1.ll -o %t1.o
 ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat2.ll -o %t2.o
 ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %s -o %t.o
-; RUN: lld -flavor wasm -o %t.wasm %t.o %t1.o %t2.o
+; RUN: lld -flavor wasm -no-gc-sections -o %t.wasm %t.o %t1.o %t2.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
 target triple = "wasm32-unknown-unknown-wasm"

Modified: lld/trunk/test/wasm/data-layout.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/data-layout.ll?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/test/wasm/data-layout.ll (original)
+++ lld/trunk/test/wasm/data-layout.ll Tue Jan 30 17:45:47 2018
@@ -9,7 +9,7 @@ target triple = "wasm32-unknown-unknown-
 @hello_str = external global i8*
 @external_ref = global i8** @hello_str, align 8
 
-; RUN: lld -flavor wasm --allow-undefined -o %t.wasm %t.o %t.hello.o
+; RUN: lld -flavor wasm -no-gc-sections --allow-undefined -o %t.wasm %t.o %t.hello.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
 ; CHECK:        - Type:            GLOBAL

Modified: lld/trunk/test/wasm/entry.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/entry.ll?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/test/wasm/entry.ll (original)
+++ lld/trunk/test/wasm/entry.ll Tue Jan 30 17:45:47 2018
@@ -33,4 +33,4 @@ entry:
 ; CHECK-CTOR-NEXT:         Index:           0
 ; CHECK-CTOR-NEXT:       - Name:            __wasm_call_ctors
 ; CHECK-CTOR-NEXT:         Kind:            FUNCTION
-; CHECK-CTOR-NEXT:         Index:           1
+; CHECK-CTOR-NEXT:         Index:           0

Added: lld/trunk/test/wasm/gc-sections.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/gc-sections.ll?rev=323842&view=auto
==============================================================================
--- lld/trunk/test/wasm/gc-sections.ll (added)
+++ lld/trunk/test/wasm/gc-sections.ll Tue Jan 30 17:45:47 2018
@@ -0,0 +1,79 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -print-gc-sections -o %t1.wasm %t.o | FileCheck %s -check-prefix=PRINT-GC
+; PRINT-GC: removing unused section 'unused_function' in file '{{.*}}'
+; PRINT-GC-NOT: removing unused section 'used_function' in file '{{.*}}'
+; PRINT-GC: removing unused section '.data.unused_data' in file '{{.*}}'
+; PRINT-GC-NOT: removing unused section '.data.used_data' in file '{{.*}}'
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+ at unused_data = hidden global i32 1, align 4
+ at used_data = hidden global i32 2, align 4
+
+define hidden i32 @unused_function() {
+  %1 = load i32, i32* @unused_data, align 4
+  ret i32 %1
+}
+
+define hidden i32 @used_function() {
+  %1 = load i32, i32* @used_data, align 4
+  ret i32 %1
+}
+
+define hidden void @_start() {
+entry:
+  call i32 @used_function()
+  ret void
+}
+
+; RUN: obj2yaml %t1.wasm | FileCheck %s
+; CHECK:        - Type:            DATA
+; CHECK-NEXT:     Segments:        
+; CHECK-NEXT:       - SectionOffset:   7
+; CHECK-NEXT:         MemoryIndex:     0
+; CHECK-NEXT:         Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           1024
+; CHECK-NEXT:         Content:         '02000000'
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            linking
+; CHECK-NEXT:     DataSize:        4
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            name
+; CHECK-NEXT:     FunctionNames:   
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Name:            used_function
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT: ...
+
+; RUN: lld -flavor wasm -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm %t.o
+; RUN: obj2yaml %t1.no-gc.wasm | FileCheck %s -check-prefix=NO-GC
+; NO-GC:        - Type:            DATA
+; NO-GC-NEXT:     Segments:        
+; NO-GC-NEXT:       - SectionOffset:   7
+; NO-GC-NEXT:         MemoryIndex:     0
+; NO-GC-NEXT:         Offset:          
+; NO-GC-NEXT:           Opcode:          I32_CONST
+; NO-GC-NEXT:           Value:           1024
+; NO-GC-NEXT:         Content:         '0100000002000000'
+; NO-GC-NEXT:   - Type:            CUSTOM
+; NO-GC-NEXT:     Name:            linking
+; NO-GC-NEXT:     DataSize:        8
+; NO-GC-NEXT:   - Type:            CUSTOM
+; NO-GC-NEXT:     Name:            name
+; NO-GC-NEXT:     FunctionNames:   
+; NO-GC-NEXT:       - Index:           0
+; NO-GC-NEXT:         Name:            unused_function
+; NO-GC-NEXT:       - Index:           1
+; NO-GC-NEXT:         Name:            used_function
+; NO-GC-NEXT:       - Index:           2
+; NO-GC-NEXT:         Name:            _start
+; NO-GC-NEXT:       - Index:           3
+; NO-GC-NEXT:         Name:            __wasm_call_ctors
+; NO-GC-NEXT: ...
+
+; RUN: not lld -flavor wasm --gc-sections --relocatable -o %t1.no-gc.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR
+; CHECK-ERROR: lld: error: -r and --gc-sections may not be used together

Modified: lld/trunk/test/wasm/local-symbols.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/local-symbols.ll?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/test/wasm/local-symbols.ll (original)
+++ lld/trunk/test/wasm/local-symbols.ll Tue Jan 30 17:45:47 2018
@@ -9,11 +9,13 @@ target triple = "wasm32-unknown-unknown-
 
 define internal i32 @baz() local_unnamed_addr {
 entry:
-  ret i32 2
+  %0 = load i32, i32* @bar, align 4
+  ret i32 %0
 }
 
 define i32 @_start() local_unnamed_addr {
 entry:
+  call i32 @baz()
   ret i32 1
 }
 
@@ -70,10 +72,10 @@ entry:
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:         Body:            4100280284888080000B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41010B
+; CHECK-NEXT:         Body:            1080808080001A41010B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:         Body:            0B

Modified: lld/trunk/test/wasm/weak-symbols.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/weak-symbols.ll?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/test/wasm/weak-symbols.ll (original)
+++ lld/trunk/test/wasm/weak-symbols.ll Tue Jan 30 17:45:47 2018
@@ -1,7 +1,7 @@
 ; RUN: llc -filetype=obj %p/Inputs/weak-symbol1.ll -o %t1.o
 ; RUN: llc -filetype=obj %p/Inputs/weak-symbol2.ll -o %t2.o
 ; RUN: llc -filetype=obj %s -o %t.o
-; RUN: lld -flavor wasm -o %t.wasm %t.o %t1.o %t2.o
+; RUN: lld -flavor wasm -no-gc-sections -o %t.wasm %t.o %t1.o %t2.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
 target triple = "wasm32-unknown-unknown-wasm"

Modified: lld/trunk/wasm/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/CMakeLists.txt?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/CMakeLists.txt (original)
+++ lld/trunk/wasm/CMakeLists.txt Tue Jan 30 17:45:47 2018
@@ -6,6 +6,7 @@ add_lld_library(lldWasm
   Driver.cpp
   InputChunks.cpp
   InputFiles.cpp
+  MarkLive.cpp
   OutputSections.cpp
   SymbolTable.cpp
   Symbols.cpp

Modified: lld/trunk/wasm/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Config.h?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/Config.h (original)
+++ lld/trunk/wasm/Config.h Tue Jan 30 17:45:47 2018
@@ -23,7 +23,9 @@ struct Configuration {
   bool AllowUndefined;
   bool CheckSignatures;
   bool Demangle;
+  bool GcSections;
   bool ImportMemory;
+  bool PrintGcSections;
   bool Relocatable;
   bool StripAll;
   bool StripDebug;

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Tue Jan 30 17:45:47 2018
@@ -8,7 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Common/Driver.h"
-#include "Config.h"
+#include "InputChunks.h"
+#include "MarkLive.h"
 #include "SymbolTable.h"
 #include "Writer.h"
 #include "lld/Common/Args.h"
@@ -23,6 +24,8 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 
+#define DEBUG_TYPE "lld"
+
 using namespace llvm;
 using namespace llvm::sys;
 using namespace llvm::wasm;
@@ -253,6 +256,10 @@ void LinkerDriver::link(ArrayRef<const c
   Config->ImportMemory = Args.hasArg(OPT_import_memory);
   Config->OutputFile = Args.getLastArgValue(OPT_o);
   Config->Relocatable = Args.hasArg(OPT_relocatable);
+  Config->GcSections =
+      Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable);
+  Config->PrintGcSections =
+      Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
   Config->SearchPaths = args::getStrings(Args, OPT_L);
   Config->StripAll = Args.hasArg(OPT_strip_all);
   Config->StripDebug = Args.hasArg(OPT_strip_debug);
@@ -274,10 +281,14 @@ void LinkerDriver::link(ArrayRef<const c
   if (!Args.hasArg(OPT_INPUT))
     error("no input files");
 
-  if (Config->Relocatable && !Config->Entry.empty())
-    error("entry point specified for relocatable output file");
-  if (Config->Relocatable && Args.hasArg(OPT_undefined))
-    error("undefined symbols specified for relocatable output file");
+  if (Config->Relocatable) {
+    if (!Config->Entry.empty())
+      error("entry point specified for relocatable output file");
+    if (Config->GcSections)
+      error("-r and --gc-sections may not be used together");
+    if (Args.hasArg(OPT_undefined))
+      error("-r -and --undefined may not be used together");
+  }
 
   Symbol *EntrySym = nullptr;
   if (!Config->Relocatable) {
@@ -345,6 +356,9 @@ void LinkerDriver::link(ArrayRef<const c
   if (errorCount())
     return;
 
+  // Do size optimizations: garbage collection
+  markLive();
+
   // Write the result to the file.
   writeResult();
 }

Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Tue Jan 30 17:45:47 2018
@@ -15,6 +15,7 @@
 #ifndef LLD_WASM_INPUT_CHUNKS_H
 #define LLD_WASM_INPUT_CHUNKS_H
 
+#include "Config.h"
 #include "InputFiles.h"
 #include "WriterUtils.h"
 #include "lld/Common/ErrorHandler.h"
@@ -58,9 +59,15 @@ public:
 
   bool Discarded = false;
   std::vector<OutputRelocation> OutRelocations;
+  const ObjFile *File;
+
+  // The garbage collector sets sections' Live bits.
+  // If GC is disabled, all sections are considered live by default.
+  unsigned Live : 1;
 
 protected:
-  InputChunk(const ObjFile *F, Kind K) : File(F), SectionKind(K) {}
+  InputChunk(const ObjFile *F, Kind K)
+      : File(F), Live(!Config->GcSections), SectionKind(K) {}
   virtual ~InputChunk() = default;
   void calcRelocations();
   virtual ArrayRef<uint8_t> data() const = 0;
@@ -68,7 +75,6 @@ protected:
 
   std::vector<WasmRelocation> Relocations;
   int32_t OutputOffset = 0;
-  const ObjFile *File;
   Kind SectionKind;
 };
 

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Tue Jan 30 17:45:47 2018
@@ -51,11 +51,11 @@ void ObjFile::dumpInfo() const {
 }
 
 uint32_t ObjFile::relocateVirtualAddress(uint32_t GlobalIndex) const {
-  return GlobalSymbols[GlobalIndex]->getVirtualAddress();
+  return getGlobalSymbol(GlobalIndex)->getVirtualAddress();
 }
 
 uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
-  Symbol *Sym = FunctionSymbols[Original];
+  const Symbol *Sym = getFunctionSymbol(Original);
   uint32_t Index = Sym->getOutputIndex();
   DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
                << Original << " -> " << Index << "\n");
@@ -67,7 +67,7 @@ uint32_t ObjFile::relocateTypeIndex(uint
 }
 
 uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
-  Symbol *Sym = FunctionSymbols[Original];
+  const Symbol *Sym = getFunctionSymbol(Original);
   uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
   DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
                << " -> " << Index << "\n");
@@ -75,7 +75,7 @@ uint32_t ObjFile::relocateTableIndex(uin
 }
 
 uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
-  Symbol *Sym = GlobalSymbols[Original];
+  const Symbol *Sym = getGlobalSymbol(Original);
   uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0;
   DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
                << " -> " << Index << "\n");

Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Tue Jan 30 17:45:47 2018
@@ -110,6 +110,8 @@ public:
     return FunctionSymbols[Index];
   }
 
+  Symbol *getGlobalSymbol(uint32_t Index) const { return GlobalSymbols[Index]; }
+
 private:
   uint32_t relocateVirtualAddress(uint32_t Index) const;
   uint32_t relocateTypeIndex(uint32_t Original) const;

Added: lld/trunk/wasm/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/MarkLive.cpp?rev=323842&view=auto
==============================================================================
--- lld/trunk/wasm/MarkLive.cpp (added)
+++ lld/trunk/wasm/MarkLive.cpp Tue Jan 30 17:45:47 2018
@@ -0,0 +1,107 @@
+//===- MarkLive.cpp -------------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements --gc-sections, which is a feature to remove unused
+// chunks from the output. Unused chunks are those that are not reachable from
+// known root symbols or chunks. This feature is implemented as a mark-sweep
+// garbage collector.
+//
+// Here's how it works. Each InputChunk has a "Live" bit. The bit is off by
+// default. Starting with the GC-roots, visit all reachable chunks and set their
+// Live bits. The Writer will then ignore chunks whose Live bits are off, so
+// that such chunk are not appear in the output.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MarkLive.h"
+#include "Config.h"
+#include "InputChunks.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
+
+#define DEBUG_TYPE "lld"
+
+using namespace llvm;
+using namespace llvm::wasm;
+using namespace lld;
+using namespace lld::wasm;
+
+void lld::wasm::markLive() {
+  if (!Config->GcSections)
+    return;
+
+  DEBUG(dbgs() << "markLive\n");
+  SmallVector<InputChunk *, 256> Q;
+
+  auto Enqueue = [&](Symbol *Sym) {
+    if (!Sym)
+      return;
+    InputChunk *Chunk = Sym->getChunk();
+    if (!Chunk || Chunk->Live)
+      return;
+    Chunk->Live = true;
+    Q.push_back(Chunk);
+  };
+
+  // Add GC root symbols.
+  if (!Config->Entry.empty())
+    Enqueue(Symtab->find(Config->Entry));
+  Enqueue(Config->CtorSymbol);
+
+  // By default we export all non-hidden, so they are gc roots too
+  for (Symbol *Sym : Symtab->getSymbols())
+    if (!Sym->isHidden())
+      Enqueue(Sym);
+
+  // The ctor fuctions are all used the synthetic __wasm_call_ctors function,
+  // but since this function is created in-place it doesn't contain reloctations
+  // which mean we have to manually mark the ctors.
+  for (const ObjFile *Obj : Symtab->ObjectFiles) {
+    const WasmLinkingData &L = Obj->getWasmObj()->linkingData();
+    for (const WasmInitFunc &F : L.InitFunctions)
+      Enqueue(Obj->getFunctionSymbol(F.FunctionIndex));
+  }
+
+  auto EnqueueSuccessors = [Enqueue](InputChunk &Chunk) {
+    for (const WasmRelocation Reloc : Chunk.getRelocations()) {
+      switch (Reloc.Type) {
+      case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+      case R_WEBASSEMBLY_TABLE_INDEX_I32:
+      case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+        Enqueue(Chunk.File->getFunctionSymbol(Reloc.Index));
+        break;
+      case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+      case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+      case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+      case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+        Enqueue(Chunk.File->getGlobalSymbol(Reloc.Index));
+        break;
+      }
+    }
+  };
+
+  while (!Q.empty())
+    EnqueueSuccessors(*Q.pop_back_val());
+
+  // Report garbage-collected sections.
+  if (Config->PrintGcSections) {
+    auto CheckChunk = [](const InputChunk *C) {
+      if (!C->Live)
+        message("removing unused section '" + C->getName() + "' in file '" +
+                C->getFileName() + "'");
+    };
+
+    for (const ObjFile *Obj : Symtab->ObjectFiles) {
+      for (InputChunk *C : Obj->Functions)
+        CheckChunk(C);
+      for (InputChunk *C : Obj->Segments)
+        CheckChunk(C);
+    }
+  }
+}

Propchange: lld/trunk/wasm/MarkLive.cpp
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: lld/trunk/wasm/MarkLive.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/MarkLive.h?rev=323842&view=auto
==============================================================================
--- lld/trunk/wasm/MarkLive.h (added)
+++ lld/trunk/wasm/MarkLive.h Tue Jan 30 17:45:47 2018
@@ -0,0 +1,20 @@
+//===- MarkLive.h -----------------------------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_WASM_MARKLIVE_H
+#define LLD_WASM_MARKLIVE_H
+
+namespace lld {
+namespace wasm {
+
+void markLive();
+}
+} // namespace lld
+
+#endif // LLD_WASM_MARKLIVE_H

Propchange: lld/trunk/wasm/MarkLive.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: lld/trunk/wasm/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Options.td?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/Options.td (original)
+++ lld/trunk/wasm/Options.td Tue Jan 30 17:45:47 2018
@@ -27,6 +27,9 @@ def error_limit: J<"error-limit=">,
 def fatal_warnings: F<"fatal-warnings">,
   HelpText<"Treat warnings as errors">;
 
+def gc_sections: F<"gc-sections">,
+  HelpText<"Enable garbage collection of unused sections">;
+
 def help: F<"help">, HelpText<"Print option help">;
 
 def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
@@ -45,9 +48,18 @@ def no_color_diagnostics: F<"no-color-di
 
 def no_fatal_warnings: F<"no-fatal-warnings">;
 
+def no_gc_sections: F<"no-gc-sections">,
+  HelpText<"Disable garbage collection of unused sections">;
+
+def no_print_gc_sections: F<"no-print-gc-sections">,
+  HelpText<"Do not list removed unused sections">;
+
 def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
   HelpText<"Path to file to write output">;
 
+def print_gc_sections: F<"print-gc-sections">,
+  HelpText<"List removed unused sections">;
+
 def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;
 
 def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=323842&r1=323841&r2=323842&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Tue Jan 30 17:45:47 2018
@@ -653,6 +653,9 @@ void Writer::calculateExports() {
 
       if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden)
         continue;
+
+      // We should never be exporting a non-live symbol
+      assert(Sym->getChunk()->Live);
       ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)});
     }
   }
@@ -735,7 +738,7 @@ void Writer::assignIndexes() {
   for (ObjFile *File : Symtab->ObjectFiles) {
     DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
     for (InputFunction *Func : File->Functions) {
-      if (Func->Discarded)
+      if (Func->Discarded || !Func->Live)
         continue;
       DefinedFunctions.emplace_back(Func);
       Func->setOutputIndex(FunctionIndex++);
@@ -784,7 +787,7 @@ static StringRef getOutputDataSegmentNam
 void Writer::createOutputSegments() {
   for (ObjFile *File : Symtab->ObjectFiles) {
     for (InputSegment *Segment : File->Segments) {
-      if (Segment->Discarded)
+      if (Segment->Discarded || !Segment->Live)
         continue;
       StringRef Name = getOutputDataSegmentName(Segment->getName());
       OutputSegment *&S = SegmentMap[Name];




More information about the llvm-commits mailing list