[lld] r353478 - [WebAssembly] Refactor handling of weak undefined functions. NFC.

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 7 14:42:16 PST 2019


Author: sbc
Date: Thu Feb  7 14:42:16 2019
New Revision: 353478

URL: http://llvm.org/viewvc/llvm-project?rev=353478&view=rev
Log:
[WebAssembly] Refactor handling of weak undefined functions. NFC.

Also add to the docs.

This is refactor in preparation for https://reviews.llvm.org/D57909

Differential Revision: https://reviews.llvm.org/D57920

Modified:
    lld/trunk/docs/WebAssembly.rst
    lld/trunk/test/wasm/archive-weak-undefined.ll
    lld/trunk/test/wasm/cxx-mangling.ll
    lld/trunk/test/wasm/lto/weak-undefined.ll
    lld/trunk/test/wasm/undefined-weak-call.ll
    lld/trunk/wasm/Driver.cpp
    lld/trunk/wasm/SymbolTable.cpp
    lld/trunk/wasm/SymbolTable.h
    lld/trunk/wasm/Symbols.h

Modified: lld/trunk/docs/WebAssembly.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/WebAssembly.rst?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/docs/WebAssembly.rst (original)
+++ lld/trunk/docs/WebAssembly.rst Thu Feb  7 14:42:16 2019
@@ -124,6 +124,18 @@ The symbols which are preserved by defau
 - Any symbol which is to be exported.
 - Any symbol transitively referenced by the above.
 
+Weak Undefined Functions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+On native platforms, calls to weak undefined functions end up as calls to the
+null function pointer.  With WebAssembly, direct calls must reference a defined
+function (with the correct signature).  In order to handle this case the linker
+will generate function a stub containing only the ``unreachable`` instruction
+and use this for any direct references to an undefined weak function.
+
+For example a runtime call to a weak undefined function ``foo`` will up trapping
+on ``unreachable`` inside and linker-generated function called
+``undefined:foo``.
 
 Missing features
 ----------------

Modified: lld/trunk/test/wasm/archive-weak-undefined.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/archive-weak-undefined.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/archive-weak-undefined.ll (original)
+++ lld/trunk/test/wasm/archive-weak-undefined.ll Thu Feb  7 14:42:16 2019
@@ -15,5 +15,5 @@ entry:
   ret void
 }
 
-; CHECK: Name: undefined function ret32
+; CHECK: Name: 'undefined:ret32'
 ; CHECK-NOT: Name: ret32

Modified: lld/trunk/test/wasm/cxx-mangling.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/cxx-mangling.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/cxx-mangling.ll (original)
+++ lld/trunk/test/wasm/cxx-mangling.ll Thu Feb  7 14:42:16 2019
@@ -58,8 +58,8 @@ define void @_start() {
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
 ; CHECK-NEXT:       - Index:           1
-; DEMANGLE-NEXT:      Name:            'undefined function bar(int)'
-; MANGLE-NEXT:        Name:            undefined function _Z3bari
+; DEMANGLE-NEXT:      Name:            'undefined:bar(int)'
+; MANGLE-NEXT:        Name:            'undefined:_Z3bari'
 ; CHECK-NEXT:       - Index:           2
 ; DEMANGLE-NEXT:      Name:            'foo(int)'
 ; MANGLE-NEXT:        Name:            _Z3fooi

Modified: lld/trunk/test/wasm/lto/weak-undefined.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/lto/weak-undefined.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/lto/weak-undefined.ll (original)
+++ lld/trunk/test/wasm/lto/weak-undefined.ll Thu Feb  7 14:42:16 2019
@@ -17,4 +17,4 @@ entry:
     ret void
 }
 
-; CHECK: Name:            undefined function foo
+; CHECK: Name:            'undefined:foo'

Modified: lld/trunk/test/wasm/undefined-weak-call.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/undefined-weak-call.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/undefined-weak-call.ll (original)
+++ lld/trunk/test/wasm/undefined-weak-call.ll Thu Feb  7 14:42:16 2019
@@ -110,11 +110,11 @@ define i32 @callWeakFuncs() {
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
 ; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            undefined function weakFunc1
+; CHECK-NEXT:         Name:            'undefined:weakFunc1'
 ; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            undefined function weakFunc2
+; CHECK-NEXT:         Name:            'undefined:weakFunc2'
 ; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Name:            undefined function weakFunc3
+; CHECK-NEXT:         Name:            'undefined:weakFunc3'
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Name:            callWeakFuncs
 ; CHECK-NEXT: ...

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Thu Feb  7 14:42:16 2019
@@ -286,53 +286,6 @@ static StringRef getEntry(opt::InputArgL
   return Arg->getValue();
 }
 
-static const uint8_t UnreachableFn[] = {
-    0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
-    0x00 /* opcode unreachable */, 0x0b /* opcode end */
-};
-
-// For weak undefined functions, there may be "call" instructions that reference
-// the symbol. In this case, we need to synthesise a dummy/stub function that
-// will abort at runtime, so that relocations can still provided an operand to
-// the call instruction that passes Wasm validation.
-static void handleWeakUndefines() {
-  for (Symbol *Sym : Symtab->getSymbols()) {
-    if (!Sym->isUndefWeak())
-      continue;
-
-    const WasmSignature *Sig = nullptr;
-
-    if (auto *FuncSym = dyn_cast<FunctionSymbol>(Sym)) {
-      // It is possible for undefined functions not to have a signature (eg. if
-      // added via "--undefined"), but weak undefined ones do have a signature.
-      assert(FuncSym->Signature);
-      Sig = FuncSym->Signature;
-    } else if (auto *LazySym = dyn_cast<LazySymbol>(Sym)) {
-      // Lazy symbols may not be functions and therefore can have a null
-      // signature.
-      Sig = LazySym->Signature;
-    }
-
-    if (!Sig)
-      continue;
-
-
-    // Add a synthetic dummy for weak undefined functions.  These dummies will
-    // be GC'd if not used as the target of any "call" instructions.
-    std::string SymName = toString(*Sym);
-    StringRef DebugName = Saver.save("undefined function " + SymName);
-    auto *Func = make<SyntheticFunction>(*Sig, Sym->getName(), DebugName);
-    Func->setBody(UnreachableFn);
-    // Ensure it compares equal to the null pointer, and so that table relocs
-    // don't pull in the stub body (only call-operand relocs should do that).
-    Func->setTableIndex(0);
-    Symtab->SyntheticFunctions.emplace_back(Func);
-    // Hide our dummy to prevent export.
-    uint32_t Flags = WASM_SYMBOL_VISIBILITY_HIDDEN;
-    replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Flags, nullptr, Func);
-  }
-}
-
 // Some Config members do not directly correspond to any particular
 // command line options, but computed based on other Config values.
 // This function initialize such members. See Config.h for the details
