[lld] [lld][WebAssembly]: Defer __wasm_apply_data_relocs decision to writer… (PR #109249)
YAMAMOTO Takashi via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 19 17:16:14 PDT 2024
https://github.com/yamt updated https://github.com/llvm/llvm-project/pull/109249
>From 50fd3a874d444a94e705b7bcc42149c75194b988 Mon Sep 17 00:00:00 2001
From: YAMAMOTO Takashi <yamamoto at midokura.com>
Date: Wed, 11 Sep 2024 15:04:01 +0900
Subject: [PATCH] [lld][WebAssembly]: Avoid emitting empty
__wasm_apply_data_relocs function
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
https://github.com/llvm/llvm-project/issues/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.)
---
lld/test/wasm/data-segments.ll | 9 +--------
lld/test/wasm/shared-weak-symbols.s | 15 +++++----------
lld/test/wasm/tls-export.s | 3 ---
lld/test/wasm/tls-non-shared-memory.s | 3 ---
lld/test/wasm/tls-relocations.s | 2 +-
lld/wasm/Driver.cpp | 11 -----------
lld/wasm/InputChunks.cpp | 7 +++++--
lld/wasm/InputChunks.h | 2 +-
lld/wasm/Symbols.cpp | 1 -
lld/wasm/Symbols.h | 8 ++------
lld/wasm/Writer.cpp | 22 ++++++++++++++++++----
11 files changed, 33 insertions(+), 50 deletions(-)
diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll
index 9354e6c8e4d2b0..670ac3c1f373fa 100644
--- a/lld/test/wasm/data-segments.ll
+++ b/lld/test/wasm/data-segments.ll
@@ -113,7 +113,7 @@
; PASSIVE-NEXT: Name: __wasm_init_memory
; PASSIVE-PIC: - Type: START
-; PASSIVE-PIC-NEXT: StartFunction: 3
+; PASSIVE-PIC-NEXT: StartFunction: 2
; PASSIVE-PIC-NEXT: - Type: DATACOUNT
; PASSIVE-PIC-NEXT: Count: 3
; PASSIVE-PIC-NEXT: - Type: CODE
@@ -125,9 +125,6 @@
; PASSIVE-PIC-NEXT: Locals: []
; PASSIVE-PIC-NEXT: Body: {{.*}}
; PASSIVE-PIC-NEXT: - Index: 2
-; PASSIVE-PIC-NEXT: Locals: []
-; PASSIVE-PIC-NEXT: Body: 0B
-; PASSIVE-PIC-NEXT: - Index: 3
; PASSIVE-PIC-NEXT: Locals:
; PASSIVE32-PIC-NEXT: - Type: I32
; PASSIVE64-PIC-NEXT: - Type: I64
@@ -152,8 +149,6 @@
; PASSIVE-PIC-NEXT: - Index: 1
; PASSIVE-PIC-NEXT: Name: __wasm_init_tls
; PASSIVE-PIC-NEXT: - Index: 2
-; PASSIVE-PIC-NEXT: Name: __wasm_apply_data_relocs
-; PASSIVE-PIC-NEXT: - Index: 3
; PASSIVE-PIC-NEXT: Name: __wasm_init_memory
; no data relocations.
@@ -161,8 +156,6 @@
; DIS-EMPTY:
; DIS-NEXT: end
-; In PIC mode __wasm_apply_data_relocs is export separatly to __wasm_call_ctors
-; PIC-DIS: <__wasm_apply_data_relocs>:
; PIC-DIS-EMPTY:
; DIS-LABEL: <__wasm_init_memory>:
diff --git a/lld/test/wasm/shared-weak-symbols.s b/lld/test/wasm/shared-weak-symbols.s
index 90de006353b3d3..df049ce4600fe4 100644
--- a/lld/test/wasm/shared-weak-symbols.s
+++ b/lld/test/wasm/shared-weak-symbols.s
@@ -30,7 +30,7 @@ call_weak:
# ASM: 10 80 80 80 80 00 call 0
drop
call hidden_weak_func
-# ASM: 10 84 80 80 80 00 call 4
+# ASM: 10 83 80 80 80 00 call 3
end_function
# ASM-NEXT: 0b end
@@ -62,15 +62,12 @@ call_weak:
# CHECK-NEXT: - Name: __wasm_call_ctors
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: Index: 1
-# CHECK-NEXT: - Name: __wasm_apply_data_relocs
-# CHECK-NEXT: Kind: FUNCTION
-# CHECK-NEXT: Index: 2
# CHECK-NEXT: - Name: weak_func
# CHECK-NEXT: Kind: FUNCTION
-# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Index: 2
# CHECK-NEXT: - Name: call_weak
# CHECK-NEXT: Kind: FUNCTION
-# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Index: 4
# CHECK-NEXT: - Type: CODE
# CHECK: - Type: CUSTOM
@@ -81,10 +78,8 @@ call_weak:
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Name: __wasm_call_ctors
# CHECK-NEXT: - Index: 2
-# CHECK-NEXT: Name: __wasm_apply_data_relocs
-# CHECK-NEXT: - Index: 3
# CHECK-NEXT: Name: weak_func
-# CHECK-NEXT: - Index: 4
+# CHECK-NEXT: - Index: 3
# CHECK-NEXT: Name: hidden_weak_func
-# CHECK-NEXT: - Index: 5
+# CHECK-NEXT: - Index: 4
# CHECK-NEXT: Name: call_weak
diff --git a/lld/test/wasm/tls-export.s b/lld/test/wasm/tls-export.s
index 1f64be607abb23..619f9d2df312ab 100644
--- a/lld/test/wasm/tls-export.s
+++ b/lld/test/wasm/tls-export.s
@@ -40,9 +40,6 @@ tls1:
# CHECK-NEXT: - Name: __wasm_call_ctors
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: Index: 0
-# CHECK-NEXT: - Name: __wasm_apply_data_relocs
-# CHECK-NEXT: Kind: FUNCTION
-# CHECK-NEXT: Index: 1
# CHECK-NEXT: - Name: tls1
# CHECK-NEXT: Kind: GLOBAL
# CHECK-NEXT: Index: 2
diff --git a/lld/test/wasm/tls-non-shared-memory.s b/lld/test/wasm/tls-non-shared-memory.s
index a2e2257cc9392e..1754fd6254bb80 100644
--- a/lld/test/wasm/tls-non-shared-memory.s
+++ b/lld/test/wasm/tls-non-shared-memory.s
@@ -127,9 +127,6 @@ tls1:
# PIE-NEXT: - Name: memory
# PIE-NEXT: Kind: MEMORY
# PIE-NEXT: Index: 0
-# PIE-NEXT: - Name: __wasm_apply_data_relocs
-# PIE-NEXT: Kind: FUNCTION
-# PIE-NEXT: Index: 1
# PIE-NEXT: - Type:
# .tdata and .data are combined into single segment in PIC mode.
diff --git a/lld/test/wasm/tls-relocations.s b/lld/test/wasm/tls-relocations.s
index ebe83227631f47..7260d72535a009 100644
--- a/lld/test/wasm/tls-relocations.s
+++ b/lld/test/wasm/tls-relocations.s
@@ -66,7 +66,7 @@ tls_sym:
# ASM-NEXT: i32.const 16
# ASM-NEXT: memory.init 0, 0
# call to __wasm_apply_tls_relocs
-# ASM-NEXT: call 4
+# ASM-NEXT: call 3
# ASM-NEXT: end
# ASM: <__wasm_apply_tls_relocs>:
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 2de7dcaeb43d47..289c1217ff5ead 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -917,17 +917,6 @@ static void createSyntheticSymbols() {
is64 ? i64ArgSignature : i32ArgSignature,
"__wasm_init_tls"));
}
-
- if (ctx.isPic ||
- config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic) {
- // For PIC code, or when dynamically importing addresses, we create
- // synthetic functions that apply relocations. These get called from
- // __wasm_call_ctors before the user-level constructors.
- WasmSym::applyDataRelocs = symtab->addSyntheticFunction(
- "__wasm_apply_data_relocs",
- WASM_SYMBOL_VISIBILITY_DEFAULT | WASM_SYMBOL_EXPORTED,
- make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs"));
- }
}
static void createOptionalSymbols() {
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index 975225974aff6e..11771c2e43554c 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -361,11 +361,12 @@ uint64_t InputChunk::getVA(uint64_t offset) const {
// Generate code to apply relocations to the data section at runtime.
// This is only called when generating shared libraries (PIC) where address are
// not known at static link time.
-void InputChunk::generateRelocationCode(raw_ostream &os) const {
+bool InputChunk::generateRelocationCode(raw_ostream &os) const {
LLVM_DEBUG(dbgs() << "generating runtime relocations: " << name
<< " count=" << relocations.size() << "\n");
bool is64 = config->is64.value_or(false);
+ bool generated = false;
unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
: WASM_OPCODE_I32_CONST;
unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
@@ -378,7 +379,7 @@ void InputChunk::generateRelocationCode(raw_ostream &os) const {
uint64_t offset = getVA(rel.Offset) - getInputSectionOffset();
Symbol *sym = file->getSymbol(rel);
- if (!ctx.isPic && sym->isDefined())
+ if (!ctx.isPic && !sym->hasGOTIndex())
continue;
LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
@@ -435,7 +436,9 @@ void InputChunk::generateRelocationCode(raw_ostream &os) const {
writeU8(os, opcode_reloc_store, "I32_STORE");
writeUleb128(os, 2, "align");
writeUleb128(os, 0, "offset");
+ generated = true;
}
+ return generated;
}
// Split WASM_SEG_FLAG_STRINGS section. Such a section is a sequence of
diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h
index 5174439facc678..14eb008c212fb5 100644
--- a/lld/wasm/InputChunks.h
+++ b/lld/wasm/InputChunks.h
@@ -78,7 +78,7 @@ class InputChunk {
size_t getNumRelocations() const { return relocations.size(); }
void writeRelocations(llvm::raw_ostream &os) const;
- void generateRelocationCode(raw_ostream &os) const;
+ bool generateRelocationCode(raw_ostream &os) const;
bool isTLS() const { return flags & llvm::wasm::WASM_SEG_FLAG_TLS; }
bool isRetained() const { return flags & llvm::wasm::WASM_SEG_FLAG_RETAIN; }
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index f74699d0763fd9..b2bbd11c53ef23 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -80,7 +80,6 @@ namespace wasm {
DefinedFunction *WasmSym::callCtors;
DefinedFunction *WasmSym::callDtors;
DefinedFunction *WasmSym::initMemory;
-DefinedFunction *WasmSym::applyDataRelocs;
DefinedFunction *WasmSym::applyGlobalRelocs;
DefinedFunction *WasmSym::applyTLSRelocs;
DefinedFunction *WasmSym::applyGlobalTLSRelocs;
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index 2ba575fddc8796..5ce3ecbc4ab194 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -591,18 +591,14 @@ struct WasmSym {
// Function that calls the libc/etc. cleanup function.
static DefinedFunction *callDtors;
- // __wasm_apply_data_relocs
- // Function that applies relocations to data segment post-instantiation.
- static DefinedFunction *applyDataRelocs;
-
// __wasm_apply_global_relocs
// Function that applies relocations to wasm globals post-instantiation.
// Unlike __wasm_apply_data_relocs this needs to run on every thread.
static DefinedFunction *applyGlobalRelocs;
// __wasm_apply_tls_relocs
- // Like applyDataRelocs but for TLS section. These must be delayed until
- // __wasm_init_tls.
+ // Like __wasm_apply_data_relocs but for TLS section. These must be
+ // delayed until __wasm_init_tls.
static DefinedFunction *applyTLSRelocs;
// __wasm_apply_global_tls_relocs
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 681f6a137ceac4..77cddfc34389c3 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -1145,6 +1145,8 @@ void Writer::createSyntheticInitFunctions() {
static WasmSignature nullSignature = {{}, {}};
+ createApplyDataRelocationsFunction();
+
// Passive segments are used to avoid memory being reinitialized on each
// thread's instantiation. These passive segments are initialized and
// dropped in __wasm_init_memory, which is registered as the start function
@@ -1467,15 +1469,29 @@ void Writer::createApplyDataRelocationsFunction() {
{
raw_string_ostream os(bodyContent);
writeUleb128(os, 0, "num locals");
+ bool generated = false;
for (const OutputSegment *seg : segments)
if (!config->sharedMemory || !seg->isTLS())
for (const InputChunk *inSeg : seg->inputSegments)
- inSeg->generateRelocationCode(os);
+ generated |= inSeg->generateRelocationCode(os);
+ if (!generated) {
+ LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n");
+ return;
+ }
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::applyDataRelocs, bodyContent);
+ // __wasm_apply_data_relocs
+ // Function that applies relocations to data segment post-instantiation.
+ static WasmSignature nullSignature = {{}, {}};
+ auto def = symtab->addSyntheticFunction(
+ "__wasm_apply_data_relocs",
+ WASM_SYMBOL_VISIBILITY_DEFAULT | WASM_SYMBOL_EXPORTED,
+ make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs"));
+ def->markLive();
+
+ createFunction(def, bodyContent);
}
void Writer::createApplyTLSRelocationsFunction() {
@@ -1771,8 +1787,6 @@ void Writer::run() {
if (!config->relocatable) {
// Create linker synthesized functions
- if (WasmSym::applyDataRelocs)
- createApplyDataRelocationsFunction();
if (WasmSym::applyGlobalRelocs)
createApplyGlobalRelocationsFunction();
if (WasmSym::applyTLSRelocs)
More information about the llvm-commits
mailing list