llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Alexey Bader (bader)

<details>
<summary>Changes</summary>

Add support for consuming static archives (.a, .lib) containing bitcode
device libraries. When an archive is passed via --bc-library, each
bitcode member is extracted and linked individually with LinkOnlyNeeded
semantics, ensuring only referenced symbols are included in the output.

Non-IR archive members (such as symbol tables or ELF objects) are
silently skipped. Archives with mismatched target triples are filtered
at the module level.

This enables sanitizer runtimes and other device libraries to be
packaged as static archives rather than individual bitcode files.

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


2 Files Affected:

- (modified) clang/test/OffloadTools/clang-sycl-linker/link.ll (+11) 
- (modified) clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp (+33) 


``````````diff
diff --git a/clang/test/OffloadTools/clang-sycl-linker/link.ll 
b/clang/test/OffloadTools/clang-sycl-linker/link.ll
index 4114f0a3f3fb1..305f493e62dc5 100644
--- a/clang/test/OffloadTools/clang-sycl-linker/link.ll
+++ b/clang/test/OffloadTools/clang-sycl-linker/link.ll
@@ -34,6 +34,17 @@
 ; Test that an absolute path to --bc-library is taken as-is, with no -L 
required.
 ; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libfoo.bc 
--dry-run -o a.spv --print-linked-module 2>&1 \
 ; RUN:   | FileCheck %s --check-prefix=CHECK-DEVICE-LIB
+;
+; Test linking with a static archive of bitcode libraries.
+; RUN: rm -f %t/libfoo.a
+; RUN: llvm-ar rcs %t/libfoo.a %t/libfoo.bc
+; RUN: clang-sycl-linker %t/foo.bc %t/bar.bc --bc-library %t/libfoo.a 
--dry-run -o a.spv --print-linked-module 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=CHECK-ARCHIVE
+; CHECK-ARCHIVE: define {{.*}}foo_func1{{.*}}
+; CHECK-ARCHIVE: define {{.*}}foo_func2{{.*}}
+; CHECK-ARCHIVE: define {{.*}}bar_func1{{.*}}
+; CHECK-ARCHIVE: define {{.*}}addFive{{.*}}
+; CHECK-ARCHIVE-NOT: define {{.*}}unusedFunc{{.*}}
 
 ;--- foo.ll
 target datalayout = 
"e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp 
b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
index e5e092c4737ec..da2af2e4315dc 100644
--- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
+++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp
@@ -30,6 +30,7 @@
 #include "llvm/LTO/LTO.h"
 #include "llvm/Linker/Linker.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Object/Archive.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/IRObjectFile.h"
 #include "llvm/Object/OffloadBinary.h"
@@ -341,6 +342,38 @@ static Expected<LinkResult> 
linkInputs(ArrayRef<std::string> InputFiles,
 
   // Link in library files.
   for (auto &File : *BCLibFiles) {
+    // Static archives are unpacked and each bitcode member is linked
+    // individually with LinkOnlyNeeded.
+    StringRef Ext = sys::path::extension(File);
+    if (Ext == ".a" || Ext == ".lib") {
+      auto BufOrErr = MemoryBuffer::getFile(File);
+      if (std::error_code EC = BufOrErr.getError())
+        return createFileError(File, EC);
+      Expected<std::unique_ptr<object::Archive>> ArOrErr =
+          object::Archive::create((*BufOrErr)->getMemBufferRef());
+      if (!ArOrErr)
+        return ArOrErr.takeError();
+      Error ArErr = Error::success();
+      for (const auto &Child : (*ArOrErr)->children(ArErr)) {
+        Expected<MemoryBufferRef> MemOrErr = Child.getMemoryBufferRef();
+        if (!MemOrErr)
+          return MemOrErr.takeError();
+        SMDiagnostic D;
+        std::unique_ptr<Module> Mod = getLazyIRModule(
+            MemoryBuffer::getMemBuffer(*MemOrErr, /*RequiresNullTerm=*/false),
+            D, C);
+        if (!Mod) {
+          // Skip non-IR archive members (e.g. symbol index, ELF objects).
+          continue;
+        }
+        if (Mod->getTargetTriple() == TargetTriple)
+          if (L.linkInModule(std::move(Mod), Linker::Flags::LinkOnlyNeeded))
+            return createStringError("Could not link IR from " + File);
+      }
+      if (ArErr)
+        return std::move(ArErr);
+      continue;
+    }
     auto LibMod = getBitcodeModule(File, C);
     if (!LibMod)
       return LibMod.takeError();

``````````

</details>


https://github.com/llvm/llvm-project/pull/201253
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to