[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