Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit c69119a

Browse files
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@323842 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 0e10ed2 commit c69119a

17 files changed

+269
-21
lines changed

test/wasm/call-indirect.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; RUN: llc -filetype=obj %p/Inputs/call-indirect.ll -o %t2.o
22
; RUN: llc -filetype=obj %s -o %t.o
3-
; RUN: lld -flavor wasm -o %t.wasm %t2.o %t.o
3+
; RUN: lld -flavor wasm -no-gc-sections -o %t.wasm %t2.o %t.o
44
; RUN: obj2yaml %t.wasm | FileCheck %s
55

66
; bitcode generated from the following C code:

test/wasm/comdats.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat1.ll -o %t1.o
22
; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat2.ll -o %t2.o
33
; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %s -o %t.o
4-
; RUN: lld -flavor wasm -o %t.wasm %t.o %t1.o %t2.o
4+
; RUN: lld -flavor wasm -no-gc-sections -o %t.wasm %t.o %t1.o %t2.o
55
; RUN: obj2yaml %t.wasm | FileCheck %s
66

77
target triple = "wasm32-unknown-unknown-wasm"

test/wasm/data-layout.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ target triple = "wasm32-unknown-unknown-wasm"
99
@hello_str = external global i8*
1010
@external_ref = global i8** @hello_str, align 8
1111

12-
; RUN: lld -flavor wasm --allow-undefined -o %t.wasm %t.o %t.hello.o
12+
; RUN: lld -flavor wasm -no-gc-sections --allow-undefined -o %t.wasm %t.o %t.hello.o
1313
; RUN: obj2yaml %t.wasm | FileCheck %s
1414

1515
; CHECK: - Type: GLOBAL

test/wasm/entry.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ entry:
3333
; CHECK-CTOR-NEXT: Index: 0
3434
; CHECK-CTOR-NEXT: - Name: __wasm_call_ctors
3535
; CHECK-CTOR-NEXT: Kind: FUNCTION
36-
; CHECK-CTOR-NEXT: Index: 1
36+
; CHECK-CTOR-NEXT: Index: 0

test/wasm/gc-sections.ll

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
; RUN: llc -filetype=obj %s -o %t.o
2+
; RUN: lld -flavor wasm -print-gc-sections -o %t1.wasm %t.o | FileCheck %s -check-prefix=PRINT-GC
3+
; PRINT-GC: removing unused section 'unused_function' in file '{{.*}}'
4+
; PRINT-GC-NOT: removing unused section 'used_function' in file '{{.*}}'
5+
; PRINT-GC: removing unused section '.data.unused_data' in file '{{.*}}'
6+
; PRINT-GC-NOT: removing unused section '.data.used_data' in file '{{.*}}'
7+
8+
target triple = "wasm32-unknown-unknown-wasm"
9+
10+
@unused_data = hidden global i32 1, align 4
11+
@used_data = hidden global i32 2, align 4
12+
13+
define hidden i32 @unused_function() {
14+
%1 = load i32, i32* @unused_data, align 4
15+
ret i32 %1
16+
}
17+
18+
define hidden i32 @used_function() {
19+
%1 = load i32, i32* @used_data, align 4
20+
ret i32 %1
21+
}
22+
23+
define hidden void @_start() {
24+
entry:
25+
call i32 @used_function()
26+
ret void
27+
}
28+
29+
; RUN: obj2yaml %t1.wasm | FileCheck %s
30+
; CHECK: - Type: DATA
31+
; CHECK-NEXT: Segments:
32+
; CHECK-NEXT: - SectionOffset: 7
33+
; CHECK-NEXT: MemoryIndex: 0
34+
; CHECK-NEXT: Offset:
35+
; CHECK-NEXT: Opcode: I32_CONST
36+
; CHECK-NEXT: Value: 1024
37+
; CHECK-NEXT: Content: '02000000'
38+
; CHECK-NEXT: - Type: CUSTOM
39+
; CHECK-NEXT: Name: linking
40+
; CHECK-NEXT: DataSize: 4
41+
; CHECK-NEXT: - Type: CUSTOM
42+
; CHECK-NEXT: Name: name
43+
; CHECK-NEXT: FunctionNames:
44+
; CHECK-NEXT: - Index: 0
45+
; CHECK-NEXT: Name: used_function
46+
; CHECK-NEXT: - Index: 1
47+
; CHECK-NEXT: Name: _start
48+
; CHECK-NEXT: - Index: 2
49+
; CHECK-NEXT: Name: __wasm_call_ctors
50+
; CHECK-NEXT: ...
51+
52+
; RUN: lld -flavor wasm -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm %t.o
53+
; RUN: obj2yaml %t1.no-gc.wasm | FileCheck %s -check-prefix=NO-GC
54+
; NO-GC: - Type: DATA
55+
; NO-GC-NEXT: Segments:
56+
; NO-GC-NEXT: - SectionOffset: 7
57+
; NO-GC-NEXT: MemoryIndex: 0
58+
; NO-GC-NEXT: Offset:
59+
; NO-GC-NEXT: Opcode: I32_CONST
60+
; NO-GC-NEXT: Value: 1024
61+
; NO-GC-NEXT: Content: '0100000002000000'
62+
; NO-GC-NEXT: - Type: CUSTOM
63+
; NO-GC-NEXT: Name: linking
64+
; NO-GC-NEXT: DataSize: 8
65+
; NO-GC-NEXT: - Type: CUSTOM
66+
; NO-GC-NEXT: Name: name
67+
; NO-GC-NEXT: FunctionNames:
68+
; NO-GC-NEXT: - Index: 0
69+
; NO-GC-NEXT: Name: unused_function
70+
; NO-GC-NEXT: - Index: 1
71+
; NO-GC-NEXT: Name: used_function
72+
; NO-GC-NEXT: - Index: 2
73+
; NO-GC-NEXT: Name: _start
74+
; NO-GC-NEXT: - Index: 3
75+
; NO-GC-NEXT: Name: __wasm_call_ctors
76+
; NO-GC-NEXT: ...
77+
78+
; RUN: not lld -flavor wasm --gc-sections --relocatable -o %t1.no-gc.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR
79+
; CHECK-ERROR: lld: error: -r and --gc-sections may not be used together

