Index: clang/lib/Driver/ToolChains/AMDGPU.cpp =================================================================== --- clang/lib/Driver/ToolChains/AMDGPU.cpp +++ clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -89,6 +89,25 @@ } } +void RocmInstallationDetector::ParseHIPVersionFile(llvm::StringRef V) { + SmallVector VersionParts; + V.split(VersionParts, '\n'); + unsigned Major; + unsigned Minor; + for (auto Part : VersionParts) { + auto Splits = Part.split('='); + if (Splits.first == "HIP_VERSION_MAJOR") + Splits.second.getAsInteger(0, Major); + else if (Splits.first == "HIP_VERSION_MINOR") + Splits.second.getAsInteger(0, Minor); + else if (Splits.first == "HIP_VERSION_PATCH") + VersionPatch = Splits.second.str(); + } + VersionMajorMinor = llvm::VersionTuple(Major, Minor); + DetectedVersion = + (Twine(Major) + "." + Twine(Minor) + "." + VersionPatch).str(); +} + RocmInstallationDetector::RocmInstallationDetector( const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args) @@ -133,6 +152,33 @@ Candidates.emplace_back(D.SysRoot + "/opt/rocm"); } + auto &FS = D.getVFS(); + + for (const auto &Candidate : Candidates) { + InstallPath = Candidate.Path; + if (InstallPath.empty() || !FS.exists(InstallPath)) + continue; + + llvm::sys::path::append(BinPath, InstallPath, "bin"); + llvm::sys::path::append(IncludePath, InstallPath, "include"); + llvm::sys::path::append(LibPath, InstallPath, "lib"); + + llvm::ErrorOr> VersionFile = + FS.getBufferForFile(BinPath + "/.hipVersion"); + if (!VersionFile) + continue; + + ParseHIPVersionFile((*VersionFile)->getBuffer()); + IsValid = true; + return; + } + IsValid = false; +} + +void RocmInstallationDetector::detectDeviceLibrary( + const llvm::opt::ArgList &Args) { + if (!IsValid) + return; bool NoBuiltinLibs = Args.hasArg(options::OPT_nogpulib); assert(LibDevicePath.empty()); @@ -157,56 +203,52 @@ return; } - for (const auto &Candidate : Candidates) { - InstallPath = Candidate.Path; - if (InstallPath.empty() || !FS.exists(InstallPath)) - continue; - - // The install path situation in old versions of ROCm is a real mess, and - // use a different install layout. Multiple copies of the device libraries - // exist for each frontend project, and differ depending on which build - // system produced the packages. Standalone OpenCL builds also have a - // different directory structure from the ROCm OpenCL package. - // - // The desired structure is (${ROCM_ROOT} or - // ${OPENCL_ROOT})/amdgcn/bitcode/*, so try to detect this layout. - - // BinPath = InstallPath + "/bin"; - llvm::sys::path::append(IncludePath, InstallPath, "include"); - llvm::sys::path::append(LibDevicePath, InstallPath, "amdgcn", "bitcode"); - - // We don't need the include path for OpenCL, since clang already ships with - // the default header. - - bool CheckLibDevice = (!NoBuiltinLibs || Candidate.StrictChecking); + // The install path situation in old versions of ROCm is a real mess, and + // use a different install layout. Multiple copies of the device libraries + // exist for each frontend project, and differ depending on which build + // system produced the packages. Standalone OpenCL builds also have a + // different directory structure from the ROCm OpenCL package. + // + // The desired structure is ${ROCM_ROOT})/amdgcn/bitcode/* or + // ${ROCM_ROOT}/lib/* so try to detect this layout. + + auto CheckDeviceLib = [&]() { + bool CheckLibDevice = !NoBuiltinLibs; if (CheckLibDevice && !FS.exists(LibDevicePath)) - continue; + return false; scanLibDevicePath(); if (!NoBuiltinLibs) { // Check that the required non-target libraries are all available. if (!allGenericLibsValid()) - continue; + return false; // Check that we have found at least one libdevice that we can link in if // -nobuiltinlib hasn't been specified. if (LibDeviceMap.empty()) - continue; + return false; } - - IsValid = true; - break; - } + return true; + }; + llvm::sys::path::append(LibDevicePath, InstallPath, "amdgcn", "bitcode"); + IsValid = CheckDeviceLib(); + if (IsValid) + return; + llvm::sys::path::append(LibDevicePath, InstallPath, "lib"); + IsValid = CheckDeviceLib(); } void RocmInstallationDetector::print(raw_ostream &OS) const { if (isValid()) - OS << "Found ROCm installation: " << InstallPath << '\n'; + OS << "Found ROCm installation: " << InstallPath << ", version " + << DetectedVersion << '\n'; } void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (VersionMajorMinor <= llvm::VersionTuple(3, 5)) + return; if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { // HIP header includes standard library wrapper headers under clang // cuda_wrappers directory. Since these wrapper headers include_next @@ -385,8 +427,9 @@ /// ROCM Toolchain ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : AMDGPUToolChain(D, Triple, Args), - RocmInstallation(D, Triple, Args) { } + : AMDGPUToolChain(D, Triple, Args), RocmInstallation(D, Triple, Args) { + RocmInstallation.detectDeviceLibrary(Args); +} void AMDGPUToolChain::addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -2656,6 +2656,7 @@ // Print the information about how we detected the GCC installation. GCCInstallation.print(OS); CudaInstallation.print(OS); + RocmInstallation.print(OS); } bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const { Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -805,6 +805,7 @@ void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { CudaInstallation.print(OS); + RocmInstallation.print(OS); } // Windows SDKs and VC Toolchains group their contents into subdirectories based Index: clang/lib/Driver/ToolChains/ROCm.h =================================================================== --- clang/lib/Driver/ToolChains/ROCm.h +++ clang/lib/Driver/ToolChains/ROCm.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/VersionTuple.h" namespace clang { namespace driver { @@ -38,11 +39,17 @@ } }; + const Driver &D; bool IsValid = false; - // RocmVersion Version = RocmVersion::UNKNOWN; + // The version string in Major.Minor.Path format. + std::string DetectedVersion; + // Version containing major and minor. + llvm::VersionTuple VersionMajorMinor; + // Version containing patch. + std::string VersionPatch; SmallString<0> InstallPath; - // SmallString<0> BinPath; + SmallString<0> BinPath; SmallString<0> LibPath; SmallString<0> LibDevicePath; SmallString<0> IncludePath; @@ -75,6 +82,7 @@ mutable llvm::SmallSet ArchsWithBadVersion; void scanLibDevicePath(); + void ParseHIPVersionFile(llvm::StringRef V); public: RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, @@ -163,6 +171,8 @@ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + + void detectDeviceLibrary(const llvm::opt::ArgList &Args); }; } // end namespace driver Index: clang/test/Driver/Inputs/rocm/bin/.hipVersion =================================================================== --- /dev/null +++ clang/test/Driver/Inputs/rocm/bin/.hipVersion @@ -0,0 +1,4 @@ +# Auto-generated by cmake +HIP_VERSION_MAJOR=3 +HIP_VERSION_MINOR=6 +HIP_VERSION_PATCH=20214-a2917cd