Skip to content

Commit a5cd5d3

Browse files
authored
[lld][WebAssembly] Avoid emitting empty __wasm_apply_data_relocs function (#109249)
Instead of always generating __wasm_apply_data_relocs when relevant options like -pie and -shared are specified, generate it only when the relevant relocations are actually necessary. Note: omitting empty __wasm_apply_data_relocs is not a problem because the export is optional in the spec (DynamicLinking.md) and all runtime linker implementations I'm aware of implement it that way. (emscripten, toywasm, wasm-tools) Motivations: * This possibly reduces the module size * This is also a preparation to fix #107387, for which it isn't obvious if we need these relocations at the time of createSyntheticSymbols. (unless we introduce a new explicit option like --non-pie-dynamic-link.)
1 parent 915df1a commit a5cd5d3

File tree

11 files changed

+36
-50
lines changed

11 files changed

+36
-50
lines changed

lld/test/wasm/data-segments.ll

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
; PASSIVE-NEXT: Name: __wasm_init_memory
114114

115115
; PASSIVE-PIC: - Type: START
116-
; PASSIVE-PIC-NEXT: StartFunction: 3
116+
; PASSIVE-PIC-NEXT: StartFunction: 2
117117
; PASSIVE-PIC-NEXT: - Type: DATACOUNT
118118
; PASSIVE-PIC-NEXT: Count: 3
119119
; PASSIVE-PIC-NEXT: - Type: CODE
@@ -125,9 +125,6 @@
125125
; PASSIVE-PIC-NEXT: Locals: []
126126
; PASSIVE-PIC-NEXT: Body: {{.*}}
127127
; PASSIVE-PIC-NEXT: - Index: 2
128-
; PASSIVE-PIC-NEXT: Locals: []
129-
; PASSIVE-PIC-NEXT: Body: 0B
130-
; PASSIVE-PIC-NEXT: - Index: 3
131128
; PASSIVE-PIC-NEXT: Locals:
132129
; PASSIVE32-PIC-NEXT: - Type: I32
133130
; PASSIVE64-PIC-NEXT: - Type: I64
@@ -152,17 +149,13 @@
152149
; PASSIVE-PIC-NEXT: - Index: 1
153150
; PASSIVE-PIC-NEXT: Name: __wasm_init_tls
154151
; PASSIVE-PIC-NEXT: - Index: 2
155-
; PASSIVE-PIC-NEXT: Name: __wasm_apply_data_relocs
156-
; PASSIVE-PIC-NEXT: - Index: 3
157152
; PASSIVE-PIC-NEXT: Name: __wasm_init_memory
158153

159154
; no data relocations.
160155
; DIS-LABEL: <__wasm_call_ctors>:
161156
; DIS-EMPTY:
162157
; DIS-NEXT: end
163158

164-
; In PIC mode __wasm_apply_data_relocs is export separatly to __wasm_call_ctors
165-
; PIC-DIS: <__wasm_apply_data_relocs>:
166159
; PIC-DIS-EMPTY:
167160

168161
; DIS-LABEL: <__wasm_init_memory>:

lld/test/wasm/shared-weak-symbols.s

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ call_weak:
3030
# ASM: 10 80 80 80 80 00 call 0
3131
drop
3232
call hidden_weak_func
33-
# ASM: 10 84 80 80 80 00 call 4
33+
# ASM: 10 83 80 80 80 00 call 3
3434
end_function
3535
# ASM-NEXT: 0b end
3636

@@ -62,15 +62,12 @@ call_weak:
6262
# CHECK-NEXT: - Name: __wasm_call_ctors
6363
# CHECK-NEXT: Kind: FUNCTION
6464
# CHECK-NEXT: Index: 1
65-
# CHECK-NEXT: - Name: __wasm_apply_data_relocs
66-
# CHECK-NEXT: Kind: FUNCTION
67-
# CHECK-NEXT: Index: 2
6865
# CHECK-NEXT: - Name: weak_func
6966
# CHECK-NEXT: Kind: FUNCTION
70-
# CHECK-NEXT: Index: 3
67+
# CHECK-NEXT: Index: 2
7168
# CHECK-NEXT: - Name: call_weak
7269
# CHECK-NEXT: Kind: FUNCTION
73-
# CHECK-NEXT: Index: 5
70+
# CHECK-NEXT: Index: 4
7471
# CHECK-NEXT: - Type: CODE
7572

7673
# CHECK: - Type: CUSTOM
@@ -81,10 +78,8 @@ call_weak:
8178
# CHECK-NEXT: - Index: 1
8279
# CHECK-NEXT: Name: __wasm_call_ctors
8380
# CHECK-NEXT: - Index: 2
84-
# CHECK-NEXT: Name: __wasm_apply_data_relocs
85-
# CHECK-NEXT: - Index: 3
8681
# CHECK-NEXT: Name: weak_func
87-
# CHECK-NEXT: - Index: 4
82+
# CHECK-NEXT: - Index: 3
8883
# CHECK-NEXT: Name: hidden_weak_func
89-
# CHECK-NEXT: - Index: 5
84+
# CHECK-NEXT: - Index: 4
9085
# CHECK-NEXT: Name: call_weak

lld/test/wasm/tls-export.s

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ tls1:
4040
# CHECK-NEXT: - Name: __wasm_call_ctors
4141
# CHECK-NEXT: Kind: FUNCTION
4242
# CHECK-NEXT: Index: 0
43-
# CHECK-NEXT: - Name: __wasm_apply_data_relocs
44-
# CHECK-NEXT: Kind: FUNCTION
45-
# CHECK-NEXT: Index: 1
4643
# CHECK-NEXT: - Name: tls1
4744
# CHECK-NEXT: Kind: GLOBAL
4845
# CHECK-NEXT: Index: 2

lld/test/wasm/tls-non-shared-memory.s

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,6 @@ tls1:
127127
# PIE-NEXT: - Name: memory
128128
# PIE-NEXT: Kind: MEMORY
129129
# PIE-NEXT: Index: 0
130-
# PIE-NEXT: - Name: __wasm_apply_data_relocs
131-
# PIE-NEXT: Kind: FUNCTION
132-
# PIE-NEXT: Index: 1
133130
# PIE-NEXT: - Type:
134131

135132
# .tdata and .data are combined into single segment in PIC mode.

lld/test/wasm/tls-relocations.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ tls_sym:
6666
# ASM-NEXT: i32.const 16
6767
# ASM-NEXT: memory.init 0, 0
6868
# call to __wasm_apply_tls_relocs
69-
# ASM-NEXT: call 4
69+
# ASM-NEXT: call 3
7070
# ASM-NEXT: end
7171

7272
# ASM: <__wasm_apply_tls_relocs>:

lld/wasm/Driver.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -917,17 +917,6 @@ static void createSyntheticSymbols() {
917917
is64 ? i64ArgSignature : i32ArgSignature,
918918
"__wasm_init_tls"));
919919
}
920-
921-
if (ctx.isPic ||
922-
config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic) {
923-
// For PIC code, or when dynamically importing addresses, we create
924-
// synthetic functions that apply relocations. These get called from
925-
// __wasm_call_ctors before the user-level constructors.
926-
WasmSym::applyDataRelocs = symtab->addSyntheticFunction(
927-
"__wasm_apply_data_relocs",
928-
WASM_SYMBOL_VISIBILITY_DEFAULT | WASM_SYMBOL_EXPORTED,
929-
make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs"));
930-
}
931920
}
932921