test/wasm/local-symbols.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ target triple = "wasm32-unknown-unknown-wasm"
99

1010
define internal i32 @baz() local_unnamed_addr {
1111
entry:
12-
ret i32 2
12+
%0 = load i32, i32* @bar, align 4
13+
ret i32 %0
1314
}
1415

1516
define i32 @_start() local_unnamed_addr {
1617
entry:
18+
call i32 @baz()
1719
ret i32 1
1820
}
1921

@@ -70,10 +72,10 @@ entry:
7072
; CHECK-NEXT: Functions:
7173
; CHECK-NEXT: - Index: 0
7274
; CHECK-NEXT: Locals:
73-
; CHECK-NEXT: Body: 41020B
75+
; CHECK-NEXT: Body: 4100280284888080000B
7476
; CHECK-NEXT: - Index: 1
7577
; CHECK-NEXT: Locals:
76-
; CHECK-NEXT: Body: 41010B
78+
; CHECK-NEXT: Body: 1080808080001A41010B
7779
; CHECK-NEXT: - Index: 2
7880
; CHECK-NEXT: Locals:
7981
; CHECK-NEXT: Body: 0B

test/wasm/weak-symbols.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; RUN: llc -filetype=obj %p/Inputs/weak-symbol1.ll -o %t1.o
22
; RUN: llc -filetype=obj %p/Inputs/weak-symbol2.ll -o %t2.o
33
; RUN: llc -filetype=obj %s -o %t.o
4-
; RUN: lld -flavor wasm -o %t.wasm %t.o %t1.o %t2.o
4+
; RUN: lld -flavor wasm -no-gc-sections -o %t.wasm %t.o %t1.o %t2.o
55
; RUN: obj2yaml %t.wasm | FileCheck %s
66

77
target triple = "wasm32-unknown-unknown-wasm"

