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