jhuber6 created this revision.
jhuber6 added reviewers: jdoerfert, gregrodgers, JonChesterfield, ronlieb.
Herald added subscribers: guansong, yaxunl.
jhuber6 requested review of this revision.
Herald added subscribers: cfe-commits, sstefan1.
Herald added a project: clang.

This patch adds support for searching through the linker library paths
to identify static libraries that may contain device code. If device
code is present it will be extracted. This should ideally fully support
static linking with OpenMP offloading.

Depends on D116627 <https://reviews.llvm.org/D116627>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D116675

Files:
  clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp


Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -65,7 +65,9 @@
 /// Path of the current binary.
 static std::string LinkerExecutable;
 
+/// Temporary files created by the linker wrapper.
 static SmallVector<std::string, 16> TempFiles;
+
 /// Magic section string that marks the existence of offloading data. The
 /// section string will be formatted as `.llvm.offloading.<triple>.<arch>`.
 #define OFFLOAD_SECTION_MAGIC_STR ".llvm.offloading."
@@ -570,6 +572,44 @@
   return static_cast<std::string>(ObjectFile);
 }
 
+Optional<std::string> findFile(StringRef Dir, const Twine &Name) {
+  SmallString<128> Path;
+  // TODO: Parse `--sysroot` somewhere and use it here.
+  sys::path::append(Path, Dir, Name);
+  if (sys::fs::exists(Path))
+    return static_cast<std::string>(Path);
+  return None;
+}
+
+Optional<std::string> findFromSearchPaths(StringRef Name,
+                                          ArrayRef<StringRef> SearchPaths) {
+  for (StringRef Dir : SearchPaths)
+    if (Optional<std::string> File = findFile(Dir, Name))
+      return File;
+  return None;
+}
+
+Optional<std::string> searchLibraryBaseName(StringRef Name,
+                                            ArrayRef<StringRef> SearchPaths) {
+  for (StringRef Dir : SearchPaths) {
+    if (Optional<std::string> File = findFile(Dir, "lib" + Name + ".a"))
+      return File;
+  }
+  return None;
+}
+
+/// Search for static libraries in the linker's library path given input like
+/// `-lfoo` or `-l:libfoo.a`.
+Optional<std::string> searchLibrary(StringRef Input,
+                                    ArrayRef<StringRef> SearchPaths) {
+  if (!Input.startswith("-l"))
+    return None;
+  StringRef Name = Input.drop_front(2);
+  if (Name.startswith(":"))
+    return findFromSearchPaths(Name.drop_front(), SearchPaths);
+  return searchLibraryBaseName(Name, SearchPaths);
+}
+
 } // namespace
 
 int main(int argc, const char **argv) {
@@ -600,16 +640,26 @@
   for (const std::string &Arg : HostLinkerArgs)
     LinkerArgs.push_back(Arg);
 
+  SmallVector<StringRef, 16> LibraryPaths;
+  for (const StringRef Arg : LinkerArgs)
+    if (Arg.startswith("-L"))
+      LibraryPaths.push_back(Arg.drop_front(2));
+
   // Try to extract device code from the linker input and replace the linker
   // input with a new file that has the device section stripped.
   SmallVector<DeviceFile, 4> DeviceFiles;
   for (std::string &Arg : LinkerArgs) {
-    if (sys::path::extension(Arg) == ".o" ||
-        sys::path::extension(Arg) == ".a") {
+    // Search for static libraries in the library link path.
+    std::string Filename = Arg;
+    if (Optional<std::string> Library = searchLibrary(Arg, LibraryPaths))
+      Filename = *Library;
+
+    if (sys::path::extension(Filename) == ".o" ||
+        sys::path::extension(Filename) == ".a") {
       ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
-          MemoryBuffer::getFileOrSTDIN(Arg);
+          MemoryBuffer::getFileOrSTDIN(Filename);
       if (std::error_code EC = BufferOrErr.getError())
-        return reportError(createFileError(Arg, EC));
+        return reportError(createFileError(Filename, EC));
 
       auto NewFileOrErr =
           extractFromBuffer(std::move(*BufferOrErr), DeviceFiles);


Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -65,7 +65,9 @@
 /// Path of the current binary.
 static std::string LinkerExecutable;
 
+/// Temporary files created by the linker wrapper.
 static SmallVector<std::string, 16> TempFiles;
+
 /// Magic section string that marks the existence of offloading data. The
 /// section string will be formatted as `.llvm.offloading.<triple>.<arch>`.
 #define OFFLOAD_SECTION_MAGIC_STR ".llvm.offloading."
@@ -570,6 +572,44 @@
   return static_cast<std::string>(ObjectFile);
 }
 
+Optional<std::string> findFile(StringRef Dir, const Twine &Name) {
+  SmallString<128> Path;
+  // TODO: Parse `--sysroot` somewhere and use it here.
+  sys::path::append(Path, Dir, Name);
+  if (sys::fs::exists(Path))
+    return static_cast<std::string>(Path);
+  return None;
+}
+
+Optional<std::string> findFromSearchPaths(StringRef Name,
+                                          ArrayRef<StringRef> SearchPaths) {
+  for (StringRef Dir : SearchPaths)
+    if (Optional<std::string> File = findFile(Dir, Name))
+      return File;
+  return None;
+}
+
+Optional<std::string> searchLibraryBaseName(StringRef Name,
+                                            ArrayRef<StringRef> SearchPaths) {
+  for (StringRef Dir : SearchPaths) {
+    if (Optional<std::string> File = findFile(Dir, "lib" + Name + ".a"))
+      return File;
+  }
+  return None;
+}
+
+/// Search for static libraries in the linker's library path given input like
+/// `-lfoo` or `-l:libfoo.a`.
+Optional<std::string> searchLibrary(StringRef Input,
+                                    ArrayRef<StringRef> SearchPaths) {
+  if (!Input.startswith("-l"))
+    return None;
+  StringRef Name = Input.drop_front(2);
+  if (Name.startswith(":"))
+    return findFromSearchPaths(Name.drop_front(), SearchPaths);
+  return searchLibraryBaseName(Name, SearchPaths);
+}
+
 } // namespace
 
 int main(int argc, const char **argv) {
@@ -600,16 +640,26 @@
   for (const std::string &Arg : HostLinkerArgs)
     LinkerArgs.push_back(Arg);
 
+  SmallVector<StringRef, 16> LibraryPaths;
+  for (const StringRef Arg : LinkerArgs)
+    if (Arg.startswith("-L"))
+      LibraryPaths.push_back(Arg.drop_front(2));
+
   // Try to extract device code from the linker input and replace the linker
   // input with a new file that has the device section stripped.
   SmallVector<DeviceFile, 4> DeviceFiles;
   for (std::string &Arg : LinkerArgs) {
-    if (sys::path::extension(Arg) == ".o" ||
-        sys::path::extension(Arg) == ".a") {
+    // Search for static libraries in the library link path.
+    std::string Filename = Arg;
+    if (Optional<std::string> Library = searchLibrary(Arg, LibraryPaths))
+      Filename = *Library;
+
+    if (sys::path::extension(Filename) == ".o" ||
+        sys::path::extension(Filename) == ".a") {
       ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
-          MemoryBuffer::getFileOrSTDIN(Arg);
+          MemoryBuffer::getFileOrSTDIN(Filename);
       if (std::error_code EC = BufferOrErr.getError())
-        return reportError(createFileError(Arg, EC));
+        return reportError(createFileError(Filename, EC));
 
       auto NewFileOrErr =
           extractFromBuffer(std::move(*BufferOrErr), DeviceFiles);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to