[lld] [wasm-ld] Refactor WasmSym from static globals to per-link context (PR #134970)

Anutosh Bhat via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 8 23:17:47 PDT 2025


https://github.com/anutosh491 created https://github.com/llvm/llvm-project/pull/134970

Towards #https://github.com/llvm/llvm-project/issues/134809#issuecomment-2787206873

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


>From 0304b6d9bf481857c8d9bef892a2633ec058fbbd Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Wed, 9 Apr 2025 11:36:45 +0530
Subject: [PATCH] Refactor WasmSym from static globals to per-link context to
 support multiple wasm-ld invocations

---
 lld/wasm/Config.h              |   4 +
 lld/wasm/Driver.cpp            |  62 ++++++------
 lld/wasm/InputChunks.cpp       |  10 +-
 lld/wasm/MarkLive.cpp          |   6 +-
 lld/wasm/OutputSections.cpp    |   4 +-
 lld/wasm/Symbols.cpp           |  26 -----
 lld/wasm/Symbols.h             |  52 +++++-----
 lld/wasm/SyntheticSections.cpp |  28 ++---
 lld/wasm/Writer.cpp            | 180 +++++++++++++++++----------------
 9 files changed, 178 insertions(+), 194 deletions(-)

diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index ffc5b84ca38b0..ad94b2a1386dc 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -32,6 +32,7 @@ class InputTable;
 class InputGlobal;
 class InputFunction;
 class Symbol;
+struct WasmSym;
 
 // For --unresolved-symbols.
 enum class UnresolvedPolicy { ReportError, Warn, Ignore, ImportDynamic };
@@ -141,6 +142,9 @@ struct Ctx {
   llvm::SmallVector<InputGlobal *, 0> syntheticGlobals;
   llvm::SmallVector<InputTable *, 0> syntheticTables;
 
+  // Linker-generated symbols like __wasm_init_memory, __heap_base, etc.
+  std::unique_ptr<WasmSym> wasmSym;
+
   // True if we are creating position-independent code.
   bool isPic = false;
 
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index de976947474e1..b43632d5e420b 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -70,6 +70,8 @@ void Ctx::reset() {
   isPic = false;
   legacyFunctionTable = false;
   emitBssSegments = false;
+  wasmSym.reset();
+  wasmSym = std::make_unique<WasmSym>();
 }
 
 namespace {
@@ -945,14 +947,14 @@ static void createSyntheticSymbols() {
                                                             true};
   static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
                                                             true};
-  WasmSym::callCtors = symtab->addSyntheticFunction(
+  ctx.wasmSym->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.wasmSym->stackPointer =
         createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
                                                      ? &mutableGlobalTypeI64
                                                      : &mutableGlobalTypeI32);
@@ -962,21 +964,21 @@ 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.wasmSym->memoryBase = createUndefinedGlobal("__memory_base", globalType);
+    ctx.wasmSym->tableBase = createUndefinedGlobal("__table_base", globalType);
+    ctx.wasmSym->memoryBase->markLive();
+    ctx.wasmSym->tableBase->markLive();
   } else {
     // For non-PIC code
-    WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true);
-    WasmSym::stackPointer->markLive();
+    ctx.wasmSym->stackPointer = createGlobalVariable("__stack_pointer", true);
+    ctx.wasmSym->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.wasmSym->tlsBase = createGlobalVariable("__tls_base", true);
+    ctx.wasmSym->tlsSize = createGlobalVariable("__tls_size", false);
+    ctx.wasmSym->tlsAlign = createGlobalVariable("__tls_align", false);
+    ctx.wasmSym->initTLS = symtab->addSyntheticFunction(
         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(
             is64 ? i64ArgSignature : i32ArgSignature,
@@ -988,25 +990,25 @@ static void createOptionalSymbols() {
   if (ctx.arg.relocatable)
     return;
 
-  WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
+  ctx.wasmSym->dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
 
   if (!ctx.arg.shared)
-    WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
+    ctx.wasmSym->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.wasmSym->stackLow = symtab->addOptionalDataSymbol("__stack_low");
+    ctx.wasmSym->stackHigh = symtab->addOptionalDataSymbol("__stack_high");
+    ctx.wasmSym->globalBase = symtab->addOptionalDataSymbol("__global_base");
+    ctx.wasmSym->heapBase = symtab->addOptionalDataSymbol("__heap_base");
+    ctx.wasmSym->heapEnd = symtab->addOptionalDataSymbol("__heap_end");
+    ctx.wasmSym->definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
+    ctx.wasmSym->definedTableBase = symtab->addOptionalDataSymbol("__table_base");
   }
 
-  WasmSym::firstPageEnd =
+  ctx.wasmSym->firstPageEnd =
       symtab->addOptionalDataSymbol("__wasm_first_page_end");
-  if (WasmSym::firstPageEnd)
-    WasmSym::firstPageEnd->setVA(ctx.arg.pageSize);
+  if (ctx.wasmSym->firstPageEnd)
+    ctx.wasmSym->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
@@ -1018,7 +1020,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.wasmSym->tlsBase = createOptionalGlobal("__tls_base", false);
 }
 
 static void processStubLibrariesPreLTO() {
@@ -1393,9 +1395,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.wasmSym->callCtors->isUsedInRegularObj &&
+      ctx.wasmSym->callCtors->getName() != ctx.arg.entry &&
+      !ctx.arg.exportedSymbols.count(ctx.wasmSym->callCtors->getName())) {
     if (Symbol *callDtors =
             handleUndefined("__wasm_call_dtors", "<internal>")) {
       if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) {
@@ -1404,7 +1406,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.wasmSym->callDtors = callDtorsFunc;
       } else {
         error("__wasm_call_dtors must be a function");
       }
@@ -1497,7 +1499,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   markLive();
 
   // Provide the indirect function table if needed.
-  WasmSym::indirectFunctionTable =
+  ctx.wasmSym->indirectFunctionTable =
       symtab->resolveIndirectFunctionTable(/*required =*/false);
 
   if (errorCount())
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index 3668697382238..ac89f313ca4b5 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -411,9 +411,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.wasmSym->tlsBase->getGlobalIndex(), "tls_base");
       else
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
+        writeUleb128(os, ctx.wasmSym->memoryBase->getGlobalIndex(), "memory_base");
       writeU8(os, opcode_ptr_add, "ADD");
     }
 
@@ -436,12 +436,12 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
       }
     } else {
       assert(ctx.isPic);
-      const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
+      const GlobalSymbol* baseSymbol = ctx.wasmSym->memoryBase;
       if (rel.Type == R_WASM_TABLE_INDEX_I32 ||
           rel.Type == R_WASM_TABLE_INDEX_I64)
-        baseSymbol = WasmSym::tableBase;
+        baseSymbol = ctx.wasmSym->tableBase;
       else if (sym->isTLS())
-        baseSymbol = WasmSym::tlsBase;
+        baseSymbol = ctx.wasmSym->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..40b105821056d 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.wasmSym->callDtors)
+    enqueue(ctx.wasmSym->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.wasmSym->callCtors->markLive();
 }
 
 void MarkLive::mark() {
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index 5038cd8ea965b..1864e4532fc36 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -124,7 +124,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.wasmSym->memoryBase->getGlobalIndex(),
                      "literal (global index)");
         if (segment->startVA) {
           writePtrConst(os, segment->startVA, is64, "offset");
@@ -137,7 +137,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.wasmSym->memoryBase->getGlobalIndex();
         } else {
           initExpr = intConst(segment->startVA, is64);
         }
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index af5ecf4f38f73..f2040441e6257 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -77,32 +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;
-DefinedData *WasmSym::firstPageEnd;
-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 03a74da7230d0..4197fc7a17b14 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -541,32 +541,32 @@ class LazySymbol : public Symbol {
 struct WasmSym {
   // __global_base
   // Symbol marking the start of the global section.
-  static DefinedData *globalBase;
+  DefinedData *globalBase = nullptr;
 
   // __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;
+  GlobalSymbol *stackPointer = nullptr;
+  DefinedData *stackLow = nullptr;
+  DefinedData *stackHigh = nullptr;
 
   // __tls_base
   // Global that holds the address of the base of the current thread's
   // TLS block.
-  static GlobalSymbol *tlsBase;
+  GlobalSymbol *tlsBase = nullptr;
 
   // __tls_size
   // Symbol whose value is the size of the TLS block.
-  static GlobalSymbol *tlsSize;
+  GlobalSymbol *tlsSize = nullptr;
 
   // __tls_size
   // Symbol whose value is the alignment of the TLS block.
-  static GlobalSymbol *tlsAlign;
+  GlobalSymbol *tlsAlign = nullptr;
 
   // __data_end
   // Symbol marking the end of the data and bss.
-  static DefinedData *dataEnd;
+  DefinedData *dataEnd = nullptr;
 
   // __heap_base/__heap_end
   // Symbols marking the beginning and end of the "heap". It starts at the end
@@ -574,70 +574,70 @@ struct WasmSym {
   // 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;
+  DefinedData *heapBase = nullptr;
+  DefinedData *heapEnd = nullptr;
 
   // __wasm_first_page_end
   // A symbol whose address is the end of the first page in memory (if any).
-  static DefinedData *firstPageEnd;
+  DefinedData *firstPageEnd = nullptr;
 
   // __wasm_init_memory_flag
   // Symbol whose contents are nonzero iff memory has already been initialized.
-  static DefinedData *initMemoryFlag;
+  DefinedData *initMemoryFlag = nullptr;
 
   // __wasm_init_memory
   // Function that initializes passive data segments during instantiation.
-  static DefinedFunction *initMemory;
+  DefinedFunction *initMemory = nullptr;
 
   // __wasm_call_ctors
   // Function that directly calls all ctors in priority order.
-  static DefinedFunction *callCtors;
+  DefinedFunction *callCtors = nullptr;
 
   // __wasm_call_dtors
   // Function that calls the libc/etc. cleanup function.
-  static DefinedFunction *callDtors;
+  DefinedFunction *callDtors = nullptr;
 
   // __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;
+  DefinedFunction *applyGlobalRelocs = nullptr;
 
   // __wasm_apply_tls_relocs
   // Like __wasm_apply_data_relocs but for TLS section.  These must be
   // delayed until __wasm_init_tls.
-  static DefinedFunction *applyTLSRelocs;
+  DefinedFunction *applyTLSRelocs = nullptr;
 
   // __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;
+  DefinedFunction *applyGlobalTLSRelocs = nullptr;
 
   // __wasm_init_tls
   // Function that allocates thread-local storage and initializes it.
-  static DefinedFunction *initTLS;
+  DefinedFunction *initTLS = nullptr;
 
   // Pointer to the function that is to be used in the start section.
   // (normally an alias of initMemory, or applyGlobalRelocs).
-  static DefinedFunction *startFunction;
+  DefinedFunction *startFunction = nullptr;
 
   // __dso_handle
   // Symbol used in calls to __cxa_atexit to determine current DLL
-  static DefinedData *dsoHandle;
+  DefinedData *dsoHandle = nullptr;
 
   // __table_base
   // Used in PIC code for offset of indirect function table
-  static UndefinedGlobal *tableBase;
-  static DefinedData *definedTableBase;
+  UndefinedGlobal *tableBase = nullptr;
+  DefinedData *definedTableBase = nullptr;
 
   // __memory_base
   // Used in PIC code for offset of global data
-  static UndefinedGlobal *memoryBase;
-  static DefinedData *definedMemoryBase;
+  UndefinedGlobal *memoryBase = nullptr;
+  DefinedData *definedMemoryBase = nullptr;
 
   // __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;
+  TableSymbol *indirectFunctionTable = nullptr;
 };
 
 // A buffer class that is large enough to hold any Symbol-derived
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index c88a6f742c35e..ce71e8f915fef 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -328,8 +328,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.wasmSym->indirectFunctionTable) &&
+      cast<DefinedTable>(ctx.wasmSym->indirectFunctionTable)->table == table) {
     if (out.importSec->getNumImportedTables()) {
       // Alack!  Some other input imported a table, meaning that we are unable
       // to assign table number 0 to the indirect function table.
@@ -408,8 +408,8 @@ void GlobalSection::assignIndexes() {
 }
 
 static void ensureIndirectFunctionTable() {
-  if (!WasmSym::indirectFunctionTable)
-    WasmSym::indirectFunctionTable =
+  if (!ctx.wasmSym->indirectFunctionTable)
+    ctx.wasmSym->indirectFunctionTable =
         symtab->resolveIndirectFunctionTable(/*required =*/true);
 }
 
@@ -443,9 +443,9 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
       // Get __memory_base
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
       if (sym->isTLS())
-        writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "__tls_base");
+        writeUleb128(os, ctx.wasmSym->tlsBase->getGlobalIndex(), "__tls_base");
       else
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
+        writeUleb128(os, ctx.wasmSym->memoryBase->getGlobalIndex(),
                      "__memory_base");
 
       // Add the virtual address of the data symbol
@@ -456,7 +456,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
         continue;
       // Get __table_base
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
-      writeUleb128(os, WasmSym::tableBase->getGlobalIndex(), "__table_base");
+      writeUleb128(os, ctx.wasmSym->tableBase->getGlobalIndex(), "__table_base");
 
       // Add the table index to __table_base
       writeU8(os, opcode_ptr_const, "CONST");
@@ -503,13 +503,13 @@ void GlobalSection::writeBody() {
     if (ctx.arg.extendedConst && ctx.isPic) {
       if (auto *d = dyn_cast<DefinedData>(sym)) {
         if (!sym->isTLS()) {
-          globalIdx = WasmSym::memoryBase->getGlobalIndex();
+          globalIdx = ctx.wasmSym->memoryBase->getGlobalIndex();
           offset = d->getVA();
           useExtendedConst = true;
         }
       } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
         if (!sym->isStub) {
-          globalIdx = WasmSym::tableBase->getGlobalIndex();
+          globalIdx = ctx.wasmSym->tableBase->getGlobalIndex();
           offset = f->getTableIndex();
           useExtendedConst = true;
         }
@@ -564,12 +564,12 @@ void ExportSection::writeBody() {
 }
 
 bool StartSection::isNeeded() const {
-  return WasmSym::startFunction != nullptr;
+  return ctx.wasmSym->startFunction != nullptr;
 }
 
 void StartSection::writeBody() {
   raw_ostream &os = bodyOutputStream;
-  writeUleb128(os, WasmSym::startFunction->getFunctionIndex(),
+  writeUleb128(os, ctx.wasmSym->startFunction->getFunctionIndex(),
                "function index");
 }
 
@@ -586,9 +586,9 @@ void ElemSection::addEntry(FunctionSymbol *sym) {
 void ElemSection::writeBody() {
   raw_ostream &os = bodyOutputStream;
 
-  assert(WasmSym::indirectFunctionTable);
+  assert(ctx.wasmSym->indirectFunctionTable);
   writeUleb128(os, 1, "segment count");
-  uint32_t tableNumber = WasmSym::indirectFunctionTable->getTableNumber();
+  uint32_t tableNumber = ctx.wasmSym->indirectFunctionTable->getTableNumber();
   uint32_t flags = 0;
   if (tableNumber)
     flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
@@ -600,7 +600,7 @@ void ElemSection::writeBody() {
   initExpr.Extended = false;
   if (ctx.isPic) {
     initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
-    initExpr.Inst.Value.Global = WasmSym::tableBase->getGlobalIndex();
+    initExpr.Inst.Value.Global = ctx.wasmSym->tableBase->getGlobalIndex();
   } else {
     bool is64 = ctx.arg.is64.value_or(false);
     initExpr = intConst(ctx.arg.tableBase, is64);
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index f4ba182ee5079..3ab68339f2ce5 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -346,16 +346,16 @@ void Writer::layoutMemory() {
     if (ctx.arg.relocatable || ctx.isPic)
       return;
     memoryPtr = alignTo(memoryPtr, stackAlignment);
-    if (WasmSym::stackLow)
-      WasmSym::stackLow->setVA(memoryPtr);
+    if (ctx.wasmSym->stackLow)
+      ctx.wasmSym->stackLow->setVA(memoryPtr);
     if (ctx.arg.zStackSize != alignTo(ctx.arg.zStackSize, stackAlignment))
       error("stack size must be " + Twine(stackAlignment) + "-byte aligned");
     log("mem: stack size  = " + Twine(ctx.arg.zStackSize));
     log("mem: stack base  = " + Twine(memoryPtr));
     memoryPtr += ctx.arg.zStackSize;
-    setGlobalPtr(cast<DefinedGlobal>(WasmSym::stackPointer), memoryPtr);
-    if (WasmSym::stackHigh)
-      WasmSym::stackHigh->setVA(memoryPtr);
+    setGlobalPtr(cast<DefinedGlobal>(ctx.wasmSym->stackPointer), memoryPtr);
+    if (ctx.wasmSym->stackHigh)
+      ctx.wasmSym->stackHigh->setVA(memoryPtr);
     log("mem: stack top   = " + Twine(memoryPtr));
   };
 
@@ -373,15 +373,15 @@ void Writer::layoutMemory() {
   }
 
   log("mem: global base = " + Twine(memoryPtr));
-  if (WasmSym::globalBase)
-    WasmSym::globalBase->setVA(memoryPtr);
+  if (ctx.wasmSym->globalBase)
+    ctx.wasmSym->globalBase->setVA(memoryPtr);
 
   uint64_t dataStart = memoryPtr;
 
   // Arbitrarily set __dso_handle handle to point to the start of the data
   // segments.
-  if (WasmSym::dsoHandle)
-    WasmSym::dsoHandle->setVA(dataStart);
+  if (ctx.wasmSym->dsoHandle)
+    ctx.wasmSym->dsoHandle->setVA(dataStart);
 
   out.dylinkSec->memAlign = 0;
   for (OutputSegment *seg : segments) {
@@ -392,16 +392,16 @@ void Writer::layoutMemory() {
                 memoryPtr, seg->size, seg->alignment));
 
     if (!ctx.arg.relocatable && seg->isTLS()) {
-      if (WasmSym::tlsSize) {
-        auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
+      if (ctx.wasmSym->tlsSize) {
+        auto *tlsSize = cast<DefinedGlobal>(ctx.wasmSym->tlsSize);
         setGlobalPtr(tlsSize, seg->size);
       }
-      if (WasmSym::tlsAlign) {
-        auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign);
+      if (ctx.wasmSym->tlsAlign) {
+        auto *tlsAlign = cast<DefinedGlobal>(ctx.wasmSym->tlsAlign);
         setGlobalPtr(tlsAlign, int64_t{1} << seg->alignment);
       }
-      if (!ctx.arg.sharedMemory && WasmSym::tlsBase) {
-        auto *tlsBase = cast<DefinedGlobal>(WasmSym::tlsBase);
+      if (!ctx.arg.sharedMemory && ctx.wasmSym->tlsBase) {
+        auto *tlsBase = cast<DefinedGlobal>(ctx.wasmSym->tlsBase);
         setGlobalPtr(tlsBase, memoryPtr);
       }
     }
@@ -412,17 +412,17 @@ void Writer::layoutMemory() {
   // Make space for the memory initialization flag
   if (ctx.arg.sharedMemory && hasPassiveInitializedSegments()) {
     memoryPtr = alignTo(memoryPtr, 4);
-    WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol(
+    ctx.wasmSym->initMemoryFlag = symtab->addSyntheticDataSymbol(
         "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
-    WasmSym::initMemoryFlag->markLive();
-    WasmSym::initMemoryFlag->setVA(memoryPtr);
+    ctx.wasmSym->initMemoryFlag->markLive();
+    ctx.wasmSym->initMemoryFlag->setVA(memoryPtr);
     log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
                 "__wasm_init_memory_flag", memoryPtr, 4, 4));
     memoryPtr += 4;
   }
 
-  if (WasmSym::dataEnd)
-    WasmSym::dataEnd->setVA(memoryPtr);
+  if (ctx.wasmSym->dataEnd)
+    ctx.wasmSym->dataEnd->setVA(memoryPtr);
 
   uint64_t staticDataSize = memoryPtr - dataStart;
   log("mem: static data = " + Twine(staticDataSize));
@@ -432,7 +432,7 @@ void Writer::layoutMemory() {
   if (!ctx.arg.stackFirst)
     placeStack();
 
-  if (WasmSym::heapBase) {
+  if (ctx.wasmSym->heapBase) {
     // Set `__heap_base` to follow the end of the stack or global data. The
     // fact that this comes last means that a malloc/brk implementation can
     // grow the heap at runtime.
@@ -440,7 +440,7 @@ void Writer::layoutMemory() {
     // __heap_base to be aligned already.
     memoryPtr = alignTo(memoryPtr, heapAlignment);
     log("mem: heap base   = " + Twine(memoryPtr));
-    WasmSym::heapBase->setVA(memoryPtr);
+    ctx.wasmSym->heapBase->setVA(memoryPtr);
   }
 
   uint64_t maxMemorySetting = 1ULL << 32;
@@ -474,12 +474,12 @@ void Writer::layoutMemory() {
   out.memorySec->numMemoryPages = memoryPtr / ctx.arg.pageSize;
   log("mem: total pages = " + Twine(out.memorySec->numMemoryPages));
 
-  if (WasmSym::heapEnd) {
+  if (ctx.wasmSym->heapEnd) {
     // Set `__heap_end` to follow the end of the statically allocated linear
     // memory. The fact that this comes last means that a malloc/brk
     // implementation can grow the heap at runtime.
     log("mem: heap end    = " + Twine(memoryPtr));
-    WasmSym::heapEnd->setVA(memoryPtr);
+    ctx.wasmSym->heapEnd->setVA(memoryPtr);
   }
 
   uint64_t maxMemory = 0;
@@ -761,14 +761,14 @@ void Writer::calculateImports() {
   // Some inputs require that the indirect function table be assigned to table
   // number 0, so if it is present and is an import, allocate it before any
   // other tables.
-  if (WasmSym::indirectFunctionTable &&
-      shouldImport(WasmSym::indirectFunctionTable))
-    out.importSec->addImport(WasmSym::indirectFunctionTable);
+  if (ctx.wasmSym->indirectFunctionTable &&
+      shouldImport(ctx.wasmSym->indirectFunctionTable))
+    out.importSec->addImport(ctx.wasmSym->indirectFunctionTable);
 
   for (Symbol *sym : symtab->symbols()) {
     if (!shouldImport(sym))
       continue;
-    if (sym == WasmSym::indirectFunctionTable)
+    if (sym == ctx.wasmSym->indirectFunctionTable)
       continue;
     LLVM_DEBUG(dbgs() << "import: " << sym->getName() << "\n");
     out.importSec->addImport(sym);
@@ -882,7 +882,7 @@ void Writer::createCommandExportWrappers() {
 
   // If there are no ctors and there's no libc `__wasm_call_dtors` to
   // call, don't wrap the exports.
-  if (initFunctions.empty() && WasmSym::callDtors == nullptr)
+  if (initFunctions.empty() && ctx.wasmSym->callDtors == nullptr)
     return;
 
   std::vector<DefinedFunction *> toWrap;
@@ -922,27 +922,27 @@ void Writer::createCommandExportWrappers() {
 }
 
 static void finalizeIndirectFunctionTable() {
-  if (!WasmSym::indirectFunctionTable)
+  if (!ctx.wasmSym->indirectFunctionTable)
     return;
 
-  if (shouldImport(WasmSym::indirectFunctionTable) &&
-      !WasmSym::indirectFunctionTable->hasTableNumber()) {
+  if (shouldImport(ctx.wasmSym->indirectFunctionTable) &&
+      !ctx.wasmSym->indirectFunctionTable->hasTableNumber()) {
     // Processing -Bsymbolic relocations resulted in a late requirement that the
     // indirect function table be present, and we are running in --import-table
     // mode.  Add the table now to the imports section.  Otherwise it will be
     // added to the tables section later in assignIndexes.
-    out.importSec->addImport(WasmSym::indirectFunctionTable);
+    out.importSec->addImport(ctx.wasmSym->indirectFunctionTable);
   }
 
   uint32_t tableSize = ctx.arg.tableBase + out.elemSec->numEntries();
   WasmLimits limits = {0, tableSize, 0, 0};
-  if (WasmSym::indirectFunctionTable->isDefined() && !ctx.arg.growableTable) {
+  if (ctx.wasmSym->indirectFunctionTable->isDefined() && !ctx.arg.growableTable) {
     limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
     limits.Maximum = limits.Minimum;
   }
   if (ctx.arg.is64.value_or(false))
     limits.Flags |= WASM_LIMITS_FLAG_IS_64;
-  WasmSym::indirectFunctionTable->setLimits(limits);
+  ctx.wasmSym->indirectFunctionTable->setLimits(limits);
 }
 
 static void scanRelocations() {
@@ -1150,26 +1150,26 @@ void Writer::createSyntheticInitFunctions() {
   // We also initialize bss segments (using memory.fill) as part of this
   // function.
   if (hasPassiveInitializedSegments()) {
-    WasmSym::initMemory = symtab->addSyntheticFunction(
+    ctx.wasmSym->initMemory = symtab->addSyntheticFunction(
         "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
-    WasmSym::initMemory->markLive();
+    ctx.wasmSym->initMemory->markLive();
     if (ctx.arg.sharedMemory) {
       // This global is assigned during  __wasm_init_memory in the shared memory
       // case.
-      WasmSym::tlsBase->markLive();
+      ctx.wasmSym->tlsBase->markLive();
     }
   }
 
   if (ctx.arg.sharedMemory) {
     if (out.globalSec->needsTLSRelocations()) {
-      WasmSym::applyGlobalTLSRelocs = symtab->addSyntheticFunction(
+      ctx.wasmSym->applyGlobalTLSRelocs = symtab->addSyntheticFunction(
           "__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
           make<SyntheticFunction>(nullSignature,
                                   "__wasm_apply_global_tls_relocs"));
-      WasmSym::applyGlobalTLSRelocs->markLive();
+      ctx.wasmSym->applyGlobalTLSRelocs->markLive();
       // TLS relocations depend on  the __tls_base symbols
-      WasmSym::tlsBase->markLive();
+      ctx.wasmSym->tlsBase->markLive();
     }
 
     auto hasTLSRelocs = [](const OutputSegment *segment) {
@@ -1180,40 +1180,40 @@ void Writer::createSyntheticInitFunctions() {
       return false;
     };
     if (llvm::any_of(segments, hasTLSRelocs)) {
-      WasmSym::applyTLSRelocs = symtab->addSyntheticFunction(
+      ctx.wasmSym->applyTLSRelocs = symtab->addSyntheticFunction(
           "__wasm_apply_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
           make<SyntheticFunction>(nullSignature,
                                   "__wasm_apply_tls_relocs"));
-      WasmSym::applyTLSRelocs->markLive();
+      ctx.wasmSym->applyTLSRelocs->markLive();
     }
   }
 
   if (ctx.isPic && out.globalSec->needsRelocations()) {
-    WasmSym::applyGlobalRelocs = symtab->addSyntheticFunction(
+    ctx.wasmSym->applyGlobalRelocs = symtab->addSyntheticFunction(
         "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(nullSignature, "__wasm_apply_global_relocs"));
-    WasmSym::applyGlobalRelocs->markLive();
+    ctx.wasmSym->applyGlobalRelocs->markLive();
   }
 
   // If there is only one start function we can just use that function
   // itself as the Wasm start function, otherwise we need to synthesize
   // a new function to call them in sequence.
-  if (WasmSym::applyGlobalRelocs && WasmSym::initMemory) {
-    WasmSym::startFunction = symtab->addSyntheticFunction(
+  if (ctx.wasmSym->applyGlobalRelocs && ctx.wasmSym->initMemory) {
+    ctx.wasmSym->startFunction = symtab->addSyntheticFunction(
         "__wasm_start", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(nullSignature, "__wasm_start"));
-    WasmSym::startFunction->markLive();
+    ctx.wasmSym->startFunction->markLive();
   }
 }
 
 void Writer::createInitMemoryFunction() {
   LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
-  assert(WasmSym::initMemory);
+  assert(ctx.wasmSym->initMemory);
   assert(hasPassiveInitializedSegments());
   uint64_t flagAddress;
   if (ctx.arg.sharedMemory) {
-    assert(WasmSym::initMemoryFlag);
-    flagAddress = WasmSym::initMemoryFlag->getVA();
+    assert(ctx.wasmSym->initMemoryFlag);
+    flagAddress = ctx.wasmSym->initMemoryFlag->getVA();
   }
   bool is64 = ctx.arg.is64.value_or(false);
   std::string bodyContent;
@@ -1286,7 +1286,7 @@ void Writer::createInitMemoryFunction() {
         writeUleb128(os, 2, "local count");
         writeU8(os, is64 ? WASM_TYPE_I64 : WASM_TYPE_I32, "address type");
         writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
-        writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
+        writeUleb128(os, ctx.wasmSym->memoryBase->getGlobalIndex(), "memory_base");
         writePtrConst(os, flagAddress, is64, "flag address");
         writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, "add");
         writeU8(os, WASM_OPCODE_LOCAL_SET, "local.set");
@@ -1333,7 +1333,7 @@ void Writer::createInitMemoryFunction() {
         writePtrConst(os, s->startVA, is64, "destination address");
         if (ctx.isPic) {
           writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
-          writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
+          writeUleb128(os, ctx.wasmSym->memoryBase->getGlobalIndex(),
                        "__memory_base");
           writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD,
                   "i32.add");
@@ -1351,7 +1351,7 @@ void Writer::createInitMemoryFunction() {
             writePtrConst(os, s->startVA, is64, "destination address");
           }
           writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET");
-          writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(),
+          writeUleb128(os, ctx.wasmSym->tlsBase->getGlobalIndex(),
                        "__tls_base");
           if (ctx.isPic) {
             writeU8(os, WASM_OPCODE_LOCAL_GET, "local.tee");
@@ -1428,30 +1428,30 @@ void Writer::createInitMemoryFunction() {
     writeU8(os, WASM_OPCODE_END, "END");
   }
 
-  createFunction(WasmSym::initMemory, bodyContent);
+  createFunction(ctx.wasmSym->initMemory, bodyContent);
 }
 
 void Writer::createStartFunction() {
   // If the start function exists when we have more than one function to call.
-  if (WasmSym::initMemory && WasmSym::applyGlobalRelocs) {
-    assert(WasmSym::startFunction);
+  if (ctx.wasmSym->initMemory && ctx.wasmSym->applyGlobalRelocs) {
+    assert(ctx.wasmSym->startFunction);
     std::string bodyContent;
     {
       raw_string_ostream os(bodyContent);
       writeUleb128(os, 0, "num locals");
       writeU8(os, WASM_OPCODE_CALL, "CALL");
-      writeUleb128(os, WasmSym::applyGlobalRelocs->getFunctionIndex(),
+      writeUleb128(os, ctx.wasmSym->applyGlobalRelocs->getFunctionIndex(),
                    "function index");
       writeU8(os, WASM_OPCODE_CALL, "CALL");
-      writeUleb128(os, WasmSym::initMemory->getFunctionIndex(),
+      writeUleb128(os, ctx.wasmSym->initMemory->getFunctionIndex(),
                    "function index");
       writeU8(os, WASM_OPCODE_END, "END");
     }
-    createFunction(WasmSym::startFunction, bodyContent);
-  } else if (WasmSym::initMemory) {
-    WasmSym::startFunction = WasmSym::initMemory;
-  } else if (WasmSym::applyGlobalRelocs) {
-    WasmSym::startFunction = WasmSym::applyGlobalRelocs;
+    createFunction(ctx.wasmSym->startFunction, bodyContent);
+  } else if (ctx.wasmSym->initMemory) {
+    ctx.wasmSym->startFunction = ctx.wasmSym->initMemory;
+  } else if (ctx.wasmSym->applyGlobalRelocs) {
+    ctx.wasmSym->startFunction = ctx.wasmSym->applyGlobalRelocs;
   }
 }
 
@@ -1505,7 +1505,7 @@ void Writer::createApplyTLSRelocationsFunction() {
     writeU8(os, WASM_OPCODE_END, "END");
   }
 
-  createFunction(WasmSym::applyTLSRelocs, bodyContent);
+  createFunction(ctx.wasmSym->applyTLSRelocs, bodyContent);
 }
 
 // Similar to createApplyDataRelocationsFunction but generates relocation code
@@ -1521,7 +1521,7 @@ void Writer::createApplyGlobalRelocationsFunction() {
     writeU8(os, WASM_OPCODE_END, "END");
   }
 
-  createFunction(WasmSym::applyGlobalRelocs, bodyContent);
+  createFunction(ctx.wasmSym->applyGlobalRelocs, bodyContent);
 }
 
 // Similar to createApplyGlobalRelocationsFunction but for
@@ -1537,7 +1537,7 @@ void Writer::createApplyGlobalTLSRelocationsFunction() {
     writeU8(os, WASM_OPCODE_END, "END");
   }
 
-  createFunction(WasmSym::applyGlobalTLSRelocs, bodyContent);
+  createFunction(ctx.wasmSym->applyGlobalTLSRelocs, bodyContent);
 }
 
 // Create synthetic "__wasm_call_ctors" function based on ctor functions
@@ -1545,7 +1545,7 @@ void Writer::createApplyGlobalTLSRelocationsFunction() {
 void Writer::createCallCtorsFunction() {
   // If __wasm_call_ctors isn't referenced, there aren't any ctors, don't
   // define the `__wasm_call_ctors` function.
-  if (!WasmSym::callCtors->isLive() && initFunctions.empty())
+  if (!ctx.wasmSym->callCtors->isLive() && initFunctions.empty())
     return;
 
   // First write the body's contents to a string.
@@ -1566,7 +1566,7 @@ void Writer::createCallCtorsFunction() {
     writeU8(os, WASM_OPCODE_END, "END");
   }
 
-  createFunction(WasmSym::callCtors, bodyContent);
+  createFunction(ctx.wasmSym->callCtors, bodyContent);
 }
 
 // Create a wrapper around a function export which calls the
@@ -1581,9 +1581,9 @@ void Writer::createCommandExportWrapper(uint32_t functionIndex,
 
     // Call `__wasm_call_ctors` which call static constructors (and
     // applies any runtime relocations in Emscripten-style PIC mode)
-    if (WasmSym::callCtors->isLive()) {
+    if (ctx.wasmSym->callCtors->isLive()) {
       writeU8(os, WASM_OPCODE_CALL, "CALL");
-      writeUleb128(os, WasmSym::callCtors->getFunctionIndex(),
+      writeUleb128(os, ctx.wasmSym->callCtors->getFunctionIndex(),
                    "function index");
     }
 
@@ -1596,7 +1596,7 @@ void Writer::createCommandExportWrapper(uint32_t functionIndex,
     writeUleb128(os, functionIndex, "function index");
 
     // Call the function that calls the destructors.
-    if (DefinedFunction *callDtors = WasmSym::callDtors) {
+    if (DefinedFunction *callDtors = ctx.wasmSym->callDtors) {
       writeU8(os, WASM_OPCODE_CALL, "CALL");
       writeUleb128(os, callDtors->getFunctionIndex(), "function index");
     }
@@ -1627,7 +1627,7 @@ void Writer::createInitTLSFunction() {
       writeUleb128(os, 0, "local index");
 
       writeU8(os, WASM_OPCODE_GLOBAL_SET, "global.set");
-      writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "global index");
+      writeUleb128(os, ctx.wasmSym->tlsBase->getGlobalIndex(), "global index");
 
       // FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend op.
       writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
@@ -1643,28 +1643,28 @@ void Writer::createInitTLSFunction() {
       writeU8(os, 0, "memory index immediate");
     }
 
-    if (WasmSym::applyTLSRelocs) {
+    if (ctx.wasmSym->applyTLSRelocs) {
       writeU8(os, WASM_OPCODE_CALL, "CALL");
-      writeUleb128(os, WasmSym::applyTLSRelocs->getFunctionIndex(),
+      writeUleb128(os, ctx.wasmSym->applyTLSRelocs->getFunctionIndex(),
                    "function index");
     }
 
-    if (WasmSym::applyGlobalTLSRelocs) {
+    if (ctx.wasmSym->applyGlobalTLSRelocs) {
       writeU8(os, WASM_OPCODE_CALL, "CALL");
-      writeUleb128(os, WasmSym::applyGlobalTLSRelocs->getFunctionIndex(),
+      writeUleb128(os, ctx.wasmSym->applyGlobalTLSRelocs->getFunctionIndex(),
                    "function index");
     }
     writeU8(os, WASM_OPCODE_END, "end function");
   }
 
-  createFunction(WasmSym::initTLS, bodyContent);
+  createFunction(ctx.wasmSym->initTLS, bodyContent);
 }
 
 // Populate InitFunctions vector with init functions from all input objects.
 // This is then used either when creating the output linking section or to
 // synthesize the "__wasm_call_ctors" function.
 void Writer::calculateInitFunctions() {
-  if (!ctx.arg.relocatable && !WasmSym::callCtors->isLive())
+  if (!ctx.arg.relocatable && !ctx.wasmSym->callCtors->isLive())
     return;
 
   for (ObjFile *file : ctx.objectFiles) {
@@ -1715,8 +1715,8 @@ void Writer::createSyntheticSectionsPostLayout() {
 void Writer::run() {
   // For PIC code the table base is assigned dynamically by the loader.
   // For non-PIC, we start at 1 so that accessing table index 0 always traps.
-  if (!ctx.isPic && WasmSym::definedTableBase)
-    WasmSym::definedTableBase->setVA(ctx.arg.tableBase);
+  if (!ctx.isPic && ctx.wasmSym->definedTableBase)
+    ctx.wasmSym->definedTableBase->setVA(ctx.arg.tableBase);
 
   log("-- createOutputSegments");
   createOutputSegments();
@@ -1784,14 +1784,18 @@ void Writer::run() {
 
   if (!ctx.arg.relocatable) {
     // Create linker synthesized functions
-    if (WasmSym::applyGlobalRelocs)
+    if (ctx.wasmSym->applyGlobalRelocs) {
       createApplyGlobalRelocationsFunction();
-    if (WasmSym::applyTLSRelocs)
+    }
+    if (ctx.wasmSym->applyTLSRelocs) {
       createApplyTLSRelocationsFunction();
-    if (WasmSym::applyGlobalTLSRelocs)
+    }
+    if (ctx.wasmSym->applyGlobalTLSRelocs) {
       createApplyGlobalTLSRelocationsFunction();
-    if (WasmSym::initMemory)
+    }
+    if (ctx.wasmSym->initMemory) {
       createInitMemoryFunction();
+    }
     createStartFunction();
 
     createCallCtorsFunction();
@@ -1802,14 +1806,14 @@ void Writer::run() {
     // the input objects or an explicit export from the command-line, we
     // assume ctors and dtors are taken care of already.
     if (!ctx.arg.relocatable && !ctx.isPic &&
-        !WasmSym::callCtors->isUsedInRegularObj &&
-        !WasmSym::callCtors->isExported()) {
+        !ctx.wasmSym->callCtors->isUsedInRegularObj &&
+        !ctx.wasmSym->callCtors->isExported()) {
       log("-- createCommandExportWrappers");
       createCommandExportWrappers();
     }
   }
 
-  if (WasmSym::initTLS && WasmSym::initTLS->isLive()) {
+  if (ctx.wasmSym->initTLS && ctx.wasmSym->initTLS->isLive()) {
     log("-- createInitTLSFunction");
     createInitTLSFunction();
   }



More information about the llvm-commits mailing list