[lld] r322320 - [WebAssembly] When loading libraries look for companion `.imports` file

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 11 14:31:35 PST 2018


Author: sbc
Date: Thu Jan 11 14:31:35 2018
New Revision: 322320

URL: http://llvm.org/viewvc/llvm-project?rev=322320&view=rev
Log:
[WebAssembly] When loading libraries look for companion `.imports` file

This allows libraries to supply a list of symbols which are
allowed to be undefined at link time (i.e. result in imports).

This method replaces the existing mechanism (-allow-undefined-file)
used by the clang driver to allow undefined symbols in libc.

For more on motivation for this see:
 https://github.com/WebAssembly/tool-conventions/issues/35

In the long run we hope to remove this features and instead
include this information in the object format itself.

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

Modified:
    lld/trunk/test/wasm/archive.ll
    lld/trunk/wasm/Driver.cpp

Modified: lld/trunk/test/wasm/archive.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/archive.ll?rev=322320&r1=322319&r2=322320&view=diff
==============================================================================
--- lld/trunk/test/wasm/archive.ll (original)
+++ lld/trunk/test/wasm/archive.ll Thu Jan 11 14:31:35 2018
@@ -3,26 +3,35 @@
 ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/archive2.ll -o %t.a2.o
 ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/hello.ll -o %t.a3.o
 ; RUN: llvm-ar rcs %t.a %t.a1.o %t.a2.o %t.a3.o
+; RUN: rm -f %t.imports
+; RUN: not lld -flavor wasm %t.a %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED %s
+
+; CHECK-UNDEFINED: undefined symbol: missing_func
+
+; RUN: echo 'missing_func' > %t.imports
 ; RUN: lld -flavor wasm %t.a %t.o -o %t.wasm
+
 ; RUN: llvm-nm -a %t.wasm | FileCheck %s
 
 declare i32 @foo() local_unnamed_addr #1
+declare i32 @missing_func() local_unnamed_addr #1
 
 define i32 @_start() local_unnamed_addr #0 {
 entry:
-  %call = tail call i32 @foo() #2
-  ret i32 %call
+  %call1 = call i32 @foo() #2
+  %call2 = call i32 @missing_func() #2
+  ret i32 %call2
 }
 
 ; Verify that multually dependant object files in an archive is handled
 ; correctly.
 
-; CHECK:      00000002 T _start
-; CHECK-NEXT: 00000002 T _start
-; CHECK-NEXT: 00000000 T bar
-; CHECK-NEXT: 00000000 T bar
-; CHECK-NEXT: 00000001 T foo
-; CHECK-NEXT: 00000001 T foo
+; CHECK:      00000003 T _start
+; CHECK-NEXT: 00000003 T _start
+; CHECK-NEXT: 00000001 T bar
+; CHECK-NEXT: 00000001 T bar
+; CHECK-NEXT: 00000002 T foo
+; CHECK-NEXT: 00000002 T foo
 
 ; Verify that symbols from unused objects don't appear in the symbol table
 ; CHECK-NOT: hello

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=322320&r1=322319&r2=322320&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Thu Jan 11 14:31:35 2018
@@ -161,16 +161,36 @@ opt::InputArgList WasmOptTable::parse(Ar
   return Args;
 }
 
+// Currently we allow a ".imports" to live alongside a library. This can
+// be used to specify a list of symbols which can be undefined at link
+// time (imported from the environment.  For example libc.a include an
+// import file that lists the syscall functions it relies on at runtime.
+// In the long run this information would be better stored as a symbol
+// attribute/flag in the object file itself.
+// See: https://github.com/WebAssembly/tool-conventions/issues/35
+static void readImportFile(StringRef Filename) {
+  if (Optional<MemoryBufferRef> Buf = readFile(Filename))
+    for (StringRef Sym : args::getLines(*Buf))
+      Config->AllowUndefinedSymbols.insert(Sym);
+}
+
 void LinkerDriver::addFile(StringRef Path) {
   Optional<MemoryBufferRef> Buffer = readFile(Path);
   if (!Buffer.hasValue())
     return;
   MemoryBufferRef MBRef = *Buffer;
 
-  if (identify_magic(MBRef.getBuffer()) == file_magic::archive)
+  if (identify_magic(MBRef.getBuffer()) == file_magic::archive) {
+    SmallString<128> ImportFile = Path;
+    path::replace_extension(ImportFile, ".imports");
+    if (fs::exists(ImportFile))
+      readImportFile(ImportFile.str());
+
     Files.push_back(make<ArchiveFile>(MBRef));
-  else
-    Files.push_back(make<ObjFile>(MBRef));
+    return;
+  }
+
+  Files.push_back(make<ObjFile>(MBRef));
 }
 
 // Add a given library by searching it from input search paths.
@@ -257,9 +277,7 @@ void LinkerDriver::link(ArrayRef<const c
       args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize);
 
   if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file))
-    if (Optional<MemoryBufferRef> Buf = readFile(Arg->getValue()))
-      for (StringRef Sym : args::getLines(*Buf))
-        Config->AllowUndefinedSymbols.insert(Sym);
+    readImportFile(Arg->getValue());
 
   if (Config->OutputFile.empty())
     error("no output file specified");




More information about the llvm-commits mailing list