[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
Wed Apr 9 12:56:59 PDT 2025
https://github.com/anutosh491 updated https://github.com/llvm/llvm-project/pull/134970
>From ca2d6950c6dbd8a3acc5b2b875fbc5a8032a29ad Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Wed, 9 Apr 2025 11:36:45 +0530
Subject: [PATCH 1/4] Refactor WasmSym from static globals to per-link context
to support multiple wasm-ld invocations
---
lld/wasm/Config.h | 4 +
lld/wasm/Driver.cpp | 69 ++++++------
lld/wasm/InputChunks.cpp | 11 +-
lld/wasm/MarkLive.cpp | 6 +-
lld/wasm/OutputSections.cpp | 5 +-
lld/wasm/Symbols.cpp | 26 -----
lld/wasm/Symbols.h | 52 ++++-----
lld/wasm/SyntheticSections.cpp | 29 +++---
lld/wasm/Writer.cpp | 185 +++++++++++++++++----------------
9 files changed, 188 insertions(+), 199 deletions(-)
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index ffc5b84ca38b0..1ee2568784a89 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.
+ 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 de976947474e1..9a1c047197c6e 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 {
@@ -945,14 +946,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);
@@ -962,25 +963,25 @@ 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"));
}
}
@@ -988,25 +989,27 @@ 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");
}
- WasmSym::firstPageEnd =
+ ctx.sym.firstPageEnd =
symtab->addOptionalDataSymbol("__wasm_first_page_end");
- if (WasmSym::firstPageEnd)
- WasmSym::firstPageEnd->setVA(ctx.arg.pageSize);
+ 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
@@ -1018,7 +1021,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() {
@@ -1393,9 +1396,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)) {
@@ -1404,7 +1407,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");
}
@@ -1497,7 +1500,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 3668697382238..cd436d5a0eab8 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -411,9 +411,10 @@ 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");
}
@@ -436,12 +437,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 5038cd8ea965b..0aaa03770fcf9 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.sym.memoryBase->getGlobalIndex(),
"literal (global index)");
if (segment->startVA) {
writePtrConst(os, segment->startVA, is64, "offset");
@@ -137,7 +137,8 @@ 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 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..cd1f9a03a6a82 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;
// __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;
+ DefinedData *stackLow;
+ DefinedData *stackHigh;
// __tls_base
// Global that holds the address of the base of the current thread's
// TLS block.
- static GlobalSymbol *tlsBase;
+ GlobalSymbol *tlsBase;
// __tls_size
// Symbol whose value is the size of the TLS block.
- static GlobalSymbol *tlsSize;
+ GlobalSymbol *tlsSize;
// __tls_size
// Symbol whose value is the alignment of the TLS block.
- static GlobalSymbol *tlsAlign;
+ GlobalSymbol *tlsAlign;
// __data_end
// Symbol marking the end of the data and bss.
- static DefinedData *dataEnd;
+ DefinedData *dataEnd;
// __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;
+ DefinedData *heapEnd;
// __wasm_first_page_end
// A symbol whose address is the end of the first page in memory (if any).
- static DefinedData *firstPageEnd;
+ DefinedData *firstPageEnd;
// __wasm_init_memory_flag
// Symbol whose contents are nonzero iff memory has already been initialized.
- static DefinedData *initMemoryFlag;
+ DefinedData *initMemoryFlag;
// __wasm_init_memory
// Function that initializes passive data segments during instantiation.
- static DefinedFunction *initMemory;
+ DefinedFunction *initMemory;
// __wasm_call_ctors
// Function that directly calls all ctors in priority order.
- static DefinedFunction *callCtors;
+ DefinedFunction *callCtors;
// __wasm_call_dtors
// Function that calls the libc/etc. cleanup function.
- static DefinedFunction *callDtors;
+ 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;
+ 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;
+ 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;
+ DefinedFunction *applyGlobalTLSRelocs;
// __wasm_init_tls
// Function that allocates thread-local storage and initializes it.
- static DefinedFunction *initTLS;
+ 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;
+ DefinedFunction *startFunction;
// __dso_handle
// Symbol used in calls to __cxa_atexit to determine current DLL
- static DefinedData *dsoHandle;
+ DefinedData *dsoHandle;
// __table_base
// Used in PIC code for offset of indirect function table
- static UndefinedGlobal *tableBase;
- static DefinedData *definedTableBase;
+ UndefinedGlobal *tableBase;
+ DefinedData *definedTableBase;
// __memory_base
// Used in PIC code for offset of global data
- static UndefinedGlobal *memoryBase;
- static DefinedData *definedMemoryBase;
+ 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.
- static TableSymbol *indirectFunctionTable;
+ TableSymbol *indirectFunctionTable;
};
// 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..c9b68909a1b2f 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.sym.indirectFunctionTable) &&
+ cast<DefinedTable>(ctx.sym.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.sym.indirectFunctionTable)
+ ctx.sym.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.sym.tlsBase->getGlobalIndex(), "__tls_base");
else
- writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
+ writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
"__memory_base");
// Add the virtual address of the data symbol
@@ -456,7 +456,8 @@ 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.sym.tableBase->getGlobalIndex(),
+ "__table_base");
// Add the table index to __table_base
writeU8(os, opcode_ptr_const, "CONST");
@@ -503,13 +504,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.sym.memoryBase->getGlobalIndex();
offset = d->getVA();
useExtendedConst = true;
}
} else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
if (!sym->isStub) {
- globalIdx = WasmSym::tableBase->getGlobalIndex();
+ globalIdx = ctx.sym.tableBase->getGlobalIndex();
offset = f->getTableIndex();
useExtendedConst = true;
}
@@ -564,12 +565,12 @@ void ExportSection::writeBody() {
}
bool StartSection::isNeeded() const {
- return WasmSym::startFunction != nullptr;
+ return ctx.sym.startFunction != nullptr;
}
void StartSection::writeBody() {
raw_ostream &os = bodyOutputStream;
- writeUleb128(os, WasmSym::startFunction->getFunctionIndex(),
+ writeUleb128(os, ctx.sym.startFunction->getFunctionIndex(),
"function index");
}
@@ -586,9 +587,9 @@ void ElemSection::addEntry(FunctionSymbol *sym) {
void ElemSection::writeBody() {
raw_ostream &os = bodyOutputStream;
- assert(WasmSym::indirectFunctionTable);
+ assert(ctx.sym.indirectFunctionTable);
writeUleb128(os, 1, "segment count");
- uint32_t tableNumber = WasmSym::indirectFunctionTable->getTableNumber();
+ uint32_t tableNumber = ctx.sym.indirectFunctionTable->getTableNumber();
uint32_t flags = 0;
if (tableNumber)
flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
@@ -600,7 +601,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.sym.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..4215f52a4d3ee 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.sym.stackLow)
+ ctx.sym.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.sym.stackPointer), memoryPtr);
+ if (ctx.sym.stackHigh)
+ ctx.sym.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.sym.globalBase)
+ ctx.sym.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.sym.dsoHandle)
+ ctx.sym.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.sym.tlsSize) {
+ auto *tlsSize = cast<DefinedGlobal>(ctx.sym.tlsSize);
setGlobalPtr(tlsSize, seg->size);
}
- if (WasmSym::tlsAlign) {
- auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign);
+ if (ctx.sym.tlsAlign) {
+ auto *tlsAlign = cast<DefinedGlobal>(ctx.sym.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.sym.tlsBase) {
+ auto *tlsBase = cast<DefinedGlobal>(ctx.sym.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.sym.initMemoryFlag = symtab->addSyntheticDataSymbol(
"__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
- WasmSym::initMemoryFlag->markLive();
- WasmSym::initMemoryFlag->setVA(memoryPtr);
+ ctx.sym.initMemoryFlag->markLive();
+ ctx.sym.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.sym.dataEnd)
+ ctx.sym.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.sym.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.sym.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.sym.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.sym.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.sym.indirectFunctionTable &&
+ shouldImport(ctx.sym.indirectFunctionTable))
+ out.importSec->addImport(ctx.sym.indirectFunctionTable);
for (Symbol *sym : symtab->symbols()) {
if (!shouldImport(sym))
continue;
- if (sym == WasmSym::indirectFunctionTable)
+ if (sym == ctx.sym.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.sym.callDtors == nullptr)
return;
std::vector<DefinedFunction *> toWrap;
@@ -922,27 +922,28 @@ void Writer::createCommandExportWrappers() {
}
static void finalizeIndirectFunctionTable() {
- if (!WasmSym::indirectFunctionTable)
+ if (!ctx.sym.indirectFunctionTable)
return;
- if (shouldImport(WasmSym::indirectFunctionTable) &&
- !WasmSym::indirectFunctionTable->hasTableNumber()) {
+ if (shouldImport(ctx.sym.indirectFunctionTable) &&
+ !ctx.sym.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.sym.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.sym.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.sym.indirectFunctionTable->setLimits(limits);
}
static void scanRelocations() {
@@ -1150,26 +1151,26 @@ void Writer::createSyntheticInitFunctions() {
// We also initialize bss segments (using memory.fill) as part of this
// function.
if (hasPassiveInitializedSegments()) {
- WasmSym::initMemory = symtab->addSyntheticFunction(
+ ctx.sym.initMemory = symtab->addSyntheticFunction(
"__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
- WasmSym::initMemory->markLive();
+ ctx.sym.initMemory->markLive();
if (ctx.arg.sharedMemory) {
// This global is assigned during __wasm_init_memory in the shared memory
// case.
- WasmSym::tlsBase->markLive();
+ ctx.sym.tlsBase->markLive();
}
}
if (ctx.arg.sharedMemory) {
if (out.globalSec->needsTLSRelocations()) {
- WasmSym::applyGlobalTLSRelocs = symtab->addSyntheticFunction(
+ ctx.sym.applyGlobalTLSRelocs = symtab->addSyntheticFunction(
"__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature,
"__wasm_apply_global_tls_relocs"));
- WasmSym::applyGlobalTLSRelocs->markLive();
+ ctx.sym.applyGlobalTLSRelocs->markLive();
// TLS relocations depend on the __tls_base symbols
- WasmSym::tlsBase->markLive();
+ ctx.sym.tlsBase->markLive();
}
auto hasTLSRelocs = [](const OutputSegment *segment) {
@@ -1180,40 +1181,39 @@ void Writer::createSyntheticInitFunctions() {
return false;
};
if (llvm::any_of(segments, hasTLSRelocs)) {
- WasmSym::applyTLSRelocs = symtab->addSyntheticFunction(
+ ctx.sym.applyTLSRelocs = symtab->addSyntheticFunction(
"__wasm_apply_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
- make<SyntheticFunction>(nullSignature,
- "__wasm_apply_tls_relocs"));
- WasmSym::applyTLSRelocs->markLive();
+ make<SyntheticFunction>(nullSignature, "__wasm_apply_tls_relocs"));
+ ctx.sym.applyTLSRelocs->markLive();
}
}
if (ctx.isPic && out.globalSec->needsRelocations()) {
- WasmSym::applyGlobalRelocs = symtab->addSyntheticFunction(
+ ctx.sym.applyGlobalRelocs = symtab->addSyntheticFunction(
"__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_apply_global_relocs"));
- WasmSym::applyGlobalRelocs->markLive();
+ ctx.sym.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.sym.applyGlobalRelocs && ctx.sym.initMemory) {
+ ctx.sym.startFunction = symtab->addSyntheticFunction(
"__wasm_start", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_start"));
- WasmSym::startFunction->markLive();
+ ctx.sym.startFunction->markLive();
}
}
void Writer::createInitMemoryFunction() {
LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
- assert(WasmSym::initMemory);
+ assert(ctx.sym.initMemory);
assert(hasPassiveInitializedSegments());
uint64_t flagAddress;
if (ctx.arg.sharedMemory) {
- assert(WasmSym::initMemoryFlag);
- flagAddress = WasmSym::initMemoryFlag->getVA();
+ assert(ctx.sym.initMemoryFlag);
+ flagAddress = ctx.sym.initMemoryFlag->getVA();
}
bool is64 = ctx.arg.is64.value_or(false);
std::string bodyContent;
@@ -1286,7 +1286,8 @@ 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.sym.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 +1334,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.sym.memoryBase->getGlobalIndex(),
"__memory_base");
writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD,
"i32.add");
@@ -1351,7 +1352,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.sym.tlsBase->getGlobalIndex(),
"__tls_base");
if (ctx.isPic) {
writeU8(os, WASM_OPCODE_LOCAL_GET, "local.tee");
@@ -1428,30 +1429,30 @@ void Writer::createInitMemoryFunction() {
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::initMemory, bodyContent);
+ createFunction(ctx.sym.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.sym.initMemory && ctx.sym.applyGlobalRelocs) {
+ assert(ctx.sym.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.sym.applyGlobalRelocs->getFunctionIndex(),
"function index");
writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, WasmSym::initMemory->getFunctionIndex(),
+ writeUleb128(os, ctx.sym.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.sym.startFunction, bodyContent);
+ } else if (ctx.sym.initMemory) {
+ ctx.sym.startFunction = ctx.sym.initMemory;
+ } else if (ctx.sym.applyGlobalRelocs) {
+ ctx.sym.startFunction = ctx.sym.applyGlobalRelocs;
}
}
@@ -1505,7 +1506,7 @@ void Writer::createApplyTLSRelocationsFunction() {
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::applyTLSRelocs, bodyContent);
+ createFunction(ctx.sym.applyTLSRelocs, bodyContent);
}
// Similar to createApplyDataRelocationsFunction but generates relocation code
@@ -1521,7 +1522,7 @@ void Writer::createApplyGlobalRelocationsFunction() {
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::applyGlobalRelocs, bodyContent);
+ createFunction(ctx.sym.applyGlobalRelocs, bodyContent);
}
// Similar to createApplyGlobalRelocationsFunction but for
@@ -1537,7 +1538,7 @@ void Writer::createApplyGlobalTLSRelocationsFunction() {
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::applyGlobalTLSRelocs, bodyContent);
+ createFunction(ctx.sym.applyGlobalTLSRelocs, bodyContent);
}
// Create synthetic "__wasm_call_ctors" function based on ctor functions
@@ -1545,7 +1546,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.sym.callCtors->isLive() && initFunctions.empty())
return;
// First write the body's contents to a string.
@@ -1566,7 +1567,7 @@ void Writer::createCallCtorsFunction() {
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::callCtors, bodyContent);
+ createFunction(ctx.sym.callCtors, bodyContent);
}
// Create a wrapper around a function export which calls the
@@ -1581,9 +1582,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.sym.callCtors->isLive()) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, WasmSym::callCtors->getFunctionIndex(),
+ writeUleb128(os, ctx.sym.callCtors->getFunctionIndex(),
"function index");
}
@@ -1596,7 +1597,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.sym.callDtors) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
writeUleb128(os, callDtors->getFunctionIndex(), "function index");
}
@@ -1627,7 +1628,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.sym.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 +1644,28 @@ void Writer::createInitTLSFunction() {
writeU8(os, 0, "memory index immediate");
}
- if (WasmSym::applyTLSRelocs) {
+ if (ctx.sym.applyTLSRelocs) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, WasmSym::applyTLSRelocs->getFunctionIndex(),
+ writeUleb128(os, ctx.sym.applyTLSRelocs->getFunctionIndex(),
"function index");
}
- if (WasmSym::applyGlobalTLSRelocs) {
+ if (ctx.sym.applyGlobalTLSRelocs) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, WasmSym::applyGlobalTLSRelocs->getFunctionIndex(),
+ writeUleb128(os, ctx.sym.applyGlobalTLSRelocs->getFunctionIndex(),
"function index");
}
writeU8(os, WASM_OPCODE_END, "end function");
}
- createFunction(WasmSym::initTLS, bodyContent);
+ createFunction(ctx.sym.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.sym.callCtors->isLive())
return;
for (ObjFile *file : ctx.objectFiles) {
@@ -1715,8 +1716,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.sym.definedTableBase)
+ ctx.sym.definedTableBase->setVA(ctx.arg.tableBase);
log("-- createOutputSegments");
createOutputSegments();
@@ -1784,14 +1785,18 @@ void Writer::run() {
if (!ctx.arg.relocatable) {
// Create linker synthesized functions
- if (WasmSym::applyGlobalRelocs)
+ if (ctx.sym.applyGlobalRelocs) {
createApplyGlobalRelocationsFunction();
- if (WasmSym::applyTLSRelocs)
+ }
+ if (ctx.sym.applyTLSRelocs) {
createApplyTLSRelocationsFunction();
- if (WasmSym::applyGlobalTLSRelocs)
+ }
+ if (ctx.sym.applyGlobalTLSRelocs) {
createApplyGlobalTLSRelocationsFunction();
- if (WasmSym::initMemory)
+ }
+ if (ctx.sym.initMemory) {
createInitMemoryFunction();
+ }
createStartFunction();
createCallCtorsFunction();
@@ -1802,14 +1807,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.sym.callCtors->isUsedInRegularObj &&
+ !ctx.sym.callCtors->isExported()) {
log("-- createCommandExportWrappers");
createCommandExportWrappers();
}
}
- if (WasmSym::initTLS && WasmSym::initTLS->isLive()) {
+ if (ctx.sym.initTLS && ctx.sym.initTLS->isLive()) {
log("-- createInitTLSFunction");
createInitTLSFunction();
}
>From f6056d1c7e01424e1c49329b526191299b033ac3 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Thu, 10 Apr 2025 00:33:10 +0530
Subject: [PATCH 2/4] fix formatting issues
---
lld/wasm/Driver.cpp | 12 ++++--------
lld/wasm/InputChunks.cpp | 3 +--
lld/wasm/OutputSections.cpp | 3 +--
lld/wasm/SyntheticSections.cpp | 13 ++++---------
lld/wasm/Writer.cpp | 12 ++++--------
5 files changed, 14 insertions(+), 29 deletions(-)
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 9a1c047197c6e..80e9a3ead2a44 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -963,8 +963,7 @@ static void createSyntheticSymbols() {
// See:
// https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32;
- ctx.sym.memoryBase =
- createUndefinedGlobal("__memory_base", globalType);
+ ctx.sym.memoryBase = createUndefinedGlobal("__memory_base", globalType);
ctx.sym.tableBase = createUndefinedGlobal("__table_base", globalType);
ctx.sym.memoryBase->markLive();
ctx.sym.tableBase->markLive();
@@ -1000,14 +999,11 @@ static void createOptionalSymbols() {
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.definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
+ ctx.sym.definedTableBase = symtab->addOptionalDataSymbol("__table_base");
}
- ctx.sym.firstPageEnd =
- symtab->addOptionalDataSymbol("__wasm_first_page_end");
+ ctx.sym.firstPageEnd = symtab->addOptionalDataSymbol("__wasm_first_page_end");
if (ctx.sym.firstPageEnd)
ctx.sym.firstPageEnd->setVA(ctx.arg.pageSize);
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index cd436d5a0eab8..ffab83e636392 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -413,8 +413,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
if (isTLS())
writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "tls_base");
else
- writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
- "memory_base");
+ writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "memory_base");
writeU8(os, opcode_ptr_add, "ADD");
}
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index 0aaa03770fcf9..cd80254a18d5c 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -137,8 +137,7 @@ void DataSection::finalizeContents() {
if (ctx.isPic) {
assert(segment->startVA == 0);
initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
- initExpr.Inst.Value.Global =
- ctx.sym.memoryBase->getGlobalIndex();
+ initExpr.Inst.Value.Global = ctx.sym.memoryBase->getGlobalIndex();
} else {
initExpr = intConst(segment->startVA, is64);
}
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index c9b68909a1b2f..76719596c62e0 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -445,8 +445,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
if (sym->isTLS())
writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "__tls_base");
else
- writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
- "__memory_base");
+ writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base");
// Add the virtual address of the data symbol
writeU8(os, opcode_ptr_const, "CONST");
@@ -456,8 +455,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
continue;
// Get __table_base
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
- writeUleb128(os, ctx.sym.tableBase->getGlobalIndex(),
- "__table_base");
+ writeUleb128(os, ctx.sym.tableBase->getGlobalIndex(), "__table_base");
// Add the table index to __table_base
writeU8(os, opcode_ptr_const, "CONST");
@@ -564,14 +562,11 @@ void ExportSection::writeBody() {
writeExport(os, export_);
}
-bool StartSection::isNeeded() const {
- return ctx.sym.startFunction != nullptr;
-}
+bool StartSection::isNeeded() const { return ctx.sym.startFunction != nullptr; }
void StartSection::writeBody() {
raw_ostream &os = bodyOutputStream;
- writeUleb128(os, ctx.sym.startFunction->getFunctionIndex(),
- "function index");
+ writeUleb128(os, ctx.sym.startFunction->getFunctionIndex(), "function index");
}
void ElemSection::addEntry(FunctionSymbol *sym) {
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 4215f52a4d3ee..3cc3e0d498979 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -936,8 +936,7 @@ static void finalizeIndirectFunctionTable() {
uint32_t tableSize = ctx.arg.tableBase + out.elemSec->numEntries();
WasmLimits limits = {0, tableSize, 0, 0};
- if (ctx.sym.indirectFunctionTable->isDefined() &&
- !ctx.arg.growableTable) {
+ if (ctx.sym.indirectFunctionTable->isDefined() && !ctx.arg.growableTable) {
limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
limits.Maximum = limits.Minimum;
}
@@ -1286,8 +1285,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, ctx.sym.memoryBase->getGlobalIndex(),
- "memory_base");
+ writeUleb128(os, ctx.sym.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");
@@ -1352,8 +1350,7 @@ void Writer::createInitMemoryFunction() {
writePtrConst(os, s->startVA, is64, "destination address");
}
writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET");
- writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(),
- "__tls_base");
+ writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "__tls_base");
if (ctx.isPic) {
writeU8(os, WASM_OPCODE_LOCAL_GET, "local.tee");
writeUleb128(os, 1, "local 1");
@@ -1584,8 +1581,7 @@ void Writer::createCommandExportWrapper(uint32_t functionIndex,
// applies any runtime relocations in Emscripten-style PIC mode)
if (ctx.sym.callCtors->isLive()) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, ctx.sym.callCtors->getFunctionIndex(),
- "function index");
+ writeUleb128(os, ctx.sym.callCtors->getFunctionIndex(), "function index");
}
// Call the user's code, leaving any return values on the operand stack.
>From 74c62dfd3901756e9a7bcb4594c74497090396c4 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Thu, 10 Apr 2025 01:19:14 +0530
Subject: [PATCH 3/4] Replicate framework as per elf
---
lld/wasm/Config.h | 111 +++++++++++++++++++++++++++++++++++++++++++--
lld/wasm/Symbols.h | 103 -----------------------------------------
2 files changed, 108 insertions(+), 106 deletions(-)
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 1ee2568784a89..7eee950999f1d 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -32,7 +32,11 @@ class InputTable;
class InputGlobal;
class InputFunction;
class Symbol;
-struct WasmSym;
+class DefinedData;
+class GlobalSymbol;
+class DefinedFunction;
+class UndefinedGlobal;
+class TableSymbol;
// For --unresolved-symbols.
enum class UnresolvedPolicy { ReportError, Warn, Ignore, ImportDynamic };
@@ -142,8 +146,109 @@ struct Ctx {
llvm::SmallVector<InputGlobal *, 0> syntheticGlobals;
llvm::SmallVector<InputTable *, 0> syntheticTables;
- // Linker-generated symbols like __wasm_init_memory, __heap_base, etc.
- WasmSym sym{};
+ // 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/Symbols.h b/lld/wasm/Symbols.h
index cd1f9a03a6a82..55ee21939ce07 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -537,109 +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.
- 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;
-};
-
// 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.
>From 25d7ad8f6218fe0987d8b46b147e3f75f1c877f2 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Thu, 10 Apr 2025 01:26:36 +0530
Subject: [PATCH 4/4] address code format changes
---
lld/wasm/Config.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 7eee950999f1d..9d903e0c799db 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -191,7 +191,8 @@ struct Ctx {
DefinedData *firstPageEnd;
// __wasm_init_memory_flag
- // Symbol whose contents are nonzero iff memory has already been initialized.
+ // Symbol whose contents are nonzero iff memory has already been
+ // initialized.
DefinedData *initMemoryFlag;
// __wasm_init_memory
@@ -244,8 +245,8 @@ struct Ctx {
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.
+ // 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;
More information about the llvm-commits
mailing list