1ec727ea7Spatrick //===--- ROCm.h - ROCm installation detector --------------------*- C++ -*-===// 2ec727ea7Spatrick // 3ec727ea7Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ec727ea7Spatrick // See https://llvm.org/LICENSE.txt for license information. 5ec727ea7Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ec727ea7Spatrick // 7ec727ea7Spatrick //===----------------------------------------------------------------------===// 8ec727ea7Spatrick 9ec727ea7Spatrick #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 10ec727ea7Spatrick #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 11ec727ea7Spatrick 12ec727ea7Spatrick #include "clang/Basic/Cuda.h" 13ec727ea7Spatrick #include "clang/Basic/LLVM.h" 14ec727ea7Spatrick #include "clang/Driver/Driver.h" 15ec727ea7Spatrick #include "clang/Driver/Options.h" 16ec727ea7Spatrick #include "llvm/ADT/SmallString.h" 17ec727ea7Spatrick #include "llvm/ADT/StringMap.h" 18ec727ea7Spatrick #include "llvm/ADT/Triple.h" 19ec727ea7Spatrick #include "llvm/Option/ArgList.h" 20ec727ea7Spatrick #include "llvm/Support/VersionTuple.h" 21ec727ea7Spatrick 22ec727ea7Spatrick namespace clang { 23ec727ea7Spatrick namespace driver { 24ec727ea7Spatrick 25*12c85518Srobert /// ABI version of device library. 26*12c85518Srobert struct DeviceLibABIVersion { 27*12c85518Srobert unsigned ABIVersion = 0; DeviceLibABIVersionDeviceLibABIVersion28*12c85518Srobert DeviceLibABIVersion(unsigned V) : ABIVersion(V) {} fromCodeObjectVersionDeviceLibABIVersion29*12c85518Srobert static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) { 30*12c85518Srobert if (CodeObjectVersion < 4) 31*12c85518Srobert CodeObjectVersion = 4; 32*12c85518Srobert return DeviceLibABIVersion(CodeObjectVersion * 100); 33*12c85518Srobert } 34*12c85518Srobert /// Whether ABI version bc file is requested. 35*12c85518Srobert /// ABIVersion is code object version multiplied by 100. Code object v4 36*12c85518Srobert /// and below works with ROCm 5.0 and below which does not have 37*12c85518Srobert /// abi_version_*.bc. Code object v5 requires abi_version_500.bc. requiresLibraryDeviceLibABIVersion38*12c85518Srobert bool requiresLibrary() { return ABIVersion >= 500; } toStringDeviceLibABIVersion39*12c85518Srobert std::string toString() { 40*12c85518Srobert assert(ABIVersion % 100 == 0 && "Not supported"); 41*12c85518Srobert return Twine(ABIVersion / 100).str(); 42*12c85518Srobert } 43*12c85518Srobert }; 44*12c85518Srobert 45ec727ea7Spatrick /// A class to find a viable ROCM installation 46ec727ea7Spatrick /// TODO: Generalize to handle libclc. 47ec727ea7Spatrick class RocmInstallationDetector { 48ec727ea7Spatrick private: 49ec727ea7Spatrick struct ConditionalLibrary { 50ec727ea7Spatrick SmallString<0> On; 51ec727ea7Spatrick SmallString<0> Off; 52ec727ea7Spatrick isValidConditionalLibrary53ec727ea7Spatrick bool isValid() const { return !On.empty() && !Off.empty(); } 54ec727ea7Spatrick getConditionalLibrary55ec727ea7Spatrick StringRef get(bool Enabled) const { 56ec727ea7Spatrick assert(isValid()); 57ec727ea7Spatrick return Enabled ? On : Off; 58ec727ea7Spatrick } 59ec727ea7Spatrick }; 60ec727ea7Spatrick 61ec727ea7Spatrick // Installation path candidate. 62ec727ea7Spatrick struct Candidate { 63ec727ea7Spatrick llvm::SmallString<0> Path; 64ec727ea7Spatrick bool StrictChecking; 65a9ac8606Spatrick // Release string for ROCm packages built with SPACK if not empty. The 66a9ac8606Spatrick // installation directories of ROCm packages built with SPACK follow the 67a9ac8606Spatrick // convention <package_name>-<rocm_release_string>-<hash>. 68a9ac8606Spatrick std::string SPACKReleaseStr; 69ec727ea7Spatrick isSPACKCandidate70a9ac8606Spatrick bool isSPACK() const { return !SPACKReleaseStr.empty(); } 71a9ac8606Spatrick Candidate(std::string Path, bool StrictChecking = false, 72a9ac8606Spatrick StringRef SPACKReleaseStr = {}) PathCandidate73a9ac8606Spatrick : Path(Path), StrictChecking(StrictChecking), 74a9ac8606Spatrick SPACKReleaseStr(SPACKReleaseStr.str()) {} 75ec727ea7Spatrick }; 76ec727ea7Spatrick 77ec727ea7Spatrick const Driver &D; 78ec727ea7Spatrick bool HasHIPRuntime = false; 79ec727ea7Spatrick bool HasDeviceLibrary = false; 80ec727ea7Spatrick 81ec727ea7Spatrick // Default version if not detected or specified. 82ec727ea7Spatrick const unsigned DefaultVersionMajor = 3; 83ec727ea7Spatrick const unsigned DefaultVersionMinor = 5; 84ec727ea7Spatrick const char *DefaultVersionPatch = "0"; 85ec727ea7Spatrick 86ec727ea7Spatrick // The version string in Major.Minor.Patch format. 87ec727ea7Spatrick std::string DetectedVersion; 88ec727ea7Spatrick // Version containing major and minor. 89ec727ea7Spatrick llvm::VersionTuple VersionMajorMinor; 90ec727ea7Spatrick // Version containing patch. 91ec727ea7Spatrick std::string VersionPatch; 92ec727ea7Spatrick 93ec727ea7Spatrick // ROCm path specified by --rocm-path. 94ec727ea7Spatrick StringRef RocmPathArg; 95ec727ea7Spatrick // ROCm device library paths specified by --rocm-device-lib-path. 96ec727ea7Spatrick std::vector<std::string> RocmDeviceLibPathArg; 97a9ac8606Spatrick // HIP runtime path specified by --hip-path. 98a9ac8606Spatrick StringRef HIPPathArg; 99ec727ea7Spatrick // HIP version specified by --hip-version. 100ec727ea7Spatrick StringRef HIPVersionArg; 101ec727ea7Spatrick // Wheter -nogpulib is specified. 102ec727ea7Spatrick bool NoBuiltinLibs = false; 103ec727ea7Spatrick 104ec727ea7Spatrick // Paths 105ec727ea7Spatrick SmallString<0> InstallPath; 106ec727ea7Spatrick SmallString<0> BinPath; 107ec727ea7Spatrick SmallString<0> LibPath; 108ec727ea7Spatrick SmallString<0> LibDevicePath; 109ec727ea7Spatrick SmallString<0> IncludePath; 110*12c85518Srobert SmallString<0> SharePath; 111ec727ea7Spatrick llvm::StringMap<std::string> LibDeviceMap; 112ec727ea7Spatrick 113ec727ea7Spatrick // Libraries that are always linked. 114ec727ea7Spatrick SmallString<0> OCML; 115ec727ea7Spatrick SmallString<0> OCKL; 116ec727ea7Spatrick 117ec727ea7Spatrick // Libraries that are always linked depending on the language 118ec727ea7Spatrick SmallString<0> OpenCL; 119ec727ea7Spatrick SmallString<0> HIP; 120ec727ea7Spatrick 121a9ac8606Spatrick // Asan runtime library 122a9ac8606Spatrick SmallString<0> AsanRTL; 123a9ac8606Spatrick 124ec727ea7Spatrick // Libraries swapped based on compile flags. 125ec727ea7Spatrick ConditionalLibrary WavefrontSize64; 126ec727ea7Spatrick ConditionalLibrary FiniteOnly; 127ec727ea7Spatrick ConditionalLibrary UnsafeMath; 128ec727ea7Spatrick ConditionalLibrary DenormalsAreZero; 129ec727ea7Spatrick ConditionalLibrary CorrectlyRoundedSqrt; 130ec727ea7Spatrick 131*12c85518Srobert // Maps ABI version to library path. The version number is in the format of 132*12c85518Srobert // three digits as used in the ABI version library name. 133*12c85518Srobert std::map<unsigned, std::string> ABIVersionMap; 134*12c85518Srobert 135a9ac8606Spatrick // Cache ROCm installation search paths. 136a9ac8606Spatrick SmallVector<Candidate, 4> ROCmSearchDirs; 137a9ac8606Spatrick bool PrintROCmSearchDirs; 138a9ac8606Spatrick bool Verbose; 139a9ac8606Spatrick allGenericLibsValid()140ec727ea7Spatrick bool allGenericLibsValid() const { 141ec727ea7Spatrick return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() && 142ec727ea7Spatrick WavefrontSize64.isValid() && FiniteOnly.isValid() && 143ec727ea7Spatrick UnsafeMath.isValid() && DenormalsAreZero.isValid() && 144ec727ea7Spatrick CorrectlyRoundedSqrt.isValid(); 145ec727ea7Spatrick } 146ec727ea7Spatrick 147ec727ea7Spatrick void scanLibDevicePath(llvm::StringRef Path); 148a9ac8606Spatrick bool parseHIPVersionFile(llvm::StringRef V); 149a9ac8606Spatrick const SmallVectorImpl<Candidate> &getInstallationPathCandidates(); 150a9ac8606Spatrick 151a9ac8606Spatrick /// Find the path to a SPACK package under the ROCm candidate installation 152a9ac8606Spatrick /// directory if the candidate is a SPACK ROCm candidate. \returns empty 153a9ac8606Spatrick /// string if the candidate is not SPACK ROCm candidate or the requested 154a9ac8606Spatrick /// package is not found. 155a9ac8606Spatrick llvm::SmallString<0> findSPACKPackage(const Candidate &Cand, 156a9ac8606Spatrick StringRef PackageName); 157ec727ea7Spatrick 158ec727ea7Spatrick public: 159ec727ea7Spatrick RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, 160ec727ea7Spatrick const llvm::opt::ArgList &Args, 161ec727ea7Spatrick bool DetectHIPRuntime = true, 162ec727ea7Spatrick bool DetectDeviceLib = false); 163ec727ea7Spatrick 164a9ac8606Spatrick /// Get file paths of default bitcode libraries common to AMDGPU based 165a9ac8606Spatrick /// toolchains. 166a9ac8606Spatrick llvm::SmallVector<std::string, 12> 167a9ac8606Spatrick getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, 168a9ac8606Spatrick StringRef LibDeviceFile, bool Wave64, bool DAZ, 169a9ac8606Spatrick bool FiniteOnly, bool UnsafeMathOpt, 170*12c85518Srobert bool FastRelaxedMath, bool CorrectSqrt, 171*12c85518Srobert DeviceLibABIVersion ABIVer, bool isOpenMP) const; 172*12c85518Srobert /// Check file paths of default bitcode libraries common to AMDGPU based 173*12c85518Srobert /// toolchains. \returns false if there are invalid or missing files. 174*12c85518Srobert bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, 175*12c85518Srobert DeviceLibABIVersion ABIVer) const; 176ec727ea7Spatrick 177ec727ea7Spatrick /// Check whether we detected a valid HIP runtime. hasHIPRuntime()178ec727ea7Spatrick bool hasHIPRuntime() const { return HasHIPRuntime; } 179ec727ea7Spatrick 180ec727ea7Spatrick /// Check whether we detected a valid ROCm device library. hasDeviceLibrary()181ec727ea7Spatrick bool hasDeviceLibrary() const { return HasDeviceLibrary; } 182ec727ea7Spatrick 183ec727ea7Spatrick /// Print information about the detected ROCm installation. 184ec727ea7Spatrick void print(raw_ostream &OS) const; 185ec727ea7Spatrick 186ec727ea7Spatrick /// Get the detected Rocm install's version. 187ec727ea7Spatrick // RocmVersion version() const { return Version; } 188ec727ea7Spatrick 189ec727ea7Spatrick /// Get the detected Rocm installation path. getInstallPath()190ec727ea7Spatrick StringRef getInstallPath() const { return InstallPath; } 191ec727ea7Spatrick 192ec727ea7Spatrick /// Get the detected path to Rocm's bin directory. 193ec727ea7Spatrick // StringRef getBinPath() const { return BinPath; } 194ec727ea7Spatrick 195ec727ea7Spatrick /// Get the detected Rocm Include path. getIncludePath()196ec727ea7Spatrick StringRef getIncludePath() const { return IncludePath; } 197ec727ea7Spatrick 198ec727ea7Spatrick /// Get the detected Rocm library path. getLibPath()199ec727ea7Spatrick StringRef getLibPath() const { return LibPath; } 200ec727ea7Spatrick 201ec727ea7Spatrick /// Get the detected Rocm device library path. getLibDevicePath()202ec727ea7Spatrick StringRef getLibDevicePath() const { return LibDevicePath; } 203ec727ea7Spatrick getOCMLPath()204ec727ea7Spatrick StringRef getOCMLPath() const { 205ec727ea7Spatrick assert(!OCML.empty()); 206ec727ea7Spatrick return OCML; 207ec727ea7Spatrick } 208ec727ea7Spatrick getOCKLPath()209ec727ea7Spatrick StringRef getOCKLPath() const { 210ec727ea7Spatrick assert(!OCKL.empty()); 211ec727ea7Spatrick return OCKL; 212ec727ea7Spatrick } 213ec727ea7Spatrick getOpenCLPath()214ec727ea7Spatrick StringRef getOpenCLPath() const { 215ec727ea7Spatrick assert(!OpenCL.empty()); 216ec727ea7Spatrick return OpenCL; 217ec727ea7Spatrick } 218ec727ea7Spatrick getHIPPath()219ec727ea7Spatrick StringRef getHIPPath() const { 220ec727ea7Spatrick assert(!HIP.empty()); 221ec727ea7Spatrick return HIP; 222ec727ea7Spatrick } 223ec727ea7Spatrick 224a9ac8606Spatrick /// Returns empty string of Asan runtime library is not available. getAsanRTLPath()225a9ac8606Spatrick StringRef getAsanRTLPath() const { return AsanRTL; } 226a9ac8606Spatrick getWavefrontSize64Path(bool Enabled)227ec727ea7Spatrick StringRef getWavefrontSize64Path(bool Enabled) const { 228ec727ea7Spatrick return WavefrontSize64.get(Enabled); 229ec727ea7Spatrick } 230ec727ea7Spatrick getFiniteOnlyPath(bool Enabled)231ec727ea7Spatrick StringRef getFiniteOnlyPath(bool Enabled) const { 232ec727ea7Spatrick return FiniteOnly.get(Enabled); 233ec727ea7Spatrick } 234ec727ea7Spatrick getUnsafeMathPath(bool Enabled)235ec727ea7Spatrick StringRef getUnsafeMathPath(bool Enabled) const { 236ec727ea7Spatrick return UnsafeMath.get(Enabled); 237ec727ea7Spatrick } 238ec727ea7Spatrick getDenormalsAreZeroPath(bool Enabled)239ec727ea7Spatrick StringRef getDenormalsAreZeroPath(bool Enabled) const { 240ec727ea7Spatrick return DenormalsAreZero.get(Enabled); 241ec727ea7Spatrick } 242ec727ea7Spatrick getCorrectlyRoundedSqrtPath(bool Enabled)243ec727ea7Spatrick StringRef getCorrectlyRoundedSqrtPath(bool Enabled) const { 244ec727ea7Spatrick return CorrectlyRoundedSqrt.get(Enabled); 245ec727ea7Spatrick } 246ec727ea7Spatrick getABIVersionPath(DeviceLibABIVersion ABIVer)247*12c85518Srobert StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const { 248*12c85518Srobert auto Loc = ABIVersionMap.find(ABIVer.ABIVersion); 249*12c85518Srobert if (Loc == ABIVersionMap.end()) 250*12c85518Srobert return StringRef(); 251*12c85518Srobert return Loc->second; 252*12c85518Srobert } 253*12c85518Srobert 254ec727ea7Spatrick /// Get libdevice file for given architecture getLibDeviceFile(StringRef Gpu)255*12c85518Srobert StringRef getLibDeviceFile(StringRef Gpu) const { 256*12c85518Srobert auto Loc = LibDeviceMap.find(Gpu); 257*12c85518Srobert if (Loc == LibDeviceMap.end()) 258*12c85518Srobert return ""; 259*12c85518Srobert return Loc->second; 260ec727ea7Spatrick } 261ec727ea7Spatrick 262ec727ea7Spatrick void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, 263ec727ea7Spatrick llvm::opt::ArgStringList &CC1Args) const; 264ec727ea7Spatrick 265ec727ea7Spatrick void detectDeviceLibrary(); 266ec727ea7Spatrick void detectHIPRuntime(); 267ec727ea7Spatrick 268ec727ea7Spatrick /// Get the values for --rocm-device-lib-path arguments getRocmDeviceLibPathArg()269*12c85518Srobert ArrayRef<std::string> getRocmDeviceLibPathArg() const { 270ec727ea7Spatrick return RocmDeviceLibPathArg; 271ec727ea7Spatrick } 272ec727ea7Spatrick 273ec727ea7Spatrick /// Get the value for --rocm-path argument getRocmPathArg()274ec727ea7Spatrick StringRef getRocmPathArg() const { return RocmPathArg; } 275ec727ea7Spatrick 276ec727ea7Spatrick /// Get the value for --hip-version argument getHIPVersionArg()277ec727ea7Spatrick StringRef getHIPVersionArg() const { return HIPVersionArg; } 278ec727ea7Spatrick getHIPVersion()279*12c85518Srobert StringRef getHIPVersion() const { return DetectedVersion; } 280ec727ea7Spatrick }; 281ec727ea7Spatrick 282ec727ea7Spatrick } // end namespace driver 283ec727ea7Spatrick } // end namespace clang 284ec727ea7Spatrick 285ec727ea7Spatrick #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 286