[llvm-branch-commits] [lld] e52881a - [lld][WebAssembly] Split __wasm_apply_relocs function in two
Sam Clegg via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 10 17:12:23 PST 2020
Author: Sam Clegg
Date: 2020-12-10T17:07:39-08:00
New Revision: e52881a2870234f0dad6e338a0f084eddeaa9356
URL: https://github.com/llvm/llvm-project/commit/e52881a2870234f0dad6e338a0f084eddeaa9356
DIFF: https://github.com/llvm/llvm-project/commit/e52881a2870234f0dad6e338a0f084eddeaa9356.diff
LOG: [lld][WebAssembly] Split __wasm_apply_relocs function in two
We have two types of relocations that we apply on startup:
1. Relocations that apply to wasm globals
2. Relocations that apply to wasm memory
The first set of relocations use only the `__memory_base` import to
update a set of internal globals. Because wasm globals are thread local
these need to run on each thread. Memory relocations, like static
constructors, must only be run once.
To ensure global relocations run on all threads and because the only
depend on the immutable `__memory_base` import we can run them during
the WebAssembly start functions, instead of waiting until the
post-instantiation __wasm_call_ctors.
Differential Revision: https://reviews.llvm.org/D93066
Added:
Modified:
lld/test/wasm/bsymbolic.s
lld/test/wasm/data-segments.ll
lld/test/wasm/pie.ll
lld/test/wasm/weak-undefined-pic.s
lld/wasm/Driver.cpp
lld/wasm/MarkLive.cpp
lld/wasm/Symbols.cpp
lld/wasm/Symbols.h
lld/wasm/SyntheticSections.cpp
lld/wasm/SyntheticSections.h
lld/wasm/Writer.cpp
Removed:
################################################################################
diff --git a/lld/test/wasm/bsymbolic.s b/lld/test/wasm/bsymbolic.s
index dc0e0ddcc773..07989fc5f437 100644
--- a/lld/test/wasm/bsymbolic.s
+++ b/lld/test/wasm/bsymbolic.s
@@ -1,5 +1,5 @@
// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
-// RUN: wasm-ld --no-entry -Bsymbolic %t.o -o %t2.so 2>&1 | FileCheck -check-prefix=WARNING %s
+// RUN: wasm-ld --no-entry -Bsymbolic %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=WARNING %s
// WARNING: warning: -Bsymbolic is only meaningful when combined with -shared
// RUN: wasm-ld --experimental-pic -shared %t.o -o %t0.so
diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll
index 6f6d96a30fa5..8c4c4ca79672 100644
--- a/lld/test/wasm/data-segments.ll
+++ b/lld/test/wasm/data-segments.ll
@@ -98,27 +98,27 @@
; PASSIVE-NEXT: Name: __wasm_init_memory
; PASSIVE-PIC: - Type: START
-; PASSIVE-PIC-NEXT: StartFunction: 3
+; PASSIVE-PIC-NEXT: StartFunction: 2
; PASSIVE-PIC-NEXT: - Type: DATACOUNT
; PASSIVE-PIC-NEXT: Count: 1
; PASSIVE-PIC-NEXT: - Type: CODE
; PASSIVE-PIC-NEXT: Functions:
; PASSIVE-PIC-NEXT: - Index: 0
; PASSIVE-PIC-NEXT: Locals: []
-; PASSIVE-PIC-NEXT: Body: 10010B
+; PASSIVE-PIC-NEXT: Body: 10030B
; PASSIVE-PIC-NEXT: - Index: 1
; PASSIVE-PIC-NEXT: Locals: []
; PASSIVE-PIC-NEXT: Body: 0B
; PASSIVE-PIC-NEXT: - Index: 2
-; PASSIVE-PIC-NEXT: Locals: []
-; PASSIVE-PIC-NEXT: Body: 0B
-; PASSIVE-PIC-NEXT: - Index: 3
; PASSIVE-PIC-NEXT: Locals:
; PASSIVE32-PIC-NEXT: - Type: I32
; PASSIVE64-PIC-NEXT: - Type: I64
; PASSIVE-PIC-NEXT: Count: 1
; PASSIVE32-PIC-NEXT: Body: 230141B4CE006A2100200041004101FE480200044020004101427FFE0102001A05410023016A410041B1CE00FC08000020004102FE1702002000417FFE0002001A0BFC09000B
; PASSIVE64-PIC-NEXT: Body: 230142B4CE006A2100200041004101FE480200044020004101427FFE0102001A05420023016A410041B1CE00FC08000020004102FE1702002000417FFE0002001A0BFC09000B
+; PASSIVE-PIC-NEXT: - Index: 3
+; PASSIVE-PIC-NEXT: Locals: []
+; PASSIVE-PIC-NEXT: Body: 0B
; PASSIVE-PIC-NEXT: - Type: DATA
; PASSIVE-PIC-NEXT: Segments:
; PASSIVE-PIC-NEXT: - SectionOffset: 4
@@ -130,8 +130,8 @@
; PASSIVE-PIC-NEXT: - Index: 0
; PASSIVE-PIC-NEXT: Name: __wasm_call_ctors
; PASSIVE-PIC-NEXT: - Index: 1
-; PASSIVE-PIC-NEXT: Name: __wasm_apply_relocs
-; PASSIVE-PIC-NEXT: - Index: 2
; PASSIVE-PIC-NEXT: Name: __wasm_init_tls
-; PASSIVE-PIC-NEXT: - Index: 3
+; PASSIVE-PIC-NEXT: - Index: 2
; PASSIVE-PIC-NEXT: Name: __wasm_init_memory
+; PASSIVE-PIC-NEXT: - Index: 3
+; PASSIVE-PIC-NEXT: Name: __wasm_apply_data_relocs
diff --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll
index 20a6c928b6ee..84555a08f19d 100644
--- a/lld/test/wasm/pie.ll
+++ b/lld/test/wasm/pie.ll
@@ -1,6 +1,5 @@
; RUN: llc -relocation-model=pic -mattr=+mutable-globals -filetype=obj %s -o %t.o
; RUN: wasm-ld --no-gc-sections --allow-undefined --experimental-pic -pie -o %t.wasm %t.o
-; RUN: obj2yaml %t.wasm | FileCheck %s
target triple = "wasm32-unknown-emscripten"
@@ -65,4 +64,51 @@ define void @_start() {
; CHECK-NEXT: GlobalType: I32
; CHECK-NEXT: GlobalMutable: false
+; CHECK: - Type: START
+; CHECK-NEXT: StartFunction: 2
+
+; CHECK: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: __wasm_call_ctors
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: __wasm_apply_data_relocs
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: __wasm_apply_global_relocs
+
+
+; Run the same test with threading support. In this mode
+; we expect __wasm_init_memory and __wasm_apply_data_relocs
+; to be generated along with __wasm_start as the start
+; function.
+
+; RUN: llc -relocation-model=pic -mattr=+mutable-globals,+atomics,+bulk-memory -filetype=obj %s -o %t.shmem.o
+; RUN: wasm-ld --no-gc-sections --shared-memory --allow-undefined --experimental-pic -pie -o %t.shmem.wasm %t.shmem.o
+; RUN: obj2yaml %t.shmem.wasm | FileCheck %s --check-prefix=SHMEM
+
+; SHMEM: - Type: CODE
+; SHMEM: - Index: 5
+; SHMEM-NEXT: Locals: []
+; SHMEM-NEXT: Body: 100210040B
+
+; SHMEM: FunctionNames:
+; SHMEM-NEXT: - Index: 0
+; SHMEM-NEXT: Name: __wasm_call_ctors
+; SHMEM-NEXT: - Index: 1
+; SHMEM-NEXT: Name: __wasm_init_tls
+; SHMEM-NEXT: - Index: 2
+; SHMEM-NEXT: Name: __wasm_init_memory
+; SHMEM-NEXT: - Index: 3
+; SHMEM-NEXT: Name: __wasm_apply_data_relocs
+; SHMEM-NEXT: - Index: 4
+; SHMEM-NEXT: Name: __wasm_apply_global_relocs
+; SHMEM-NEXT: - Index: 5
+; SHMEM-NEXT: Name: __wasm_start
+; SHMEM-NEXT: - Index: 6
+; SHMEM-NEXT: Name: foo
+; SHMEM-NEXT: - Index: 7
+; SHMEM-NEXT: Name: get_data_address
+; SHMEM-NEXT: - Index: 8
+; SHMEM-NEXT: Name: _start
diff --git a/lld/test/wasm/weak-undefined-pic.s b/lld/test/wasm/weak-undefined-pic.s
index a169fd315f08..17dbc54faf7c 100644
--- a/lld/test/wasm/weak-undefined-pic.s
+++ b/lld/test/wasm/weak-undefined-pic.s
@@ -66,7 +66,7 @@ _start:
# CHECK-NEXT: - Index: 0
# CHECK-NEXT: Name: __stack_pointer
# CHECK-NEXT: - Index: 1
-# CHECK-NEXT: Name: 'undefined_weak:foo'
+# CHECK-NEXT: Name: 'GOT.func.internal.undefined_weak:foo'
# With `-pie` or `-shared` the resolution should be deferred to the dynamic
# linker and the function address should be imported as GOT.func.foo.
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 3be0a0345079..0d84914c1295 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -615,14 +615,6 @@ static void createSyntheticSymbols() {
"__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
- if (config->isPic) {
- // For PIC code we create a synthetic function __wasm_apply_relocs which
- // is called from __wasm_call_ctors before the user-level constructors.
- WasmSym::applyRelocs = symtab->addSyntheticFunction(
- "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
- make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs"));
- }
-
if (config->isPic) {
WasmSym::stackPointer =
createUndefinedGlobal("__stack_pointer", config->is64.getValueOr(false)
diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp
index acc3c4c04c0c..63c12545d554 100644
--- a/lld/wasm/MarkLive.cpp
+++ b/lld/wasm/MarkLive.cpp
@@ -98,9 +98,6 @@ void MarkLive::run() {
if (WasmSym::callDtors)
enqueue(WasmSym::callDtors);
- if (WasmSym::applyRelocs)
- enqueue(WasmSym::applyRelocs);
-
// Enqueue constructors in objects explicitly live from the command-line.
for (const ObjFile *obj : symtab->objectFiles)
if (obj->isLive())
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index ffb52c1c5746..9e41f7c6281d 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -68,8 +68,10 @@ namespace wasm {
DefinedFunction *WasmSym::callCtors;
DefinedFunction *WasmSym::callDtors;
DefinedFunction *WasmSym::initMemory;
-DefinedFunction *WasmSym::applyRelocs;
+DefinedFunction *WasmSym::applyDataRelocs;
+DefinedFunction *WasmSym::applyGlobalRelocs;
DefinedFunction *WasmSym::initTLS;
+DefinedFunction *WasmSym::startFunction;
DefinedData *WasmSym::dsoHandle;
DefinedData *WasmSym::dataEnd;
DefinedData *WasmSym::globalBase;
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index cfa686998de4..4fa1a834db37 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -484,14 +484,23 @@ struct WasmSym {
// Function that calls the libc/etc. cleanup function.
static DefinedFunction *callDtors;
- // __wasm_apply_relocs
+ // __wasm_apply_data_relocs
// Function that applies relocations to data segment post-instantiation.
- static DefinedFunction *applyRelocs;
+ static DefinedFunction *applyDataRelocs;
+
+ // __wasm_apply_global_relocs
+ // Function that applies relocations to data segment post-instantiation.
+ // Unlike __wasm_apply_data_relocs this needs to run on every thread.
+ static DefinedFunction *applyGlobalRelocs;
// __wasm_init_tls
// Function that allocates thread-local storage and initializes it.
static DefinedFunction *initTLS;
+ // Pointer to the function that is to be used in the start section.
+ // (normally an alias of initMemory, or applyGlobalRelocs).
+ static DefinedFunction *startFunction;
+
// __dso_handle
// Symbol used in calls to __cxa_atexit to determine current DLL
static DefinedData *dsoHandle;
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 8e2c7c631f95..768a265b3d09 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -372,12 +372,13 @@ void ExportSection::writeBody() {
}
bool StartSection::isNeeded() const {
- return WasmSym::initMemory != nullptr;
+ return WasmSym::startFunction != nullptr;
}
void StartSection::writeBody() {
raw_ostream &os = bodyOutputStream;
- writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index");
+ writeUleb128(os, WasmSym::startFunction->getFunctionIndex(),
+ "function index");
}
void ElemSection::addEntry(FunctionSymbol *sym) {
@@ -624,7 +625,10 @@ void NameSection::writeBody() {
}
for (Symbol *s : out.globalSec->internalGotSymbols) {
writeUleb128(sub.os, s->getGOTIndex(), "global index");
- writeStr(sub.os, toString(*s), "symbol name");
+ if (isa<FunctionSymbol>(s))
+ writeStr(sub.os, "GOT.func.internal." + toString(*s), "symbol name");
+ else
+ writeStr(sub.os, "GOT.data.internal." + toString(*s), "symbol name");
}
sub.writeTo(bodyOutputStream);
diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h
index 3f52b5dc547e..b4d833d212a6 100644
--- a/lld/wasm/SyntheticSections.h
+++ b/lld/wasm/SyntheticSections.h
@@ -217,6 +217,7 @@ class GlobalSection : public SyntheticSection {
// specific relocation types combined with linker relaxation which could
// transform a `global.get` to an `i32.const`.
void addInternalGOTEntry(Symbol *sym);
+ bool needsRelocations() { return internalGotSymbols.size(); }
void generateRelocationCode(raw_ostream &os) const;
std::vector<const DefinedData *> dataAddressGlobals;
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index ff9d0dc7a99b..3f255966f8db 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -60,7 +60,9 @@ class Writer {
void createSyntheticInitFunctions();
void createInitMemoryFunction();
- void createApplyRelocationsFunction();
+ void createStartFunction();
+ void createApplyDataRelocationsFunction();
+ void createApplyGlobalRelocationsFunction();
void createCallCtorsFunction();
void createInitTLSFunction();
void createCommandExportWrappers();
@@ -296,8 +298,11 @@ void Writer::layoutMemory() {
}
// Make space for the memory initialization flag
- if (WasmSym::initMemoryFlag) {
+ if (config->sharedMemory && hasPassiveInitializedSegments()) {
memoryPtr = alignTo(memoryPtr, 4);
+ WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol(
+ "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
+ WasmSym::initMemoryFlag->markLive();
WasmSym::initMemoryFlag->setVirtualAddress(memoryPtr);
log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
"__wasm_init_memory_flag", memoryPtr, 4, 4));
@@ -867,19 +872,43 @@ bool Writer::hasPassiveInitializedSegments() {
}
void Writer::createSyntheticInitFunctions() {
+ if (config->relocatable)
+ return;
+
+ static WasmSignature nullSignature = {{}, {}};
+
// Passive segments are used to avoid memory being reinitialized on each
// thread's instantiation. These passive segments are initialized and
// dropped in __wasm_init_memory, which is registered as the start function
-
if (config->sharedMemory && hasPassiveInitializedSegments()) {
- static WasmSignature nullSignature = {{}, {}};
WasmSym::initMemory = symtab->addSyntheticFunction(
"__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
WasmSym::initMemory->markLive();
- WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol(
- "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
- WasmSym::initMemoryFlag->markLive();
+ }
+
+ if (config->isPic) {
+ // For PIC code we create synthetic functions that apply relocations.
+ // These get called from __wasm_call_ctors before the user-level
+ // constructors.
+ WasmSym::applyDataRelocs = symtab->addSyntheticFunction(
+ "__wasm_apply_data_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
+ make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs"));
+ WasmSym::applyDataRelocs->markLive();
+
+ if (out.globalSec->needsRelocations()) {
+ WasmSym::applyGlobalRelocs = symtab->addSyntheticFunction(
+ "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
+ make<SyntheticFunction>(nullSignature, "__wasm_apply_global_relocs"));
+ WasmSym::applyGlobalRelocs->markLive();
+ }
+ }
+
+ if (WasmSym::applyGlobalRelocs && WasmSym::initMemory) {
+ WasmSym::startFunction = symtab->addSyntheticFunction(
+ "__wasm_start", WASM_SYMBOL_VISIBILITY_HIDDEN,
+ make<SyntheticFunction>(nullSignature, "__wasm_start"));
+ WasmSym::startFunction->markLive();
}
}
@@ -1042,24 +1071,39 @@ void Writer::createInitMemoryFunction() {
createFunction(WasmSym::initMemory, bodyContent);
}
+void Writer::createStartFunction() {
+ if (WasmSym::startFunction) {
+ std::string bodyContent;
+ {
+ raw_string_ostream os(bodyContent);
+ writeUleb128(os, 0, "num locals");
+ writeU8(os, WASM_OPCODE_CALL, "CALL");
+ writeUleb128(os, WasmSym::initMemory->getFunctionIndex(),
+ "function index");
+ writeU8(os, WASM_OPCODE_CALL, "CALL");
+ writeUleb128(os, WasmSym::applyGlobalRelocs->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;
+ }
+}
+
// For -shared (PIC) output, we create create a synthetic function which will
// apply any relocations to the data segments on startup. This function is
// called __wasm_apply_relocs and is added at the beginning of __wasm_call_ctors
// before any of the constructors run.
-void Writer::createApplyRelocationsFunction() {
- LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n");
+void Writer::createApplyDataRelocationsFunction() {
+ LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n");
// First write the body's contents to a string.
std::string bodyContent;
{
raw_string_ostream os(bodyContent);
writeUleb128(os, 0, "num locals");
-
- // First apply relocations to any internalized GOT entries. These
- // are the result of relaxation when building with -Bsymbolic.
- out.globalSec->generateRelocationCode(os);
-
- // Next apply any realocation to the data section by reading GOT entry
- // globals.
for (const OutputSegment *seg : segments)
for (const InputSegment *inSeg : seg->inputSegments)
inSeg->generateRelocationCode(os);
@@ -1067,7 +1111,23 @@ void Writer::createApplyRelocationsFunction() {
writeU8(os, WASM_OPCODE_END, "END");
}
- createFunction(WasmSym::applyRelocs, bodyContent);
+ createFunction(WasmSym::applyDataRelocs, bodyContent);
+}
+
+// Similar to createApplyDataRelocationsFunction but generates relocation code
+// fro WebAssembly globals. Because these globals are not shared between threads
+// these relocation need to run on every thread.
+void Writer::createApplyGlobalRelocationsFunction() {
+ // First write the body's contents to a string.
+ std::string bodyContent;
+ {
+ raw_string_ostream os(bodyContent);
+ writeUleb128(os, 0, "num locals");
+ out.globalSec->generateRelocationCode(os);
+ writeU8(os, WASM_OPCODE_END, "END");
+ }
+
+ createFunction(WasmSym::applyGlobalRelocs, bodyContent);
}
// Create synthetic "__wasm_call_ctors" function based on ctor functions
@@ -1076,7 +1136,8 @@ void Writer::createCallCtorsFunction() {
// If __wasm_call_ctors isn't referenced, there aren't any ctors, and we
// aren't calling `__wasm_apply_relocs` for Emscripten-style PIC, don't
// define the `__wasm_call_ctors` function.
- if (!WasmSym::callCtors->isLive() && initFunctions.empty() && !config->isPic)
+ if (!WasmSym::callCtors->isLive() && !WasmSym::applyDataRelocs &&
+ initFunctions.empty())
return;
// First write the body's contents to a string.
@@ -1085,9 +1146,9 @@ void Writer::createCallCtorsFunction() {
raw_string_ostream os(bodyContent);
writeUleb128(os, 0, "num locals");
- if (config->isPic) {
+ if (WasmSym::applyDataRelocs) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, WasmSym::applyRelocs->getFunctionIndex(),
+ writeUleb128(os, WasmSym::applyDataRelocs->getFunctionIndex(),
"function index");
}
@@ -1099,6 +1160,7 @@ void Writer::createCallCtorsFunction() {
writeU8(os, WASM_OPCODE_DROP, "DROP");
}
}
+
writeU8(os, WASM_OPCODE_END, "END");
}
@@ -1118,7 +1180,7 @@ void Writer::createCommandExportWrapper(uint32_t functionIndex,
// If we have any ctors, or we're calling `__wasm_apply_relocs` for
// Emscripten-style PIC, call `__wasm_call_ctors` which performs those
// calls.
- if (!initFunctions.empty() || config->isPic) {
+ if (WasmSym::callCtors->isLive()) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
writeUleb128(os, WasmSym::callCtors->getFunctionIndex(),
"function index");
@@ -1253,8 +1315,6 @@ void Writer::run() {
populateProducers();
log("-- calculateImports");
calculateImports();
- log("-- createSyntheticInitFunctions");
- createSyntheticInitFunctions();
log("-- layoutMemory");
layoutMemory();
@@ -1267,18 +1327,23 @@ void Writer::run() {
log("-- scanRelocations");
scanRelocations();
+ log("-- createSyntheticInitFunctions");
+ createSyntheticInitFunctions();
log("-- assignIndexes");
assignIndexes();
log("-- calculateInitFunctions");
calculateInitFunctions();
if (!config->relocatable) {
- if (WasmSym::applyRelocs)
- createApplyRelocationsFunction();
+ // Create linker synthesized functions
+ if (WasmSym::applyDataRelocs)
+ createApplyDataRelocationsFunction();
+ if (WasmSym::applyGlobalRelocs)
+ createApplyGlobalRelocationsFunction();
if (WasmSym::initMemory)
createInitMemoryFunction();
+ createStartFunction();
- // Create linker synthesized functions
createCallCtorsFunction();
// Create export wrappers for commands if needed.
More information about the llvm-branch-commits
mailing list