Skip to content

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

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions lld/wasm/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class InputTable;
class InputGlobal;
class InputFunction;
class Symbol;
class DefinedData;
class GlobalSymbol;
class DefinedFunction;
class UndefinedGlobal;
class TableSymbol;

// For --unresolved-symbols.
enum class UnresolvedPolicy { ReportError, Warn, Ignore, ImportDynamic };
Expand Down Expand Up @@ -139,6 +144,107 @@ struct Ctx {
llvm::SmallVector<InputGlobal *, 0> syntheticGlobals;
llvm::SmallVector<InputTable *, 0> syntheticTables;

// linker-generated symbols
struct WasmSym {
// __global_base
// Symbol marking the start of the global section.
DefinedData *globalBase;

// __stack_pointer/__stack_low/__stack_high
// Global that holds current value of stack pointer and data symbols marking
// the start and end of the stack region. stackPointer is initialized to
// stackHigh and grows downwards towards stackLow
GlobalSymbol *stackPointer;
DefinedData *stackLow;
DefinedData *stackHigh;

// __tls_base
// Global that holds the address of the base of the current thread's
// TLS block.
GlobalSymbol *tlsBase;

// __tls_size
// Symbol whose value is the size of the TLS block.
GlobalSymbol *tlsSize;

// __tls_size
// Symbol whose value is the alignment of the TLS block.
GlobalSymbol *tlsAlign;

// __data_end
// Symbol marking the end of the data and bss.
DefinedData *dataEnd;

// __heap_base/__heap_end
// Symbols marking the beginning and end of the "heap". It starts at the end
// of the data, bss and explicit stack, and extends to the end of the linear
// memory allocated by wasm-ld. This region of memory is not used by the
// linked code, so it may be used as a backing store for `sbrk` or `malloc`
// implementations.
DefinedData *heapBase;
DefinedData *heapEnd;

// __wasm_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;

Expand Down
60 changes: 30 additions & 30 deletions lld/wasm/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void Ctx::reset() {
isPic = false;
legacyFunctionTable = false;
emitBssSegments = false;
sym = WasmSym{};
}

namespace {
Expand Down Expand Up @@ -941,14 +942,14 @@ static void createSyntheticSymbols() {
true};
static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
true};
WasmSym::callCtors = symtab->addSyntheticFunction(
ctx.sym.callCtors = symtab->addSyntheticFunction(
"__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));

bool is64 = ctx.arg.is64.value_or(false);

if (ctx.isPic) {
WasmSym::stackPointer =
ctx.sym.stackPointer =
createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
? &mutableGlobalTypeI64
: &mutableGlobalTypeI32);
Expand All @@ -958,45 +959,44 @@ 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"));
}
}

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");
}

// For non-shared memory programs we still need to define __tls_base since we
Expand All @@ -1009,7 +1009,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() {
Expand Down Expand Up @@ -1384,9 +1384,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)) {
Expand All @@ -1395,7 +1395,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");
}
Expand Down Expand Up @@ -1488,7 +1488,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())
Expand Down
10 changes: 5 additions & 5 deletions lld/wasm/InputChunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,9 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
if (ctx.isPic) {
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
if (isTLS())
writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "tls_base");
writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "tls_base");
else
writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "memory_base");
writeU8(os, opcode_ptr_add, "ADD");
}

Expand All @@ -422,12 +422,12 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
}
} else {
assert(ctx.isPic);
const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
const GlobalSymbol *baseSymbol = ctx.sym.memoryBase;
if (rel.Type == R_WASM_TABLE_INDEX_I32 ||
rel.Type == R_WASM_TABLE_INDEX_I64)
baseSymbol = WasmSym::tableBase;
baseSymbol = ctx.sym.tableBase;
else if (sym->isTLS())
baseSymbol = WasmSym::tlsBase;
baseSymbol = ctx.sym.tlsBase;
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
writeU8(os, opcode_reloc_const, "CONST");
Expand Down
6 changes: 3 additions & 3 deletions lld/wasm/MarkLive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions lld/wasm/OutputSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void DataSection::finalizeContents() {
if ((segment->initFlags & WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
if (ctx.isPic && ctx.arg.extendedConst) {
writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");
writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
"literal (global index)");
if (segment->startVA) {
writePtrConst(os, segment->startVA, is64, "offset");
Expand All @@ -136,7 +136,7 @@ void DataSection::finalizeContents() {
if (ctx.isPic) {
assert(segment->startVA == 0);
initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
initExpr.Inst.Value.Global = WasmSym::memoryBase->getGlobalIndex();
initExpr.Inst.Value.Global = ctx.sym.memoryBase->getGlobalIndex();
} else {
initExpr = intConst(segment->startVA, is64);
}
Expand Down
25 changes: 0 additions & 25 deletions lld/wasm/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,31 +77,6 @@ std::string toString(wasm::Symbol::Kind kind) {
}

namespace wasm {
DefinedFunction *WasmSym::callCtors;
DefinedFunction *WasmSym::callDtors;
DefinedFunction *WasmSym::initMemory;
DefinedFunction *WasmSym::applyGlobalRelocs;
DefinedFunction *WasmSym::applyTLSRelocs;
DefinedFunction *WasmSym::applyGlobalTLSRelocs;
DefinedFunction *WasmSym::initTLS;
DefinedFunction *WasmSym::startFunction;
DefinedData *WasmSym::dsoHandle;
DefinedData *WasmSym::dataEnd;
DefinedData *WasmSym::globalBase;
DefinedData *WasmSym::heapBase;
DefinedData *WasmSym::heapEnd;
DefinedData *WasmSym::initMemoryFlag;
GlobalSymbol *WasmSym::stackPointer;
DefinedData *WasmSym::stackLow;
DefinedData *WasmSym::stackHigh;
GlobalSymbol *WasmSym::tlsBase;
GlobalSymbol *WasmSym::tlsSize;
GlobalSymbol *WasmSym::tlsAlign;
UndefinedGlobal *WasmSym::tableBase;
DefinedData *WasmSym::definedTableBase;
UndefinedGlobal *WasmSym::memoryBase;
DefinedData *WasmSym::definedMemoryBase;
TableSymbol *WasmSym::indirectFunctionTable;

WasmSymbolType Symbol::getWasmType() const {
if (isa<FunctionSymbol>(this))
Expand Down
Loading
Loading