[lld] r320004 - [WebAssembly] Add -u/--undefined argument handling

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 6 19:19:53 PST 2017


Author: sbc
Date: Wed Dec  6 19:19:53 2017
New Revision: 320004

URL: http://llvm.org/viewvc/llvm-project?rev=320004&view=rev
Log:
[WebAssembly] Add -u/--undefined argument handling

Adds a new argument to wasm-lld, `--undefined`, with
similar semantics to the ELF linker. It pulls in symbols
from files contained within a `.a` archive, forcing them
to be included even if the translation unit would not
otherwise be pulled in.

Patch by Nicholas Wilson

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

Added:
    lld/trunk/test/wasm/load-undefined.ll
Modified:
    lld/trunk/wasm/Driver.cpp
    lld/trunk/wasm/Options.td
    lld/trunk/wasm/SymbolTable.cpp
    lld/trunk/wasm/Symbols.h

Added: lld/trunk/test/wasm/load-undefined.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/load-undefined.ll?rev=320004&view=auto
==============================================================================
--- lld/trunk/test/wasm/load-undefined.ll (added)
+++ lld/trunk/test/wasm/load-undefined.ll Wed Dec  6 19:19:53 2017
@@ -0,0 +1,38 @@
+; Verify that the -u / --undefined option is able to pull in symbols from
+; an archive, and doesn't error when uses to pull in a symbol already loaded.
+;
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/ret64.ll -o %t.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/ret32.ll -o %t2.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t3.o
+; RUN: llvm-ar rcs %t2.a %t2.o
+; RUN: lld -flavor wasm %t3.o %t2.a %t.o -o %t.wasm -u ret32 --undefined ret64
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+define i32 @_start() local_unnamed_addr {
+entry:
+  ret i32 1
+}
+
+; CHECK:        - Type:            EXPORT
+; CHECK-NEXT:     Exports:
+; CHECK-NEXT:       - Name:            memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            _start
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            ret32
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            ret64
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:   - Type:
+
+
+; Verify that referencing a symbol that doesn't exist won't work
+; RUN: not lld -flavor wasm %t3.o -o %t.wasm -u symboldoesnotexist 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED1 %s
+; CHECK-UNDEFINED1: error: undefined symbol: symboldoesnotexist
+
+; RUN: not lld -flavor wasm %t3.o -o %t.wasm --undefined symboldoesnotexist --allow-undefined 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED2 %s
+; CHECK-UNDEFINED2: function forced with --undefined not found: symboldoesnotexist

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=320004&r1=320003&r2=320004&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Wed Dec  6 19:19:53 2017
@@ -273,6 +273,8 @@ void LinkerDriver::link(ArrayRef<const c
 
   if (Config->Relocatable && !Config->Entry.empty())
     error("entry point specified for relocatable output file");
+  if (Config->Relocatable && Args.hasArg(OPT_undefined))
+    error("undefined symbols specified for relocatable output file");
 
   if (!Config->Relocatable) {
     if (Config->Entry.empty())
@@ -280,6 +282,10 @@ void LinkerDriver::link(ArrayRef<const c
     static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
     addSyntheticUndefinedFunction(Config->Entry, &Signature);
 
+    // Handle the `--undefined <sym>` options.
+    for (StringRef S : args::getStrings(Args, OPT_undefined))
+      addSyntheticUndefinedFunction(S, nullptr);
+
     Config->StackPointerSymbol = addSyntheticGlobal("__stack_pointer", 0);
   }
 
@@ -297,6 +303,18 @@ void LinkerDriver::link(ArrayRef<const c
     Symtab->reportRemainingUndefines();
     if (errorCount())
       return;
+  } else {
+    // When we allow undefined symbols we cannot include those defined in
+    // -u/--undefined since these undefined symbols have only names and no
+    // function signature, which means they cannot be written to the final
+    // output.
+    for (StringRef S : args::getStrings(Args, OPT_undefined)) {
+      Symbol *Sym = Symtab->find(S);
+      if (!Sym->isDefined())
+        error("function forced with --undefined not found: " + Sym->getName());
+    }
+    if (errorCount())
+      return;
   }
 
   if (!Config->Entry.empty()) {

Modified: lld/trunk/wasm/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Options.td?rev=320004&r1=320003&r2=320004&view=diff
==============================================================================
--- lld/trunk/wasm/Options.td (original)
+++ lld/trunk/wasm/Options.td Wed Dec  6 19:19:53 2017
@@ -6,6 +6,11 @@ class F<string name>: Flag<["--", "-"],
 class J<string name>: Joined<["--", "-"], name>;
 class S<string name>: Separate<["--", "-"], name>;
 
+multiclass Eq<string name> {
+  def "": Separate<["--", "-"], name>;
+  def _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
+}
+
 def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
   HelpText<"Add a directory to the library search path">;
 
@@ -52,6 +57,9 @@ def strip_all: F<"strip-all">, HelpText<
 
 def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
 
+defm undefined: Eq<"undefined">,
+  HelpText<"Force undefined symbol during linking">;
+
 def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
   HelpText<"Linker option extensions">;
 
@@ -89,3 +97,4 @@ def alias_max_memory_m: Flag<["-"], "m">
 def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>;
 def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
 def alias_entry_entry: J<"entry=">, Alias<entry>;
+def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;

Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=320004&r1=320003&r2=320004&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Wed Dec  6 19:19:53 2017
@@ -118,6 +118,10 @@ static void checkSymbolTypes(const Symbo
   // For function symbols, optionally check the function signature matches too.
   if (!NewIsFunction || !Config->CheckSignatures)
     return;
+  // Skip the signature check if the existing function has no signature (e.g.
+  // if it is an undefined symbol generated by --undefined command line flag).
+  if (!Existing.hasFunctionType())
+    return;
 
   DEBUG(dbgs() << "checkSymbolTypes: " << New.Name << "\n");
   assert(NewSig);

Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=320004&r1=320003&r2=320004&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Wed Dec  6 19:19:53 2017
@@ -69,6 +69,7 @@ public:
   uint32_t getGlobalIndex() const;
   uint32_t getFunctionIndex() const;
 
+  bool hasFunctionType() const { return FunctionType != nullptr; }
   const WasmSignature &getFunctionType() const;
   uint32_t getOutputIndex() const;
 




More information about the llvm-commits mailing list