[WebAssembly] Improve support for "needed" list in dylink section
authorSam Clegg <sbc@chromium.org>
Wed, 13 Mar 2019 21:29:20 +0000 (21:29 +0000)
committerSam Clegg <sbc@chromium.org>
Wed, 13 Mar 2019 21:29:20 +0000 (21:29 +0000)
This change adds basic support for shared library dependencies
via the dylink section.

See https://github.com/WebAssembly/tool-conventions/pull/77

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

llvm-svn: 356102

lld/test/wasm/shared-needed.ll [new file with mode: 0644]
lld/test/wasm/shared.ll
lld/wasm/InputFiles.cpp
lld/wasm/InputFiles.h
lld/wasm/SymbolTable.cpp
lld/wasm/SymbolTable.h
lld/wasm/Writer.cpp
llvm/lib/Object/WasmObjectFile.cpp

diff --git a/lld/test/wasm/shared-needed.ll b/lld/test/wasm/shared-needed.ll
new file mode 100644 (file)
index 0000000..f0afb10
--- /dev/null
@@ -0,0 +1,38 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+
+; RUN: wasm-ld -shared -o %t1.so %t.o
+; RUN: obj2yaml %t1.so | FileCheck %s -check-prefix=SO1
+
+; RUN: wasm-ld -shared -o %t2.so %t1.so %t.ret32.o
+; RUN: obj2yaml %t2.so | FileCheck %s -check-prefix=SO2
+
+target triple = "wasm32-unknown-unknown"
+
+@data = global i32 2, align 4
+
+define default void @foo() {
+entry:
+  ret void
+}
+
+; SO1:      Sections:
+; SO1-NEXT:   - Type:            CUSTOM
+; SO1-NEXT:     Name:            dylink
+; SO1-NEXT:     MemorySize:      4
+; SO1-NEXT:     MemoryAlignment: 2
+; SO1-NEXT:     TableSize:       0
+; SO1-NEXT:     TableAlignment:  0
+; SO1-NEXT:     Needed:          []
+; SO1-NEXT:   - Type:            TYPE
+
+; SO2:      Sections:
+; SO2-NEXT:   - Type:            CUSTOM
+; SO2-NEXT:     Name:            dylink
+; SO2-NEXT:     MemorySize:      0
+; SO2-NEXT:     MemoryAlignment: 0
+; SO2-NEXT:     TableSize:       0
+; SO2-NEXT:     TableAlignment:  0
+; SO2-NEXT:     Needed:
+; SO2-NEXT:       - shared-needed.ll.tmp1.so
+; SO2-NEXT:   - Type:            TYPE
index 21fd855..b83e61e 100644 (file)
@@ -33,6 +33,8 @@ declare void @func_external()
 ; CHECK-NEXT:     MemoryAlignment: 2
 ; CHECK-NEXT:     TableSize:       2
 ; CHECK-NEXT:     TableAlignment:  0
+; CHECK-NEXT:     Needed:          []
+; CHECK-NEXT:   - Type:            TYPE
 
 ; check for import of __table_base and __memory_base globals
 
index 2a5c10e..5c9ae60 100644 (file)
@@ -44,8 +44,13 @@ Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {
 
 InputFile *lld::wasm::createObjectFile(MemoryBufferRef MB) {
   file_magic Magic = identify_magic(MB.getBuffer());
-  if (Magic == file_magic::wasm_object)
+  if (Magic == file_magic::wasm_object) {
+    std::unique_ptr<Binary> Bin = check(createBinary(MB));
+    auto *Obj = cast<WasmObjectFile>(Bin.get());
+    if (Obj->isSharedObject())
+      return make<SharedFile>(MB);
     return make<ObjFile>(MB);
+  }
 
   if (Magic == file_magic::bitcode)
     return make<BitcodeFile>(MB);
index 07d72de..1f44f5b 100644 (file)
@@ -33,6 +33,7 @@ class InputFile {
 public:
   enum Kind {
     ObjectKind,
+    SharedKind,
     ArchiveKind,
     BitcodeKind,
   };
@@ -129,6 +130,16 @@ private:
   std::unique_ptr<WasmObjectFile> WasmObj;
 };
 
+// .so file.
+class SharedFile : public InputFile {
+public:
+  explicit SharedFile(MemoryBufferRef M) : InputFile(SharedKind, M) {}
+  static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
+
+  void parse() override {}
+};
+
+// .bc file
 class BitcodeFile : public InputFile {
 public:
   explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
index 1e7357d..5d7ed8c 100644 (file)
@@ -37,6 +37,8 @@ void SymbolTable::addFile(InputFile *File) {
     BitcodeFiles.push_back(F);
   else if (auto *F = dyn_cast<ObjFile>(File))
     ObjectFiles.push_back(F);
+  else if (auto *F = dyn_cast<SharedFile>(File))
+    SharedFiles.push_back(F);
 }
 
 // This function is where all the optimizations of link-time
index 3d0529a..afb1bb9 100644 (file)
@@ -39,6 +39,7 @@ public:
   void addCombinedLTOObject();
 
   std::vector<ObjFile *> ObjectFiles;
+  std::vector<InputFile *> SharedFiles;
   std::vector<BitcodeFile *> BitcodeFiles;
   std::vector<InputFunction *> SyntheticFunctions;
   std::vector<InputGlobal *> SyntheticGlobals;
index 12b526d..42affb4 100644 (file)
@@ -28,6 +28,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/LEB128.h"
+#include "llvm/Support/Path.h"
 
 #include <cstdarg>
 #include <map>
@@ -502,7 +503,9 @@ void Writer::createDylinkSection() {
   writeUleb128(OS, MemAlign, "MemAlign");
   writeUleb128(OS, IndirectFunctions.size(), "TableSize");
   writeUleb128(OS, 0, "TableAlign");
-  writeUleb128(OS, 0, "Needed");  // TODO: Support "needed" shared libraries
+  writeUleb128(OS, Symtab->SharedFiles.size(), "Needed");
+  for (auto *SO : Symtab->SharedFiles)
+    writeStr(OS, llvm::sys::path::filename(SO->getName()), "so name");
 }
 
 // Create the custom "linking" section containing linker metadata.
index 9d084bf..2ff2c55 100644 (file)
@@ -324,6 +324,7 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
 
 Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
   // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
+  HasDylinkSection = true;
   DylinkInfo.MemorySize = readVaruint32(Ctx);
   DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
   DylinkInfo.TableSize = readVaruint32(Ctx);