[lld] r346974 - [WebAssembly] Import the stack pointer when building shared libraries
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 15 10:15:54 PST 2018
Author: sbc
Date: Thu Nov 15 10:15:54 2018
New Revision: 346974
URL: http://llvm.org/viewvc/llvm-project?rev=346974&view=rev
Log:
[WebAssembly] Import the stack pointer when building shared libraries
Differential Revision: https://reviews.llvm.org/D54558
Modified:
lld/trunk/test/wasm/shared.ll
lld/trunk/wasm/Driver.cpp
lld/trunk/wasm/OutputSections.cpp
lld/trunk/wasm/Symbols.cpp
lld/trunk/wasm/Symbols.h
lld/trunk/wasm/Writer.cpp
Modified: lld/trunk/test/wasm/shared.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/shared.ll?rev=346974&r1=346973&r2=346974&view=diff
==============================================================================
--- lld/trunk/test/wasm/shared.ll (original)
+++ lld/trunk/test/wasm/shared.ll Thu Nov 15 10:15:54 2018
@@ -9,6 +9,8 @@ target triple = "wasm32-unknown-unknown"
define default void @foo() {
entry:
+ ; To ensure we use __stack_pointer
+ %ptr = alloca i32
%0 = load i32, i32* @used_data, align 4
%1 = load void ()*, void ()** @indirect_func, align 4
call void %1()
@@ -39,6 +41,11 @@ entry:
; CHECK-NEXT: Initial: 0x00000001
; CHECK-NEXT: Maximum: 0x00000001
; CHECK-NEXT: - Module: env
+; CHECK-NEXT: Field: __stack_pointer
+; CHECK-NEXT: Kind: GLOBAL
+; CHECK-NEXT: GlobalType: I32
+; CHECK-NEXT: GlobalMutable: true
+; CHECK-NEXT: - Module: env
; CHECK-NEXT: Field: __memory_base
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: GlobalType: I32
@@ -55,7 +62,7 @@ entry:
; CHECK-NEXT: Segments:
; CHECK-NEXT: - Offset:
; CHECK-NEXT: Opcode: GET_GLOBAL
-; CHECK-NEXT: Index: 1
+; CHECK-NEXT: Index: 2
; CHECK-NEXT: Functions: [ 1 ]
; check the data segment initialized with __memory_base global as offset
@@ -66,5 +73,5 @@ entry:
; CHECK-NEXT: MemoryIndex: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: GET_GLOBAL
-; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Index: 1
; CHECK-NEXT: Content: '00000000'
Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=346974&r1=346973&r2=346974&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Thu Nov 15 10:15:54 2018
@@ -431,6 +431,71 @@ static Symbol *handleUndefined(StringRef
return Sym;
}
+static UndefinedGlobal *
+createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) {
+ auto *Sym =
+ cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, 0, nullptr, Type));
+ Config->AllowUndefinedSymbols.insert(Sym->getName());
+ Sym->IsUsedInRegularObj = true;
+ return Sym;
+}
+
+// Create ABI-defined synthetic symbols
+static void createSyntheticSymbols() {
+ static WasmSignature NullSignature = {{}, {}};
+ static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false};
+ static llvm::wasm::WasmGlobalType MutableGlobalTypeI32 = {WASM_TYPE_I32,
+ true};
+
+ WasmSym::CallCtors = Symtab->addSyntheticFunction(
+ "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
+ make<SyntheticFunction>(NullSignature, "__wasm_call_ctors"));
+
+ // The __stack_pointer is imported in the shared library case, and exported
+ // in the non-shared (executable) case.
+ if (Config->Shared) {
+ WasmSym::StackPointer =
+ createUndefinedGlobal("__stack_pointer", &MutableGlobalTypeI32);
+ } else {
+ llvm::wasm::WasmGlobal Global;
+ Global.Type = {WASM_TYPE_I32, true};
+ Global.InitExpr.Value.Int32 = 0;
+ Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
+ Global.SymbolName = "__stack_pointer";
+ InputGlobal *StackPointer = make<InputGlobal>(Global, nullptr);
+ StackPointer->Live = true;
+ // For non-PIC code
+ // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global
+ // spec proposal is implemented in all major browsers.
+ // See: https://github.com/WebAssembly/mutable-global
+ WasmSym::StackPointer = Symtab->addSyntheticGlobal(
+ "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
+ WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0);
+ WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0);
+
+ // These two synthetic symbols exist purely for the embedder so we always
+ // want to export them.
+ WasmSym::HeapBase->ForceExport = true;
+ WasmSym::DataEnd->ForceExport = true;
+ }
+
+ if (Config->Pic) {
+ // For PIC code, we import two global variables (__memory_base and
+ // __table_base) from the environment and use these as the offset at
+ // which to load our static data and function table.
+ // See:
+ // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
+ WasmSym::MemoryBase =
+ createUndefinedGlobal("__memory_base", &GlobalTypeI32);
+ WasmSym::TableBase = createUndefinedGlobal("__table_base", &GlobalTypeI32);
+ WasmSym::MemoryBase->markLive();
+ WasmSym::TableBase->markLive();
+ }
+
+ WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol(
+ "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
+}
+
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
WasmOptTable Parser;
opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
@@ -480,59 +545,8 @@ void LinkerDriver::link(ArrayRef<const c
if (Config->Shared)
Config->ExportDynamic = true;
- Symbol *EntrySym = nullptr;
- if (!Config->Relocatable) {
- llvm::wasm::WasmGlobal Global;
- Global.Type = {WASM_TYPE_I32, true};
- Global.InitExpr.Value.Int32 = 0;
- Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
- Global.SymbolName = "__stack_pointer";
- InputGlobal *StackPointer = make<InputGlobal>(Global, nullptr);
- StackPointer->Live = true;
-
- static WasmSignature NullSignature = {{}, {}};
-
- // Add synthetic symbols before any others
- WasmSym::CallCtors = Symtab->addSyntheticFunction(
- "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
- make<SyntheticFunction>(NullSignature, "__wasm_call_ctors"));
- // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global
- // spec proposal is implemented in all major browsers.
- // See: https://github.com/WebAssembly/mutable-global
- WasmSym::StackPointer = Symtab->addSyntheticGlobal(
- "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
- WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0);
- WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol(
- "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
- WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0);
-
- if (Config->Pic) {
- // For PIC code, we import two global variables (__memory_base and
- // __table_base) from the environment and use these as the offset at
- // which to load our static data and function table.
- // See: https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
- static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false};
-
- WasmSym::MemoryBase = Symtab->addUndefinedGlobal(
- "__memory_base", WASM_SYMBOL_VISIBILITY_HIDDEN, nullptr,
- &GlobalTypeI32);
- Config->AllowUndefinedSymbols.insert(WasmSym::MemoryBase->getName());
- WasmSym::MemoryBase->IsUsedInRegularObj = true;
- WasmSym::MemoryBase->markLive();
-
- WasmSym::TableBase = Symtab->addUndefinedGlobal(
- "__table_base", WASM_SYMBOL_VISIBILITY_HIDDEN, nullptr,
- &GlobalTypeI32);
- Config->AllowUndefinedSymbols.insert(WasmSym::TableBase->getName());
- WasmSym::TableBase->IsUsedInRegularObj = true;
- WasmSym::TableBase->markLive();
- }
-
- // These two synthetic symbols exist purely for the embedder so we always
- // want to export them.
- WasmSym::HeapBase->ForceExport = true;
- WasmSym::DataEnd->ForceExport = true;
- }
+ if (!Config->Relocatable)
+ createSyntheticSymbols();
createFiles(Args);
if (errorCount())
@@ -560,6 +574,7 @@ void LinkerDriver::link(ArrayRef<const c
Arg->getValue());
}
+ Symbol *EntrySym = nullptr;
if (!Config->Relocatable) {
// Add synthetic dummies for weak undefined functions.
handleWeakUndefines();
Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=346974&r1=346973&r2=346974&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Thu Nov 15 10:15:54 2018
@@ -141,8 +141,7 @@ DataSection::DataSection(ArrayRef<Output
assert(Segments.size() <= 1 &&
"Currenly only a single data segment is supported in PIC mode");
InitExpr.Opcode = WASM_OPCODE_GET_GLOBAL;
- InitExpr.Value.Global =
- cast<GlobalSymbol>(WasmSym::MemoryBase)->getGlobalIndex();
+ InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex();
} else {
InitExpr.Opcode = WASM_OPCODE_I32_CONST;
InitExpr.Value.Int32 = Segment->StartVA;
Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=346974&r1=346973&r2=346974&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Thu Nov 15 10:15:54 2018
@@ -27,9 +27,9 @@ DefinedFunction *WasmSym::CallCtors;
DefinedData *WasmSym::DsoHandle;
DefinedData *WasmSym::DataEnd;
DefinedData *WasmSym::HeapBase;
-DefinedGlobal *WasmSym::StackPointer;
-Symbol *WasmSym::TableBase;
-Symbol *WasmSym::MemoryBase;
+GlobalSymbol *WasmSym::StackPointer;
+UndefinedGlobal *WasmSym::TableBase;
+UndefinedGlobal *WasmSym::MemoryBase;
WasmSymbolType Symbol::getWasmType() const {
if (isa<FunctionSymbol>(this))
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=346974&r1=346973&r2=346974&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Thu Nov 15 10:15:54 2018
@@ -291,7 +291,7 @@ struct WasmSym {
// __stack_pointer
// Global that holds the address of the top of the explicit value stack in
// linear memory.
- static DefinedGlobal *StackPointer;
+ static GlobalSymbol *StackPointer;
// __data_end
// Symbol marking the end of the data and bss.
@@ -313,11 +313,11 @@ struct WasmSym {
// __table_base
// Used in PIC code for offset of indirect function table
- static Symbol *TableBase;
+ static UndefinedGlobal *TableBase;
// __memory_base
// Used in PIC code for offset of global data
- static Symbol *MemoryBase;
+ static UndefinedGlobal *MemoryBase;
};
// A buffer class that is large enough to hold any Symbol-derived
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=346974&r1=346973&r2=346974&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Thu Nov 15 10:15:54 2018
@@ -332,8 +332,7 @@ void Writer::createElemSection() {
WasmInitExpr InitExpr;
if (Config->Pic) {
InitExpr.Opcode = WASM_OPCODE_GET_GLOBAL;
- InitExpr.Value.Global =
- cast<GlobalSymbol>(WasmSym::TableBase)->getGlobalIndex();
+ InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex();
} else {
InitExpr.Opcode = WASM_OPCODE_I32_CONST;
InitExpr.Value.Int32 = TableBase;
@@ -632,7 +631,8 @@ void Writer::layoutMemory() {
log("mem: stack size = " + Twine(Config->ZStackSize));
log("mem: stack base = " + Twine(MemoryPtr));
MemoryPtr += Config->ZStackSize;
- WasmSym::StackPointer->Global->Global.InitExpr.Value.Int32 = MemoryPtr;
+ auto *SP = cast<DefinedGlobal>(WasmSym::StackPointer);
+ SP->Global->Global.InitExpr.Value.Int32 = MemoryPtr;
log("mem: stack top = " + Twine(MemoryPtr));
};
@@ -666,6 +666,11 @@ void Writer::layoutMemory() {
log("mem: static data = " + Twine(MemoryPtr - DataStart));
+ if (Config->Shared) {
+ MemSize = MemoryPtr;
+ return;
+ }
+
if (!Config->StackFirst)
PlaceStack();
More information about the llvm-commits
mailing list