@@ -620,7 +573,7 @@ void LinkerDriver::link(ArrayRef<const c
   // Add synthetic dummies for weak undefined functions.  Must happen
   // after LTO otherwise functions may not yet have signatures.
   if (!Config->Relocatable)
-    handleWeakUndefines();
+    Symtab->handleWeakUndefines();
 
   if (EntrySym)
     EntrySym->setHidden(false);

Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Thu Feb  7 14:42:16 2019
@@ -102,7 +102,8 @@ std::pair<Symbol *, bool> SymbolTable::i
   return {Sym, true};
 }
 
-std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) {
+std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name,
+                                              const InputFile *File) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insertName(Name);
@@ -442,3 +443,58 @@ bool SymbolTable::addComdat(StringRef Na
 void SymbolTable::trace(StringRef Name) {
   SymMap.insert({CachedHashStringRef(Name), -1});
 }
+
+static const uint8_t UnreachableFn[] = {
+    0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
+    0x00 /* opcode unreachable */, 0x0b /* opcode end */
+};
+
+// Replace the given symbol body with an unreachable function.
+// This is used by handleWeakUndefines in order to generate a callable
+// equivalent of an undefined function.
+InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym,
+                                                   const WasmSignature &Sig,
+                                                   StringRef DebugName) {
+  auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName);
+  Func->setBody(UnreachableFn);
+  SyntheticFunctions.emplace_back(Func);
+  replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Sym->getFlags(), nullptr, Func);
+  return Func;
+}
+
+// For weak undefined functions, there may be "call" instructions that reference
+// the symbol. In this case, we need to synthesise a dummy/stub function that
+// will abort at runtime, so that relocations can still provided an operand to
+// the call instruction that passes Wasm validation.
+void SymbolTable::handleWeakUndefines() {
+  for (Symbol *Sym : getSymbols()) {
+    if (!Sym->isUndefWeak())
+      continue;
+
+    const WasmSignature *Sig = nullptr;
+
+    if (auto *FuncSym = dyn_cast<FunctionSymbol>(Sym)) {
+      // It is possible for undefined functions not to have a signature (eg. if
+      // added via "--undefined"), but weak undefined ones do have a signature.
+      assert(FuncSym->Signature);
+      Sig = FuncSym->Signature;
+    } else if (auto *LazySym = dyn_cast<LazySymbol>(Sym)) {
+      // Lazy symbols may not be functions and therefore can have a null
+      // signature.
+      Sig = LazySym->Signature;
+    }
+
+    if (!Sig)
+      continue;
+
+    // Add a synthetic dummy for weak undefined functions.  These dummies will
+    // be GC'd if not used as the target of any "call" instructions.
+    StringRef DebugName = Saver.save("undefined:" + toString(*Sym));
+    InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName);
+    // Ensure it compares equal to the null pointer, and so that table relocs
+    // don't pull in the stub body (only call-operand relocs should do that).
+    Func->setTableIndex(0);
+    // Hide our dummy to prevent export.
+    Sym->setHidden(true);
+  }
+}

Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Thu Feb  7 14:42:16 2019
@@ -79,10 +79,15 @@ public:
   DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags,
                                         InputFunction *Function);
 
+  void handleWeakUndefines();
+
 private:
-  std::pair<Symbol *, bool> insert(StringRef Name, InputFile *File);
+  std::pair<Symbol *, bool> insert(StringRef Name, const InputFile *File);
   std::pair<Symbol *, bool> insertName(StringRef Name);
 
+  InputFunction *replaceWithUnreachable(Symbol *Sym, const WasmSignature &Sig,
+                                        StringRef DebugName);
+
   // Maps symbol names to index into the SymVector.  -1 means that symbols
   // is to not yet in the vector but it should have tracing enabled if it is
   // ever added.

Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Thu Feb  7 14:42:16 2019
@@ -76,6 +76,8 @@ public:
   // Returns the file from which this symbol was created.
   InputFile *getFile() const { return File; }
 
+  uint32_t getFlags() const { return Flags; }
+
   InputChunk *getChunk() const;
 
   // Indicates that the section or import for this symbol will be included in




More information about the llvm-commits mailing list