[lld] [lld][WebAssembly] Implement `--start-lib`/`--end-lib` (PR #78821)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 19 16:33:47 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-wasm

@llvm/pr-subscribers-lld-elf

Author: Sam Clegg (sbc100)

<details>
<summary>Changes</summary>

Fixes: #<!-- -->77960

---
Full diff: https://github.com/llvm/llvm-project/pull/78821.diff


8 Files Affected:

- (modified) lld/ELF/InputFiles.h (+2-2) 
- (added) lld/test/wasm/Inputs/start-lib1.s (+7) 
- (added) lld/test/wasm/Inputs/start-lib2.s (+4) 
- (added) lld/test/wasm/start-lib.s (+33) 
- (modified) lld/wasm/Driver.cpp (+14-1) 
- (modified) lld/wasm/InputFiles.h (+2-3) 
- (modified) lld/wasm/Options.td (+6) 
- (modified) lld/wasm/Symbols.h (+3-3) 


``````````diff
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index ab98d78fcf1455a..108a87bc43eb6b1 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -126,8 +126,8 @@ class InputFile {
   uint8_t osabi = 0;
   uint8_t abiVersion = 0;
 
-  // True if this is a relocatable object file/bitcode file between --start-lib
-  // and --end-lib.
+  // True if this is a relocatable object file/bitcode file in an ar archive
+  // or between --start-lib and --end-lib.
   bool lazy = false;
 
   // True if this is an argument for --just-symbols. Usually false.
diff --git a/lld/test/wasm/Inputs/start-lib1.s b/lld/test/wasm/Inputs/start-lib1.s
new file mode 100644
index 000000000000000..229f67a4bd897f8
--- /dev/null
+++ b/lld/test/wasm/Inputs/start-lib1.s
@@ -0,0 +1,7 @@
+.functype bar () -> ()
+
+.globl foo
+foo:
+  .functype foo () -> ()
+  call bar
+  end_function
diff --git a/lld/test/wasm/Inputs/start-lib2.s b/lld/test/wasm/Inputs/start-lib2.s
new file mode 100644
index 000000000000000..28cfa6f637c58a9
--- /dev/null
+++ b/lld/test/wasm/Inputs/start-lib2.s
@@ -0,0 +1,4 @@
+.globl bar
+bar:
+  .functype bar () -> ()
+  end_function
diff --git a/lld/test/wasm/start-lib.s b/lld/test/wasm/start-lib.s
new file mode 100644
index 000000000000000..8bed63cdcf494cb
--- /dev/null
+++ b/lld/test/wasm/start-lib.s
@@ -0,0 +1,33 @@
+// Based on lld/test/ELF/start-lib.s
+
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown \
+// RUN:   %p/Inputs/start-lib1.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown \
+// RUN:   %p/Inputs/start-lib2.s -o %t3.o
+
+// RUN: wasm-ld --no-gc-sections -o %t3 %t1.o %t2.o %t3.o
+// RUN: obj2yaml %t3 | FileCheck --check-prefix=TEST1 %s
+// TEST1: Name: foo
+// TEST1: Name: bar
+
+// RUN: wasm-ld --no-gc-sections -o %t3 %t1.o -u bar --start-lib %t2.o %t3.o
+// RUN: obj2yaml %t3 | FileCheck --check-prefix=TEST2 %s
+// TEST2-NOT: Name: foo
+// TEST2: Name: bar
+
+// RUN: wasm-ld --no-gc-sections -o %t3 %t1.o --start-lib %t2.o %t3.o
+// RUN: obj2yaml %t3 | FileCheck --check-prefix=TEST3 %s
+// TEST3-NOT: Name: foo
+// TEST3-NOT: Name: bar
+
+// RUN: not wasm-ld %t1.o --start-lib --start-lib 2>&1 | FileCheck -check-prefix=NESTED-LIB %s
+// NESTED-LIB: nested --start-lib
+
+// RUN: not wasm-ld --end-lib 2>&1 | FileCheck -check-prefix=END %s
+// END: stray --end-lib
+
+.globl _start
+_start:
+  .functype _start () -> ()
+  end_function
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index edf1979c1d3025a..3a81f342baa1681 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -94,6 +94,9 @@ class LinkerDriver {
   // True if we are in --whole-archive and --no-whole-archive.
   bool inWholeArchive = false;
 
+  // True if we are in --start-lib and --end-lib.
+  bool inLib = false;
+
   std::vector<InputFile *> files;
 };
 } // anonymous namespace
@@ -304,7 +307,7 @@ void LinkerDriver::addFile(StringRef path) {
   }
   case file_magic::bitcode:
   case file_magic::wasm_object:
-    files.push_back(createObjectFile(mbref));
+    files.push_back(createObjectFile(mbref, "", 0, inLib));
     break;
   case file_magic::unknown:
     if (mbref.getBuffer().starts_with("#STUB")) {
@@ -375,6 +378,16 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
     case OPT_no_whole_archive:
       inWholeArchive = false;
       break;
+    case OPT_start_lib:
+      if (inLib)
+        error("nested --start-lib");
+      inLib = true;
+      break;
+    case OPT_end_lib:
+      if (!inLib)
+        error("stray --end-lib");
+      inLib = false;
+      break;
     }
   }
   if (files.empty() && errorCount() == 0)
diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h
index fd3d5e5ef479677..a129be36515d017 100644
--- a/lld/wasm/InputFiles.h
+++ b/lld/wasm/InputFiles.h
@@ -67,9 +67,8 @@ class InputFile {
   void markLive() { live = true; }
   bool isLive() const { return live; }
 
-  // True if this file is exists as in an archive file and has not yet been
-  // extracted.
-  // TODO(sbc): Use this to implement --start-lib/--end-lib.
+  // True if this is a relocatable object file/bitcode file in an ar archive
+  // or between --start-lib and --end-lib.
   bool lazy = false;
 
 protected:
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index 95ebc202a451879..8190717cef63bb9 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -70,6 +70,9 @@ defm export_dynamic: B<"export-dynamic",
     "Put symbols in the dynamic symbol table",
     "Do not put symbols in the dynamic symbol table (default)">;
 
+def end_lib: F<"end-lib">,
+  HelpText<"End a grouping of objects that should be treated as if they were together in an archive">;
+
 def entry: S<"entry">, MetaVarName<"<entry>">,
   HelpText<"Name of entry point symbol">;
 
@@ -128,6 +131,9 @@ defm rsp_quoting: Eq<"rsp-quoting", "Quoting style for response files">,
 
 def shared: F<"shared">, HelpText<"Build a shared object">;
 
+def start_lib: F<"start-lib">,
+  HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">;
+
 def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;
 
 def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index de52c92d34e78b0..38586bbd1323629 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -486,9 +486,9 @@ class UndefinedTag : public TagSymbol {
   static bool classof(const Symbol *s) { return s->kind() == UndefinedTagKind; }
 };
 
-// LazySymbol represents a symbol that is not yet in the link, but we know where
-// to find it if needed. If the resolver finds both Undefined and Lazy for the
-// same name, it will ask the Lazy to load a file.
+// LazySymbol symbols represent symbols in object files between --start-lib and
+// --end-lib options. LLD also handles traditional archives as if all the files
+// in the archive are surrounded by --start-lib and --end-lib.
 //
 // A special complication is the handling of weak undefined symbols. They should
 // not load a file, but we have to remember we have seen both the weak undefined

``````````

</details>


https://github.com/llvm/llvm-project/pull/78821


More information about the llvm-commits mailing list