933922
static void createOptionalSymbols() {

lld/wasm/InputChunks.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,12 @@ uint64_t InputChunk::getVA(uint64_t offset) const {
361361
// Generate code to apply relocations to the data section at runtime.
362362
// This is only called when generating shared libraries (PIC) where address are
363363
// not known at static link time.
364-
void InputChunk::generateRelocationCode(raw_ostream &os) const {
364+
bool InputChunk::generateRelocationCode(raw_ostream &os) const {
365365
LLVM_DEBUG(dbgs() << "generating runtime relocations: " << name
366366
<< " count=" << relocations.size() << "\n");
367367

368368
bool is64 = config->is64.value_or(false);
369+
bool generated = false;
369370
unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
370371
: WASM_OPCODE_I32_CONST;
371372
unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
@@ -378,7 +379,10 @@ void InputChunk::generateRelocationCode(raw_ostream &os) const {
378379
uint64_t offset = getVA(rel.Offset) - getInputSectionOffset();
379380

380381
Symbol *sym = file->getSymbol(rel);
381-
if (!ctx.isPic && sym->isDefined())
382+
// Runtime relocations are needed when we don't know the address of
383+
// a symbol statically.
384+
bool requiresRuntimeReloc = ctx.isPic || sym->hasGOTIndex();
385+
if (!requiresRuntimeReloc)
382386
continue;
383387

384388
LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
@@ -435,7 +439,9 @@ void InputChunk::generateRelocationCode(raw_ostream &os) const {
435439
writeU8(os, opcode_reloc_store, "I32_STORE");
436440
writeUleb128(os, 2, "align");
437441
writeUleb128(os, 0, "offset");
442+
generated = true;
438443
}
444+
return generated;
439445
}
440446

441447
// Split WASM_SEG_FLAG_STRINGS section. Such a section is a sequence of

lld/wasm/InputChunks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class InputChunk {
7878

7979
size_t getNumRelocations() const { return relocations.size(); }
8080
void writeRelocations(llvm::raw_ostream &os) const;
81-
void generateRelocationCode(raw_ostream &os) const;
81+
bool generateRelocationCode(raw_ostream &os) const;
8282

8383
bool isTLS() const { return flags & llvm::wasm::WASM_SEG_FLAG_TLS; }
8484
bool isRetained() const { return flags & llvm::wasm::WASM_SEG_FLAG_RETAIN; }

lld/wasm/Symbols.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ namespace wasm {
8080
DefinedFunction *WasmSym::callCtors;
8181
DefinedFunction *WasmSym::callDtors;
8282
DefinedFunction *WasmSym::initMemory;
83-
DefinedFunction *WasmSym::applyDataRelocs;
8483
DefinedFunction *WasmSym::applyGlobalRelocs;
8584
DefinedFunction *WasmSym::applyTLSRelocs;
8685
DefinedFunction *WasmSym::applyGlobalTLSRelocs;

lld/wasm/Symbols.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -591,18 +591,14 @@ struct WasmSym {
591591
// Function that calls the libc/etc. cleanup function.
592592
static DefinedFunction *callDtors;
593593

594-
// __wasm_apply_data_relocs
595-
// Function that applies relocations to data segment post-instantiation.
596-
static DefinedFunction *applyDataRelocs;
597-
598594
// __wasm_apply_global_relocs
599595
// Function that applies relocations to wasm globals post-instantiation.
600596
// Unlike __wasm_apply_data_relocs this needs to run on every thread.
601597
static DefinedFunction *applyGlobalRelocs;
602598

603599
// __wasm_apply_tls_relocs
604-
// Like applyDataRelocs but for TLS section. These must be delayed until
605-
// __wasm_init_tls.
600+
// Like __wasm_apply_data_relocs but for TLS section. These must be
601+
// delayed until __wasm_init_tls.
606602
static DefinedFunction *applyTLSRelocs;
607603

608604
// __wasm_apply_global_tls_relocs

lld/wasm/Writer.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,8 @@ void Writer::createSyntheticInitFunctions() {
11451145

11461146
static WasmSignature nullSignature = {{}, {}};
11471147

1148+
createApplyDataRelocationsFunction();
1149+
11481150
// Passive segments are used to avoid memory being reinitialized on each
11491151
// thread's instantiation. These passive segments are initialized and
11501152
// dropped in __wasm_init_memory, which is registered as the start function
@@ -1467,15 +1469,29 @@ void Writer::createApplyDataRelocationsFunction() {
14671469
{
14681470
raw_string_ostream os(bodyContent);
14691471
writeUleb128(os, 0, "num locals");
1472+
bool generated = false;
14701473
for (const OutputSegment *seg : segments)
14711474
if (!config->sharedMemory || !seg->isTLS())
14721475
for (const InputChunk *inSeg : seg->inputSegments)
1473-
inSeg->generateRelocationCode(os);
1476+
generated |= inSeg->generateRelocationCode(os);
14741477

1478+
if (!generated) {
1479+
LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n");
1480+
return;
1481+
}
14751482
writeU8(os, WASM_OPCODE_END, "END");
14761483
}
14771484

1478-
createFunction(WasmSym::applyDataRelocs, bodyContent);
1485+
// __wasm_apply_data_relocs
1486+
// Function that applies relocations to data segment post-instantiation.
1487+
static WasmSignature nullSignature = {{}, {}};
1488+
auto def = symtab->addSyntheticFunction(
1489+
"__wasm_apply_data_relocs",
1490+
WASM_SYMBOL_VISIBILITY_DEFAULT | WASM_SYMBOL_EXPORTED,
1491+
make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs"));
1492+
def->markLive();
1493+
1494+
createFunction(def, bodyContent);
14791495
}
14801496

14811497
void Writer::createApplyTLSRelocationsFunction() {
@@ -1771,8 +1787,6 @@ void Writer::run() {
17711787

17721788
if (!config->relocatable) {
17731789
// Create linker synthesized functions
1774-
if (WasmSym::applyDataRelocs)
1775-
createApplyDataRelocationsFunction();
17761790
if (WasmSym::applyGlobalRelocs)
17771791
createApplyGlobalRelocationsFunction();
17781792
if (WasmSym::applyTLSRelocs)

0 commit comments

Comments
 (0)