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