wasm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_lld_library(lldWasm
66
Driver.cpp
77
InputChunks.cpp
88
InputFiles.cpp
9+
MarkLive.cpp
910
OutputSections.cpp
1011
SymbolTable.cpp
1112
Symbols.cpp

wasm/Config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ struct Configuration {
2323
bool AllowUndefined;
2424
bool CheckSignatures;
2525
bool Demangle;
26+
bool GcSections;
2627
bool ImportMemory;
28+
bool PrintGcSections;
2729
bool Relocatable;
2830
bool StripAll;
2931
bool StripDebug;

wasm/Driver.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
//===----------------------------------------------------------------------===//
99

1010
#include "lld/Common/Driver.h"
11-
#include "Config.h"
11+
#include "InputChunks.h"
12+
#include "MarkLive.h"
1213
#include "SymbolTable.h"
1314
#include "Writer.h"
1415
#include "lld/Common/Args.h"
@@ -23,6 +24,8 @@
2324
#include "llvm/Support/Path.h"
2425
#include "llvm/Support/Process.h"
2526

27+
#define DEBUG_TYPE "lld"
28+
2629
using namespace llvm;
2730
using namespace llvm::sys;
2831
using namespace llvm::wasm;
@@ -253,6 +256,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
253256
Config->ImportMemory = Args.hasArg(OPT_import_memory);
254257
Config->OutputFile = Args.getLastArgValue(OPT_o);
255258
Config->Relocatable = Args.hasArg(OPT_relocatable);
259+
Config->GcSections =
260+
Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable);
261+
Config->PrintGcSections =
262+
Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
256263
Config->SearchPaths = args::getStrings(Args, OPT_L);
257264
Config->StripAll = Args.hasArg(OPT_strip_all);
258265
Config->StripDebug = Args.hasArg(OPT_strip_debug);
@@ -274,10 +281,14 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
274281
if (!Args.hasArg(OPT_INPUT))
275282
error("no input files");
276283

277-
if (Config->Relocatable && !Config->Entry.empty())
278-
error("entry point specified for relocatable output file");
279-
if (Config->Relocatable && Args.hasArg(OPT_undefined))
280-
error("undefined symbols specified for relocatable output file");
284+
if (Config->Relocatable) {
285+
if (!Config->Entry.empty())
286+
error("entry point specified for relocatable output file");
287+
if (Config->GcSections)
288+
error("-r and --gc-sections may not be used together");
289+
if (Args.hasArg(OPT_undefined))
290+
error("-r -and --undefined may not be used together");
291+
}
281292

282293
Symbol *EntrySym = nullptr;
283294
if (!Config->Relocatable) {
@@ -345,6 +356,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
345356
if (errorCount())
346357
return;
347358

359+
// Do size optimizations: garbage collection
360+
markLive();
361+
348362
// Write the result to the file.
349363
writeResult();
350364
}

wasm/InputChunks.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef LLD_WASM_INPUT_CHUNKS_H
1616
#define LLD_WASM_INPUT_CHUNKS_H
1717

18+
#include "Config.h"
1819
#include "InputFiles.h"
1920
#include "WriterUtils.h"
2021
#include "lld/Common/ErrorHandler.h"
@@ -58,17 +59,22 @@ class InputChunk {
5859

5960
bool Discarded = false;
6061
std::vector<OutputRelocation> OutRelocations;
62+
const ObjFile *File;
63+
64+
// The garbage collector sets sections' Live bits.
65+
// If GC is disabled, all sections are considered live by default.
66+
unsigned Live : 1;
6167

6268
protected:
63-
InputChunk(const ObjFile *F, Kind K) : File(F), SectionKind(K) {}
69+
InputChunk(const ObjFile *F, Kind K)
70+
: File(F), Live(!Config->GcSections), SectionKind(K) {}
6471
virtual ~InputChunk() = default;
6572
void calcRelocations();
6673
virtual ArrayRef<uint8_t> data() const = 0;
6774
virtual uint32_t getInputSectionOffset() const = 0;
6875

6976
std::vector<WasmRelocation> Relocations;
7077
int32_t OutputOffset = 0;
71-
const ObjFile *File;
7278
Kind SectionKind;
7379
};
7480

wasm/InputFiles.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ void ObjFile::dumpInfo() const {
5151
}
5252

5353
uint32_t ObjFile::relocateVirtualAddress(uint32_t GlobalIndex) const {
54-
return GlobalSymbols[GlobalIndex]->getVirtualAddress();
54+
return getGlobalSymbol(GlobalIndex)->getVirtualAddress();
5555
}
5656

5757
uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
58-
Symbol *Sym = FunctionSymbols[Original];
58+
const Symbol *Sym = getFunctionSymbol(Original);
5959
uint32_t Index = Sym->getOutputIndex();
6060
DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
6161
<< Original << " -> " << Index << "\n");
@@ -67,15 +67,15 @@ uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
6767
}
6868

6969
uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
70-
Symbol *Sym = FunctionSymbols[Original];
70+
const Symbol *Sym = getFunctionSymbol(Original);
7171
uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
7272
DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
7373
<< " -> " << Index << "\n");
7474
return Index;
7575
}
7676

7777
uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
78-
Symbol *Sym = GlobalSymbols[Original];
78+
const Symbol *Sym = getGlobalSymbol(Original);
7979
uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0;
8080
DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
8181
<< " -> " << Index << "\n");

wasm/InputFiles.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class ObjFile : public InputFile {
110110
return FunctionSymbols[Index];
111111
}
112112

113+
Symbol *getGlobalSymbol(uint32_t Index) const { return GlobalSymbols[Index]; }
114+
113115
private:
114116
uint32_t relocateVirtualAddress(uint32_t Index) const;
115117
uint32_t relocateTypeIndex(uint32_t Original) const;

0 commit comments

Comments
 (0)