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
}

0 commit comments

Comments
 (0)