Skip to content

release/20.x: [wasm-ld] Refactor WasmSym from static globals to per-link context (#134970) #137620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: release/20.x
Choose a base branch
from

Conversation

anutosh491
Copy link
Contributor

Backport : 9cbbb74

…lvm#134970)

Towards

This change moves WasmSym from a static global struct to an instance
owned by Ctx, allowing it to be reset cleanly between linker runs. This
enables safe support for multiple invocations of wasm-ld within the same
process

Changes done

- Converted WasmSym from a static struct to a regular struct with
instance members.

- Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx.

- Reset wasmSym in Ctx::reset() to clear state between links.

- Replaced all WasmSym:: references with ctx.wasmSym->.

- Removed global symbol definitions from Symbols.cpp that are no longer
needed.

Clearing wasmSym in ctx.reset() ensures a clean slate for each link
invocation, preventing symbol leakage across runs—critical when using
wasm-ld/lld as a reentrant library where global state can cause subtle,
hard-to-debug errors.

---------

Co-authored-by: Vassil Vassilev <v.g.vassilev@gmail.com>
(cherry picked from commit 9cbbb74)
@llvmbot
Copy link
Member

llvmbot commented Apr 28, 2025

@llvm/pr-subscribers-lld-wasm

Author: Anutosh Bhat (anutosh491)

Changes

Backport : 9cbbb74


Patch is 44.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/137620.diff

9 Files Affected:

  • (modified) lld/wasm/Config.h (+110)
  • (modified) lld/wasm/Driver.cpp (+34-30)
  • (modified) lld/wasm/InputChunks.cpp (+5-5)
  • (modified) lld/wasm/MarkLive.cpp (+3-3)
  • (modified) lld/wasm/OutputSections.cpp (+2-2)
  • (modified) lld/wasm/Symbols.cpp (-25)
  • (modified) lld/wasm/Symbols.h (-99)
  • (modified) lld/wasm/SyntheticSections.cpp (+14-18)
  • (modified) lld/wasm/Writer.cpp (+94-93)
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 1fa6c42d9cd86..71dabaedb8a8c 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -32,6 +32,11 @@ class InputTable;
 class InputGlobal;
 class InputFunction;
 class Symbol;
+class DefinedData;
+class GlobalSymbol;
+class DefinedFunction;
+class UndefinedGlobal;
+class TableSymbol;
 
 // For --unresolved-symbols.
 enum class UnresolvedPolicy { ReportError, Warn, Ignore, ImportDynamic };
@@ -139,6 +144,111 @@ struct Ctx {
   llvm::SmallVector<InputGlobal *, 0> syntheticGlobals;
   llvm::SmallVector<InputTable *, 0> syntheticTables;
 
+  // linker-generated symbols
+  struct WasmSym {
+    // __global_base
+    // Symbol marking the start of the global section.
+    DefinedData *globalBase;
+
+    // __stack_pointer/__stack_low/__stack_high
+    // Global that holds current value of stack pointer and data symbols marking
+    // the start and end of the stack region.  stackPointer is initialized to
+    // stackHigh and grows downwards towards stackLow
+    GlobalSymbol *stackPointer;
+    DefinedData *stackLow;
+    DefinedData *stackHigh;
+
+    // __tls_base
+    // Global that holds the address of the base of the current thread's
+    // TLS block.
+    GlobalSymbol *tlsBase;
+
+    // __tls_size
+    // Symbol whose value is the size of the TLS block.
+    GlobalSymbol *tlsSize;
+
+    // __tls_size
+    // Symbol whose value is the alignment of the TLS block.
+    GlobalSymbol *tlsAlign;
+
+    // __data_end
+    // Symbol marking the end of the data and bss.
+    DefinedData *dataEnd;
+
+    // __heap_base/__heap_end
+    // Symbols marking the beginning and end of the "heap". It starts at the end
+    // of the data, bss and explicit stack, and extends to the end of the linear
+    // memory allocated by wasm-ld. This region of memory is not used by the
+    // linked code, so it may be used as a backing store for `sbrk` or `malloc`
+    // implementations.
+    DefinedData *heapBase;
+    DefinedData *heapEnd;
+
+    // __wasm_first_page_end
+    // A symbol whose address is the end of the first page in memory (if any).
+    DefinedData *firstPageEnd;
+
+    // __wasm_init_memory_flag
+    // Symbol whose contents are nonzero iff memory has already been
+    // initialized.
+    DefinedData *initMemoryFlag;
+
+    // __wasm_init_memory
+    // Function that initializes passive data segments during instantiation.
+    DefinedFunction *initMemory;
+
+    // __wasm_call_ctors
+    // Function that directly calls all ctors in priority order.
+    DefinedFunction *callCtors;
+
+    // __wasm_call_dtors
+    // Function that calls the libc/etc. cleanup function.
+    DefinedFunction *callDtors;
+
+    // __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.
+    DefinedFunction *applyGlobalRelocs;
+
+    // __wasm_apply_tls_relocs
+    // Like __wasm_apply_data_relocs but for TLS section.  These must be
+    // delayed until __wasm_init_tls.
+    DefinedFunction *applyTLSRelocs;
+
+    // __wasm_apply_global_tls_relocs
+    // Like applyGlobalRelocs but for globals that hold TLS addresses.  These
+    // must be delayed until __wasm_init_tls.
+    DefinedFunction *applyGlobalTLSRelocs;
+
+    // __wasm_init_tls
+    // Function that allocates thread-local storage and initializes it.
+    DefinedFunction *initTLS;
+
+    // Pointer to the function that is to be used in the start section.
+    // (normally an alias of initMemory, or applyGlobalRelocs).
+    DefinedFunction *startFunction;
+
+    // __dso_handle
+    // Symbol used in calls to __cxa_atexit to determine current DLL
+    DefinedData *dsoHandle;
+
+    // __table_base
+    // Used in PIC code for offset of indirect function table
+    UndefinedGlobal *tableBase;
+    DefinedData *definedTableBase;
+
+    // __memory_base
+    // Used in PIC code for offset of global data
+    UndefinedGlobal *memoryBase;
+    DefinedData *definedMemoryBase;
+
+    // __indirect_function_table
+    // Used as an address space for function pointers, with each function that
+    // is used as a function pointer being allocated a slot.
+    TableSymbol *indirectFunctionTable;
+  };
+  WasmSym sym;
+
   // True if we are creating position-independent code.
   bool isPic = false;
 
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index c3a74dde6480e..a6e6f90e56dc3 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -70,6 +70,7 @@ void Ctx::reset() {
   isPic = false;
   legacyFunctionTable = false;
   emitBssSegments = false;
+  sym = WasmSym{};
 }
 
 namespace {
@@ -941,14 +942,14 @@ static void createSyntheticSymbols() {
                                                             true};
   static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
                                                             true};
-  WasmSym::callCtors = symtab->addSyntheticFunction(
+  ctx.sym.callCtors = symtab->addSyntheticFunction(
       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
       make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
 
   bool is64 = ctx.arg.is64.value_or(false);
 
   if (ctx.isPic) {
-    WasmSym::stackPointer =
+    ctx.sym.stackPointer =
         createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
                                                      ? &mutableGlobalTypeI64
                                                      : &mutableGlobalTypeI32);
@@ -958,25 +959,24 @@ static void createSyntheticSymbols() {
     // See:
     // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
     auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32;
-    WasmSym::memoryBase = createUndefinedGlobal("__memory_base", globalType);
-    WasmSym::tableBase = createUndefinedGlobal("__table_base", globalType);
-    WasmSym::memoryBase->markLive();
-    WasmSym::tableBase->markLive();
+    ctx.sym.memoryBase = createUndefinedGlobal("__memory_base", globalType);
+    ctx.sym.tableBase = createUndefinedGlobal("__table_base", globalType);
+    ctx.sym.memoryBase->markLive();
+    ctx.sym.tableBase->markLive();
   } else {
     // For non-PIC code
-    WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true);
-    WasmSym::stackPointer->markLive();
+    ctx.sym.stackPointer = createGlobalVariable("__stack_pointer", true);
+    ctx.sym.stackPointer->markLive();
   }
 
   if (ctx.arg.sharedMemory) {
-    WasmSym::tlsBase = createGlobalVariable("__tls_base", true);
-    WasmSym::tlsSize = createGlobalVariable("__tls_size", false);
-    WasmSym::tlsAlign = createGlobalVariable("__tls_align", false);
-    WasmSym::initTLS = symtab->addSyntheticFunction(
+    ctx.sym.tlsBase = createGlobalVariable("__tls_base", true);
+    ctx.sym.tlsSize = createGlobalVariable("__tls_size", false);
+    ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false);
+    ctx.sym.initTLS = symtab->addSyntheticFunction(
         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
-        make<SyntheticFunction>(
-            is64 ? i64ArgSignature : i32ArgSignature,
-            "__wasm_init_tls"));
+        make<SyntheticFunction>(is64 ? i64ArgSignature : i32ArgSignature,
+                                "__wasm_init_tls"));
   }
 }
 
@@ -984,21 +984,25 @@ static void createOptionalSymbols() {
   if (ctx.arg.relocatable)
     return;
 
-  WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
+  ctx.sym.dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
 
   if (!ctx.arg.shared)
-    WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
+    ctx.sym.dataEnd = symtab->addOptionalDataSymbol("__data_end");
 
   if (!ctx.isPic) {
-    WasmSym::stackLow = symtab->addOptionalDataSymbol("__stack_low");
-    WasmSym::stackHigh = symtab->addOptionalDataSymbol("__stack_high");
-    WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
-    WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
-    WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end");
-    WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
-    WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
+    ctx.sym.stackLow = symtab->addOptionalDataSymbol("__stack_low");
+    ctx.sym.stackHigh = symtab->addOptionalDataSymbol("__stack_high");
+    ctx.sym.globalBase = symtab->addOptionalDataSymbol("__global_base");
+    ctx.sym.heapBase = symtab->addOptionalDataSymbol("__heap_base");
+    ctx.sym.heapEnd = symtab->addOptionalDataSymbol("__heap_end");
+    ctx.sym.definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
+    ctx.sym.definedTableBase = symtab->addOptionalDataSymbol("__table_base");
   }
 
+  ctx.sym.firstPageEnd = symtab->addOptionalDataSymbol("__wasm_first_page_end");
+  if (ctx.sym.firstPageEnd)
+    ctx.sym.firstPageEnd->setVA(ctx.arg.pageSize);
+
   // For non-shared memory programs we still need to define __tls_base since we
   // allow object files built with TLS to be linked into single threaded
   // programs, and such object files can contain references to this symbol.
@@ -1009,7 +1013,7 @@ static void createOptionalSymbols() {
   // __tls_size and __tls_align are not needed in this case since they are only
   // needed for __wasm_init_tls (which we do not create in this case).
   if (!ctx.arg.sharedMemory)
-    WasmSym::tlsBase = createOptionalGlobal("__tls_base", false);
+    ctx.sym.tlsBase = createOptionalGlobal("__tls_base", false);
 }
 
 static void processStubLibrariesPreLTO() {
@@ -1384,9 +1388,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // by libc/etc., because destructors are registered dynamically with
   // `__cxa_atexit` and friends.
   if (!ctx.arg.relocatable && !ctx.arg.shared &&
-      !WasmSym::callCtors->isUsedInRegularObj &&
-      WasmSym::callCtors->getName() != ctx.arg.entry &&
-      !ctx.arg.exportedSymbols.count(WasmSym::callCtors->getName())) {
+      !ctx.sym.callCtors->isUsedInRegularObj &&
+      ctx.sym.callCtors->getName() != ctx.arg.entry &&
+      !ctx.arg.exportedSymbols.count(ctx.sym.callCtors->getName())) {
     if (Symbol *callDtors =
             handleUndefined("__wasm_call_dtors", "<internal>")) {
       if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) {
@@ -1395,7 +1399,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
              !callDtorsFunc->signature->Returns.empty())) {
           error("__wasm_call_dtors must have no argument or return values");
         }
-        WasmSym::callDtors = callDtorsFunc;
+        ctx.sym.callDtors = callDtorsFunc;
       } else {
         error("__wasm_call_dtors must be a function");
       }
@@ -1488,7 +1492,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   markLive();
 
   // Provide the indirect function table if needed.
-  WasmSym::indirectFunctionTable =
+  ctx.sym.indirectFunctionTable =
       symtab->resolveIndirectFunctionTable(/*required =*/false);
 
   if (errorCount())
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index ccdc92f5c8d71..0e6c4e691be10 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -397,9 +397,9 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
     if (ctx.isPic) {
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
       if (isTLS())
-        writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "tls_base");
+        writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "tls_base");
       else
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
+        writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "memory_base");
       writeU8(os, opcode_ptr_add, "ADD");
     }
 
