diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp index 08c647dfcb6f72..82f56277bf7d24 100644 --- a/clang/lib/Driver/ToolChains/HIPUtility.cpp +++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp @@ -52,13 +52,16 @@ static std::string normalizeForBundler(const llvm::Triple &T, // input object or archive files. class HIPUndefinedFatBinSymbols { public: - HIPUndefinedFatBinSymbols(const Compilation &C) - : C(C), DiagID(C.getDriver().getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Error collecting HIP undefined fatbin symbols: %0")), + HIPUndefinedFatBinSymbols(const Compilation &C, + const llvm::opt::ArgList &Args_) + : C(C), Args(Args_), + DiagID(C.getDriver().getDiags().getCustomDiagID( + DiagnosticsEngine::Error, + "Error collecting HIP undefined fatbin symbols: %0")), Quiet(C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)), Verbose(C.getArgs().hasArg(options::OPT_v)) { populateSymbols(); + processStaticLibraries(); if (Verbose) { for (auto Name : FatBinSymbols) llvm::errs() << "Found undefined HIP fatbin symbol: " << Name << "\n"; @@ -76,8 +79,70 @@ class HIPUndefinedFatBinSymbols { return GPUBinHandleSymbols; } + // Collect symbols from static libraries specified by -l options. + void processStaticLibraries() { + llvm::SmallVector LibNames; + llvm::SmallVector LibPaths; + llvm::SmallVector ExactLibNames; + llvm::Triple Triple(C.getDriver().getTargetTriple()); + bool IsMSVC = Triple.isWindowsMSVCEnvironment(); + llvm::StringRef Ext = IsMSVC ? ".lib" : ".a"; + + for (const auto *Arg : Args.filtered(options::OPT_l)) { + llvm::StringRef Value = Arg->getValue(); + if (Value.starts_with(":")) + ExactLibNames.push_back(Value.drop_front()); + else + LibNames.push_back(Value); + } + for (const auto *Arg : Args.filtered(options::OPT_L)) { + auto Path = Arg->getValue(); + LibPaths.push_back(Path); + if (Verbose) + llvm::errs() << "HIP fatbin symbol search uses library path: " << Path + << "\n"; + } + + auto ProcessLib = [&](llvm::StringRef LibName, bool IsExact) { + llvm::SmallString<256> FullLibName( + IsExact ? Twine(LibName).str() + : IsMSVC ? (Twine(LibName) + Ext).str() + : (Twine("lib") + LibName + Ext).str()); + + bool Found = false; + for (const auto Path : LibPaths) { + llvm::SmallString<256> FullPath = Path; + llvm::sys::path::append(FullPath, FullLibName); + + if (llvm::sys::fs::exists(FullPath)) { + if (Verbose) + llvm::errs() << "HIP fatbin symbol search found library: " + << FullPath << "\n"; + auto BufferOrErr = llvm::MemoryBuffer::getFile(FullPath); + if (!BufferOrErr) { + errorHandler(llvm::errorCodeToError(BufferOrErr.getError())); + continue; + } + processInput(BufferOrErr.get()->getMemBufferRef()); + Found = true; + break; + } + } + if (!Found && Verbose) + llvm::errs() << "HIP fatbin symbol search could not find library: " + << FullLibName << "\n"; + }; + + for (const auto LibName : ExactLibNames) + ProcessLib(LibName, true); + + for (const auto LibName : LibNames) + ProcessLib(LibName, false); + } + private: const Compilation &C; + const llvm::opt::ArgList &Args; unsigned DiagID; bool Quiet; bool Verbose; @@ -301,7 +366,7 @@ void HIP::constructGenerateObjFileFromHIPFatBinary( auto HostTriple = C.getSingleOffloadToolChain()->getTriple(); - HIPUndefinedFatBinSymbols Symbols(C); + HIPUndefinedFatBinSymbols Symbols(C, Args); std::string PrimaryHipFatbinSymbol; std::string PrimaryGpuBinHandleSymbol; diff --git a/clang/test/Driver/hip-toolchain-rdc.hip b/clang/test/Driver/hip-toolchain-rdc.hip index d19d8ccd6cb29e..ada12135649a69 100644 --- a/clang/test/Driver/hip-toolchain-rdc.hip +++ b/clang/test/Driver/hip-toolchain-rdc.hip @@ -23,6 +23,29 @@ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,MSVC %s +// Test fatbin symbol search for -l libraries. + +// RUN: touch librdctest.a rdctest2.bin +// RUN: %clang -### --target=x86_64-linux-gnu -v \ +// RUN: -fgpu-rdc -nogpuinc -nogpulib \ +// RUN: --no-offload-new-driver -L. -lrdctest -l:rdctest2.bin \ +// RUN: %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=LIB,LNX-LIB %s +// RUN: rm librdctest.a rdctest2.bin + +// RUN: touch rdctest.lib rdctest2.bin +// RUN: %clang -### --target=x86_64-pc-windows-msvc -v \ +// RUN: -fgpu-rdc -nogpuinc -nogpulib \ +// RUN: --no-offload-new-driver -L. -lrdctest -l:rdctest2.bin \ +// RUN: %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=LIB,MSVC-LIB %s +// RUN: rm rdctest.lib rdctest2.bin + +// LIB: HIP fatbin symbol search uses library path: . +// LIB: HIP fatbin symbol search found library: .{{/|\\}}rdctest2.bin +// LNX-LIB: HIP fatbin symbol search found library: .{{/|\\}}librdctest.a +// MSVC-LIB: HIP fatbin symbol search found library: .{{/|\\}}rdctest.lib + // check HIP fatbin and gpubin handle symbols and code object alignment in dumped llvm-mc input // CHECK: Found undefined HIP fatbin symbol: __hip_fatbin_[[ID1:[0-9a-f]+]] // CHECK: Found undefined HIP fatbin symbol: __hip_fatbin_[[ID2:[0-9a-f]+]]