@@ -422,12 +422,12 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
       }
     } else {
       assert(ctx.isPic);
-      const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
+      const GlobalSymbol *baseSymbol = ctx.sym.memoryBase;
       if (rel.Type == R_WASM_TABLE_INDEX_I32 ||
           rel.Type == R_WASM_TABLE_INDEX_I64)
-        baseSymbol = WasmSym::tableBase;
+        baseSymbol = ctx.sym.tableBase;
       else if (sym->isTLS())
-        baseSymbol = WasmSym::tlsBase;
+        baseSymbol = ctx.sym.tlsBase;
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
       writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
       writeU8(os, opcode_reloc_const, "CONST");
diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp
index 13c7a3d894fe3..2b2cf19f14b30 100644
--- a/lld/wasm/MarkLive.cpp
+++ b/lld/wasm/MarkLive.cpp
@@ -114,8 +114,8 @@ void MarkLive::run() {
     if (sym->isNoStrip() || sym->isExported())
       enqueue(sym);
 
-  if (WasmSym::callDtors)
-    enqueue(WasmSym::callDtors);
+  if (ctx.sym.callDtors)
+    enqueue(ctx.sym.callDtors);
 
   for (const ObjFile *obj : ctx.objectFiles)
     if (obj->isLive()) {
@@ -131,7 +131,7 @@ void MarkLive::run() {
   // If we have any non-discarded init functions, mark `__wasm_call_ctors` as
   // live so that we assign it an index and call it.
   if (isCallCtorsLive())
-    WasmSym::callCtors->markLive();
+    ctx.sym.callCtors->markLive();
 }
 
 void MarkLive::mark() {
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index 95f7ecc29de6b..4142a913c8cbf 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -123,7 +123,7 @@ void DataSection::finalizeContents() {
     if ((segment->initFlags & WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
       if (ctx.isPic && ctx.arg.extendedConst) {
         writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
+        writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
                      "literal (global index)");
         if (segment->startVA) {
           writePtrConst(os, segment->startVA, is64, "offset");
@@ -136,7 +136,7 @@ void DataSection::finalizeContents() {
         if (ctx.isPic) {
           assert(segment->startVA == 0);
           initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
-          initExpr.Inst.Value.Global = WasmSym::memoryBase->getGlobalIndex();
+          initExpr.Inst.Value.Global = ctx.sym.memoryBase->getGlobalIndex();
         } else {
           initExpr = intConst(segment->startVA, is64);
         }
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index a687fd6d6c4ef..92a933ecbb024 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -77,31 +77,6 @@ std::string toString(wasm::Symbol::Kind kind) {
 }
 
 namespace wasm {
-DefinedFunction *WasmSym::callCtors;
-DefinedFunction *WasmSym::callDtors;
-DefinedFunction *WasmSym::initMemory;
-DefinedFunction *WasmSym::applyGlobalRelocs;
-DefinedFunction *WasmSym::applyTLSRelocs;
-DefinedFunction *WasmSym::applyGlobalTLSRelocs;
-DefinedFunction *WasmSym::initTLS;
-DefinedFunction *WasmSym::startFunction;
-DefinedData *WasmSym::dsoHandle;
-DefinedData *WasmSym::dataEnd;
-DefinedData *WasmSym::globalBase;
-DefinedData *WasmSym::heapBase;
-DefinedData *WasmSym::heapEnd;
-DefinedData *WasmSym::initMemoryFlag;
-GlobalSymbol *WasmSym::stackPointer;
-DefinedData *WasmSym::stackLow;
-DefinedData *WasmSym::stackHigh;
-GlobalSymbol *WasmSym::tlsBase;
-GlobalSymbol *WasmSym::tlsSize;
-GlobalSymbol *WasmSym::tlsAlign;
-UndefinedGlobal *WasmSym::tableBase;
-DefinedData *WasmSym::definedTableBase;
-UndefinedGlobal *WasmSym::memoryBase;
-DefinedData *WasmSym::definedMemoryBase;
-TableSymbol *WasmSym::indirectFunctionTable;
 
 WasmSymbolType Symbol::getWasmType() const {
   if (isa<FunctionSymbol>(this))
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index b409fffc50a6c..55ee21939ce07 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -537,105 +537,6 @@ class LazySymbol : public Symbol {
   const WasmSignature *signature = nullptr;
 };
 
-// linker-generated symbols
-struct WasmSym {
-  // __global_base
-  // Symbol marking the start of the global section.
-  static DefinedData *globalBase;
-
-  // __stack_pointer/__stack_low/__stack_high
-  // Global that holds current value of stack pointer and data symbols marking
-  // the start and end of the stack region.  stackPointer is initialized to
-  // stackHigh and grows downwards towards stackLow
-  static GlobalSymbol *stackPointer;
-  static DefinedData *stackLow;
-  static DefinedData *stackHigh;
-
-  // __tls_base
-  // Global that holds the address of the base of the current thread's
-  // TLS block.
-  static GlobalSymbol *tlsBase;
-
-  // __tls_size
-  // Symbol whose value is the size of the TLS block.
-  static GlobalSymbol *tlsSize;
-
-  // __tls_size
-  // Symbol whose value is the alignment of the TLS block.
-  static GlobalSymbol *tlsAlign;
-
-  // __data_end
-  // Symbol marking the end of the data and bss.
-  static DefinedData *dataEnd;
-
-  // __heap_base/__heap_end
-  // Symbols marking the beginning and end of the "heap". It starts at the end
-  // of the data, bss and explicit stack, and extends to the end of the linear
-  // memory allocated by wasm-ld. This region of memory is not used by the
-  // linked code, so it may be used as a backing store for `sbrk` or `malloc`
-  // implementations.
-  static DefinedData *heapBase;
-  static DefinedData *heapEnd;
-
-  // __wasm_init_memory_flag
-  // Symbol whose contents are nonzero iff memory has already been initialized.
-  static DefinedData *initMemoryFlag;
-
-  // __wasm_init_memory
-  // Function that initializes passive data segments during instantiation.
-  static DefinedFunction *initMemory;
-
-  // __wasm_call_ctors
-  // Function that directly calls all ctors in priority order.
-  static DefinedFunction *callCtors;
-
-  // __wasm_call_dtors
-  // Function that calls the libc/etc. cleanup function.
-  static DefinedFunction *callDtors;
-
-  // __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 __wasm_apply_data_relocs but for TLS section.  These must be
-  // delayed until __wasm_init_tls.
-  static DefinedFunction *applyTLSRelocs;
-
-  // __wasm_apply_global_tls_relocs
-  // Like applyGlobalRelocs but for globals that hold TLS addresses.  These
-  // must be delayed until __wasm_init_tls.
-  static DefinedFunction *applyGlobalTLSRelocs;
-
-  // __wasm_init_tls
-  // Function that allocates thread-local storage and initializes it.
-  static DefinedFunction *initTLS;
-
-  // Pointer to the function that is to be used in the start section.
-  // (normally an alias of initMemory, or applyGlobalRelocs).
-  static DefinedFunction *startFunction;
-
-  // __dso_handle
-  // Symbol used in calls to __cxa_atexit to determine current DLL
-  static DefinedData *dsoHandle;
-
-  // __table_base
-  // Used in PIC code for offset of indirect function table
-  static UndefinedGlobal *tableBase;
-  static DefinedData *definedTableBase;
-
-  // __memory_base
-  // Used in PIC code for offset of global data
-  static UndefinedGlobal *memoryBase;
-  static DefinedData *definedMemoryBase;
-
-  // __indirect_function_table
-  // Used as an address space for function pointers, with each function that is
-  // used as a function pointer being allocated a slot.
-  static TableSymbol *indirectFunctionTable;
-};
-
 // A buffer class that is large enough to hold any Symbol-derived
 // object. We allocate memory using this class and instantiate a symbol
 // using the placement new.
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 7fb44b9f0c009..0e2aa57e9048e 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -319,8 +319,8 @@ void TableSection::addTable(InputTable *table) {
   // Some inputs require that the indirect function table be assigned to table
   // number 0.
   if (ctx.legacyFunctionTable &&
-      isa<DefinedTable>(WasmSym::indirectFunctionTable) &&
-      cast<DefinedTable>(WasmSym::indirectFunctionTable)->table == table) {
+      isa<DefinedTable>(ctx.sym.indirectFunctionTable) &&
+      cast<DefinedTable>(ctx.sym.indirectFunctionTable)->table == table) {
     if (out.importSec->getNumImportedTables()) {
       // Alack!  Some other i...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Apr 28, 2025

@llvm/pr-subscribers-lld

Author: Anutosh Bhat (anutosh491)

Changes

Backport : 9cbbb74


Patch is 44.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/137620.diff

9 Files Affected:

  • (modified) lld/wasm/Config.h (+110)
  • (modified) lld/wasm/Driver.cpp (+34-30)
  • (modified) lld/wasm/InputChunks.cpp (+5-5)
  • (modified) lld/wasm/MarkLive.cpp (+3-3)
  • (modified) lld/wasm/OutputSections.cpp (+2-2)
  • (modified) lld/wasm/Symbols.cpp (-25)
  • (modified) lld/wasm/Symbols.h (-99)
  • (modified) lld/wasm/SyntheticSections.cpp (+14-18)
  • (modified) lld/wasm/Writer.cpp (+94-93)
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 1fa6c42d9cd86..71dabaedb8a8c 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -32,6 +32,11 @@ class InputTable;
 class InputGlobal;
 class InputFunction;
 class Symbol;
+class DefinedData;
+class GlobalSymbol;
+class DefinedFunction;
+class UndefinedGlobal;
+class TableSymbol;
 
 // For --unresolved-symbols.
 enum class UnresolvedPolicy { ReportError, Warn, Ignore, ImportDynamic };
@@ -139,6 +144,111 @@ struct Ctx {
   llvm::SmallVector<InputGlobal *, 0> syntheticGlobals;
   llvm::SmallVector<InputTable *, 0> syntheticTables;
 
+  // linker-generated symbols
+  struct WasmSym {
+    // __global_base
+    // Symbol marking the start of the global section.
+    DefinedData *globalBase;
+
+    // __stack_pointer/__stack_low/__stack_high
+    // Global that holds current value of stack pointer and data symbols marking
+    // the start and end of the stack region.  stackPointer is initialized to
+    // stackHigh and grows downwards towards stackLow
+    GlobalSymbol *stackPointer;
+    DefinedData *stackLow;
+    DefinedData *stackHigh;
+
+    // __tls_base
+    // Global that holds the address of the base of the current thread's
+    // TLS block.
+    GlobalSymbol *tlsBase;
+
+    // __tls_size
+    // Symbol whose value is the size of the TLS block.
+    GlobalSymbol *tlsSize;
+
+    // __tls_size
+    // Symbol whose value is the alignment of the TLS block.
+    GlobalSymbol *tlsAlign;
+
+    // __data_end
+    // Symbol marking the end of the data and bss.
+    DefinedData *dataEnd;
+
+    // __heap_base/__heap_end
+    // Symbols marking the beginning and end of the "heap". It starts at the end
+    // of the data, bss and explicit stack, and extends to the end of the linear
+    // memory allocated by wasm-ld. This region of memory is not used by the
+    // linked code, so it may be used as a backing store for `sbrk` or `malloc`
+    // implementations.
+    DefinedData *heapBase;
+    DefinedData *heapEnd;
+
+    // __wasm_first_page_end
+    // A symbol whose address is the end of the first page in memory (if any).
+    DefinedData *firstPageEnd;
+
+    // __wasm_init_memory_flag
+    // Symbol whose contents are nonzero iff memory has already been
+    // initialized.
+    DefinedData *initMemoryFlag;
+
+    // __wasm_init_memory
+    // Function that initializes passive data segments during instantiation.
+    DefinedFunction *initMemory;
+
+    // __wasm_call_ctors
+    // Function that directly calls all ctors in priority order.
+    DefinedFunction *callCtors;
+
+    // __wasm_call_dtors
+    // Function that calls the libc/etc. cleanup function.
+    DefinedFunction *callDtors;
+
+    // __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.
+    DefinedFunction *applyGlobalRelocs;
+
+    // __wasm_apply_tls_relocs
+    // Like __wasm_apply_data_relocs but for TLS section.  These must be
+    // delayed until __wasm_init_tls.
+    DefinedFunction *applyTLSRelocs;
+
+    // __wasm_apply_global_tls_relocs
+    // Like applyGlobalRelocs but for globals that hold TLS addresses.  These
+    // must be delayed until __wasm_init_tls.
+    DefinedFunction *applyGlobalTLSRelocs;
+
+    // __wasm_init_tls
+    // Function that allocates thread-local storage and initializes it.
+    DefinedFunction *initTLS;
+
+    // Pointer to the function that is to be used in the start section.
+    // (normally an alias of initMemory, or applyGlobalRelocs).
+    DefinedFunction *startFunction;
+
+    // __dso_handle
+    // Symbol used in calls to __cxa_atexit to determine current DLL
+    DefinedData *dsoHandle;
+
+    // __table_base
+    // Used in PIC code for offset of indirect function table
+    UndefinedGlobal *tableBase;
+    DefinedData *definedTableBase;
+
+    // __memory_base
+    // Used in PIC code for offset of global data
+    UndefinedGlobal *memoryBase;
+    DefinedData *definedMemoryBase;
+
+    // __indirect_function_table
+    // Used as an address space for function pointers, with each function that
+    // is used as a function pointer being allocated a slot.
+    TableSymbol *indirectFunctionTable;
+  };
+  WasmSym sym;
+
   // True if we are creating position-independent code.
   bool isPic = false;
 
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index c3a74dde6480e..a6e6f90e56dc3 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -70,6 +70,7 @@ void Ctx::reset() {
   isPic = false;
   legacyFunctionTable = false;
   emitBssSegments = false;
+  sym = WasmSym{};
 }
 
 namespace {
@@ -941,14 +942,14 @@ static void createSyntheticSymbols() {
                                                             true};
   static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
                                                             true};
-  WasmSym::callCtors = symtab->addSyntheticFunction(
+  ctx.sym.callCtors = symtab->addSyntheticFunction(
       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
       make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
 
   bool is64 = ctx.arg.is64.value_or(false);
 
   if (ctx.isPic) {
-    WasmSym::stackPointer =
+    ctx.sym.stackPointer =
         createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
                                                      ? &mutableGlobalTypeI64
                                                      : &mutableGlobalTypeI32);
@@ -958,25 +959,24 @@ static void createSyntheticSymbols() {
     // See:
     // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
     auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32;
-    WasmSym::memoryBase = createUndefinedGlobal("__memory_base", globalType);
-    WasmSym::tableBase = createUndefinedGlobal("__table_base", globalType);
-    WasmSym::memoryBase->markLive();
-    WasmSym::tableBase->markLive();
+    ctx.sym.memoryBase = createUndefinedGlobal("__memory_base", globalType);
+    ctx.sym.tableBase = createUndefinedGlobal("__table_base", globalType);
+    ctx.sym.memoryBase->markLive();
+    ctx.sym.tableBase->markLive();
   } else {
     // For non-PIC code
-    WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true);
-    WasmSym::stackPointer->markLive();
+    ctx.sym.stackPointer = createGlobalVariable("__stack_pointer", true);
+    ctx.sym.stackPointer->markLive();
   }
 
   if (ctx.arg.sharedMemory) {
-    WasmSym::tlsBase = createGlobalVariable("__tls_base", true);
-    WasmSym::tlsSize = createGlobalVariable("__tls_size", false);
-    WasmSym::tlsAlign = createGlobalVariable("__tls_align", false);
-    WasmSym::initTLS = symtab->addSyntheticFunction(
+    ctx.sym.tlsBase = createGlobalVariable("__tls_base", true);
+    ctx.sym.tlsSize = createGlobalVariable("__tls_size", false);
+    ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false);
+    ctx.sym.initTLS = symtab->addSyntheticFunction(
         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
-        make<SyntheticFunction>(
-            is64 ? i64ArgSignature : i32ArgSignature,
-            "__wasm_init_tls"));
+        make<SyntheticFunction>(is64 ? i64ArgSignature : i32ArgSignature,
+                                "__wasm_init_tls"));
   }
 }
 
@@ -984,21 +984,25 @@ static void createOptionalSymbols() {
   if (ctx.arg.relocatable)
     return;
 
-  WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
+  ctx.sym.dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
 
   if (!ctx.arg.shared)
-    WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
+    ctx.sym.dataEnd = symtab->addOptionalDataSymbol("__data_end");
 
   if (!ctx.isPic) {
-    WasmSym::stackLow = symtab->addOptionalDataSymbol("__stack_low");
-    WasmSym::stackHigh = symtab->addOptionalDataSymbol("__stack_high");
-    WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
-    WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
-    WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end");
-    WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
-    WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
+    ctx.sym.stackLow = symtab->addOptionalDataSymbol("__stack_low");
+    ctx.sym.stackHigh = symtab->addOptionalDataSymbol("__stack_high");
+    ctx.sym.globalBase = symtab->addOptionalDataSymbol("__global_base");
+    ctx.sym.heapBase = symtab->addOptionalDataSymbol("__heap_base");
+    ctx.sym.heapEnd = symtab->addOptionalDataSymbol("__heap_end");
+    ctx.sym.definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
+    ctx.sym.definedTableBase = symtab->addOptionalDataSymbol("__table_base");
   }
 
+  ctx.sym.firstPageEnd = symtab->addOptionalDataSymbol("__wasm_first_page_end");
+  if (ctx.sym.firstPageEnd)
+    ctx.sym.firstPageEnd->setVA(ctx.arg.pageSize);
+
   // For non-shared memory programs we still need to define __tls_base since we
   // allow object files built with TLS to be linked into single threaded
   // programs, and such object files can contain references to this symbol.
@@ -1009,7 +1013,7 @@ static void createOptionalSymbols() {
   // __tls_size and __tls_align are not needed in this case since they are only
   // needed for __wasm_init_tls (which we do not create in this case).
   if (!ctx.arg.sharedMemory)
-    WasmSym::tlsBase = createOptionalGlobal("__tls_base", false);
+    ctx.sym.tlsBase = createOptionalGlobal("__tls_base", false);
 }
 
 static void processStubLibrariesPreLTO() {
@@ -1384,9 +1388,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // by libc/etc., because destructors are registered dynamically with
   // `__cxa_atexit` and friends.
   if (!ctx.arg.relocatable && !ctx.arg.shared &&
-      !WasmSym::callCtors->isUsedInRegularObj &&
-      WasmSym::callCtors->getName() != ctx.arg.entry &&
-      !ctx.arg.exportedSymbols.count(WasmSym::callCtors->getName())) {
+      !ctx.sym.callCtors->isUsedInRegularObj &&
+      ctx.sym.callCtors->getName() != ctx.arg.entry &&
+      !ctx.arg.exportedSymbols.count(ctx.sym.callCtors->getName())) {
     if (Symbol *callDtors =
             handleUndefined("__wasm_call_dtors", "<internal>")) {
       if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) {
@@ -1395,7 +1399,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
              !callDtorsFunc->signature->Returns.empty())) {
           error("__wasm_call_dtors must have no argument or return values");
         }
-        WasmSym::callDtors = callDtorsFunc;
+        ctx.sym.callDtors = callDtorsFunc;
       } else {
         error("__wasm_call_dtors must be a function");
       }
@@ -1488,7 +1492,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   markLive();
 
   // Provide the indirect function table if needed.
-  WasmSym::indirectFunctionTable =
+  ctx.sym.indirectFunctionTable =
       symtab->resolveIndirectFunctionTable(/*required =*/false);
 
   if (errorCount())
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index ccdc92f5c8d71..0e6c4e691be10 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -397,9 +397,9 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
     if (ctx.isPic) {
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
       if (isTLS())
-        writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "tls_base");
+        writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "tls_base");
       else
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
+        writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "memory_base");
       writeU8(os, opcode_ptr_add, "ADD");
     }
 
@@ -422,12 +422,12 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
       }
     } else {
       assert(ctx.isPic);
-      const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
+      const GlobalSymbol *baseSymbol = ctx.sym.memoryBase;
       if (rel.Type == R_WASM_TABLE_INDEX_I32 ||
           rel.Type == R_WASM_TABLE_INDEX_I64)
-        baseSymbol = WasmSym::tableBase;
+        baseSymbol = ctx.sym.tableBase;
       else if (sym->isTLS())
-        baseSymbol = WasmSym::tlsBase;
+        baseSymbol = ctx.sym.tlsBase;
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
       writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
       writeU8(os, opcode_reloc_const, "CONST");
diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp
index 13c7a3d894fe3..2b2cf19f14b30 100644
--- a/lld/wasm/MarkLive.cpp
+++ b/lld/wasm/MarkLive.cpp
@@ -114,8 +114,8 @@ void MarkLive::run() {
     if (sym->isNoStrip() || sym->isExported())
       enqueue(sym);
 
-  if (WasmSym::callDtors)
-    enqueue(WasmSym::callDtors);
+  if (ctx.sym.callDtors)
+    enqueue(ctx.sym.callDtors);
 
   for (const ObjFile *obj : ctx.objectFiles)
     if (obj->isLive()) {
@@ -131,7 +131,7 @@ void MarkLive::run() {
   // If we have any non-discarded init functions, mark `__wasm_call_ctors` as
   // live so that we assign it an index and call it.
   if (isCallCtorsLive())
-    WasmSym::callCtors->markLive();
+    ctx.sym.callCtors->markLive();
 }
 
 void MarkLive::mark() {
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index 95f7ecc29de6b..4142a913c8cbf 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -123,7 +123,7 @@ void DataSection::finalizeContents() {
     if ((segment->initFlags & WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
       if (ctx.isPic && ctx.arg.extendedConst) {
         writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
+        writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
                      "literal (global index)");
         if (segment->startVA) {
           writePtrConst(os, segment->startVA, is64, "offset");
@@ -136,7 +136,7 @@ void DataSection::finalizeContents() {
         if (ctx.isPic) {
           assert(segment->startVA == 0);
           initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
-          initExpr.Inst.Value.Global = WasmSym::memoryBase->getGlobalIndex();
+          initExpr.Inst.Value.Global = ctx.sym.memoryBase->getGlobalIndex();
         } else {
           initExpr = intConst(segment->startVA, is64);
         }
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index a687fd6d6c4ef..92a933ecbb024 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -77,31 +77,6 @@ std::string toString(wasm::Symbol::Kind kind) {
 }
 
 namespace wasm {
-DefinedFunction *WasmSym::callCtors;
-DefinedFunction *WasmSym::callDtors;
-DefinedFunction *WasmSym::initMemory;
-DefinedFunction *WasmSym::applyGlobalRelocs;
-DefinedFunction *WasmSym::applyTLSRelocs;
-DefinedFunction *WasmSym::applyGlobalTLSRelocs;
-DefinedFunction *WasmSym::initTLS;
-DefinedFunction *WasmSym::startFunction;
-DefinedData *WasmSym::dsoHandle;
-DefinedData *WasmSym::dataEnd;
-DefinedData *WasmSym::globalBase;
-DefinedData *WasmSym::heapBase;
-DefinedData *WasmSym::heapEnd;
-DefinedData *WasmSym::initMemoryFlag;
-GlobalSymbol *WasmSym::stackPointer;
-DefinedData *WasmSym::stackLow;
-DefinedData *WasmSym::stackHigh;
-GlobalSymbol *WasmSym::tlsBase;
-GlobalSymbol *WasmSym::tlsSize;
-GlobalSymbol *WasmSym::tlsAlign;
-UndefinedGlobal *WasmSym::tableBase;
-DefinedData *WasmSym::definedTableBase;
-UndefinedGlobal *WasmSym::memoryBase;
-DefinedData *WasmSym::definedMemoryBase;
-TableSymbol *WasmSym::indirectFunctionTable;
 
 WasmSymbolType Symbol::getWasmType() const {
   if (isa<FunctionSymbol>(this))
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index b409fffc50a6c..55ee21939ce07 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -537,105 +537,6 @@ class LazySymbol : public Symbol {
   const WasmSignature *signature = nullptr;
 };
 
-// linker-generated symbols
-struct WasmSym {
-  // __global_base
-  // Symbol marking the start of the global section.
-  static DefinedData *globalBase;
-
-  // __stack_pointer/__stack_low/__stack_high
-  // Global that holds current value of stack pointer and data symbols marking
-  // the start and end of the stack region.  stackPointer is initialized to
-  // stackHigh and grows downwards towards stackLow
-  static GlobalSymbol *stackPointer;
-  static DefinedData *stackLow;
-  static DefinedData *stackHigh;
-
-  // __tls_base
-  // Global that holds the address of the base of the current thread's
-  // TLS block.
-  static GlobalSymbol *tlsBase;
-
-  // __tls_size
-  // Symbol whose value is the size of the TLS block.
-  static GlobalSymbol *tlsSize;
-
-  // __tls_size
-  // Symbol whose value is the alignment of the TLS block.
-  static GlobalSymbol *tlsAlign;
-
-  // __data_end
-  // Symbol marking the end of the data and bss.
-  static DefinedData *dataEnd;
-
-  // __heap_base/__heap_end
-  // Symbols marking the beginning and end of the "heap". It starts at the end
-  // of the data, bss and explicit stack, and extends to the end of the linear
-  // memory allocated by wasm-ld. This region of memory is not used by the
-  // linked code, so it may be used as a backing store for `sbrk` or `malloc`
-  // implementations.
-  static DefinedData *heapBase;
-  static DefinedData *heapEnd;
-
-  // __wasm_init_memory_flag
-  // Symbol whose contents are nonzero iff memory has already been initialized.
-  static DefinedData *initMemoryFlag;
-
-  // __wasm_init_memory
-  // Function that initializes passive data segments during instantiation.
-  static DefinedFunction *initMemory;
-
-  // __wasm_call_ctors
-  // Function that directly calls all ctors in priority order.
-  static DefinedFunction *callCtors;
-
-  // __wasm_call_dtors
-  // Function that calls the libc/etc. cleanup function.
-  static DefinedFunction *callDtors;
-
-  // __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 __wasm_apply_data_relocs but for TLS section.  These must be
-  // delayed until __wasm_init_tls.
-  static DefinedFunction *applyTLSRelocs;
-
-  // __wasm_apply_global_tls_relocs
-  // Like applyGlobalRelocs but for globals that hold TLS addresses.  These
-  // must be delayed until __wasm_init_tls.
-  static DefinedFunction *applyGlobalTLSRelocs;
-
-  // __wasm_init_tls
-  // Function that allocates thread-local storage and initializes it.
-  static DefinedFunction *initTLS;
-
-  // Pointer to the function that is to be used in the start section.
-  // (normally an alias of initMemory, or applyGlobalRelocs).
-  static DefinedFunction *startFunction;
-
-  // __dso_handle
-  // Symbol used in calls to __cxa_atexit to determine current DLL
-  static DefinedData *dsoHandle;
-
-  // __table_base
-  // Used in PIC code for offset of indirect function table
-  static UndefinedGlobal *tableBase;
-  static DefinedData *definedTableBase;
-
-  // __memory_base
-  // Used in PIC code for offset of global data
-  static UndefinedGlobal *memoryBase;
-  static DefinedData *definedMemoryBase;
-
-  // __indirect_function_table
-  // Used as an address space for function pointers, with each function that is
-  // used as a function pointer being allocated a slot.
-  static TableSymbol *indirectFunctionTable;
-};
-
 // A buffer class that is large enough to hold any Symbol-derived
 // object. We allocate memory using this class and instantiate a symbol
 // using the placement new.
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 7fb44b9f0c009..0e2aa57e9048e 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -319,8 +319,8 @@ void TableSection::addTable(InputTable *table) {
   // Some inputs require that the indirect function table be assigned to table
   // number 0.
   if (ctx.legacyFunctionTable &&
-      isa<DefinedTable>(WasmSym::indirectFunctionTable) &&
-      cast<DefinedTable>(WasmSym::indirectFunctionTable)->table == table) {
+      isa<DefinedTable>(ctx.sym.indirectFunctionTable) &&
+      cast<DefinedTable>(ctx.sym.indirectFunctionTable)->table == table) {
     if (out.importSec->getNumImportedTables()) {
       // Alack!  Some other i...
[truncated]

@anutosh491
Copy link
Contributor Author

anutosh491 commented Apr 28, 2025

cc @tstellar

I couldn't get the bot to cherry pick this due to a simple conflict that I had to manually resolved

#134970 (comment)

Hope this is all that's needed from my side !

EDIT: The conflict was due to this #129762
And the changes there have been removed from here. Not sure why that PR hasn't been taken in yet but this one is critical for downstream projects and should be moved in through the upcoming release.

Copy link
Contributor

@vgvassilev vgvassilev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants