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 llvm::StringMap<std::string> LibDeviceMap; 111 112 // Libraries that are always linked. 113 SmallString<0> OCML; 114 SmallString<0> OCKL; 115 116 // Libraries that are always linked depending on the language 117 SmallString<0> OpenCL; 118 SmallString<0> HIP; 119 120 // Asan runtime library 121 SmallString<0> AsanRTL; 122 123 // Libraries swapped based on compile flags. 124 ConditionalLibrary WavefrontSize64; 125 ConditionalLibrary FiniteOnly; 126 ConditionalLibrary UnsafeMath; 127 ConditionalLibrary DenormalsAreZero; 128 ConditionalLibrary CorrectlyRoundedSqrt; 129 130 // Maps ABI version to library path. The version number is in the format of 131 // three digits as used in the ABI version library name. 132 std::map<unsigned, std::string> ABIVersionMap; 133 134 // Cache ROCm installation search paths. 135 SmallVector<Candidate, 4> ROCmSearchDirs; 136 bool PrintROCmSearchDirs; 137 bool Verbose; 138 139 bool allGenericLibsValid() const { 140 return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() && 141 WavefrontSize64.isValid() && FiniteOnly.isValid() && 142 UnsafeMath.isValid() && DenormalsAreZero.isValid() && 143 CorrectlyRoundedSqrt.isValid(); 144 } 145 146 void scanLibDevicePath(llvm::StringRef Path); 147 bool parseHIPVersionFile(llvm::StringRef V); 148 const SmallVectorImpl<Candidate> &getInstallationPathCandidates(); 149 150 /// Find the path to a SPACK package under the ROCm candidate installation 151 /// directory if the candidate is a SPACK ROCm candidate. \returns empty 152 /// string if the candidate is not SPACK ROCm candidate or the requested 153 /// package is not found. 154 llvm::SmallString<0> findSPACKPackage(const Candidate &Cand, 155 StringRef PackageName); 156 157 public: 158 RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, 159 const llvm::opt::ArgList &Args, 160 bool DetectHIPRuntime = true, 161 bool DetectDeviceLib = false); 162 163 /// Get file paths of default bitcode libraries common to AMDGPU based 164 /// toolchains. 165 llvm::SmallVector<std::string, 12> 166 getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, 167 StringRef LibDeviceFile, bool Wave64, bool DAZ, 168 bool FiniteOnly, bool UnsafeMathOpt, 169 bool FastRelaxedMath, bool CorrectSqrt, 170 DeviceLibABIVersion ABIVer, bool isOpenMP) const; 171 /// Check file paths of default bitcode libraries common to AMDGPU based 172 /// toolchains. \returns false if there are invalid or missing files. 173 bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, 174 DeviceLibABIVersion ABIVer) const; 175 176 /// Check whether we detected a valid HIP runtime. 177 bool hasHIPRuntime() const { return HasHIPRuntime; } 178 179 /// Check whether we detected a valid ROCm device library. 180 bool hasDeviceLibrary() const { return HasDeviceLibrary; } 181 182 /// Print information about the detected ROCm installation. 183 void print(raw_ostream &OS) const; 184 185 /// Get the detected Rocm install's version. 186 // RocmVersion version() const { return Version; } 187 188 /// Get the detected Rocm installation path. 189 StringRef getInstallPath() const { return InstallPath; } 190 191 /// Get the detected path to Rocm's bin directory. 192 // StringRef getBinPath() const { return BinPath; } 193 194 /// Get the detected Rocm Include path. 195 StringRef getIncludePath() const { return IncludePath; } 196 197 /// Get the detected Rocm library path. 198 StringRef getLibPath() const { return LibPath; } 199 200 /// Get the detected Rocm device library path. 201 StringRef getLibDevicePath() const { return LibDevicePath; } 202 203 StringRef getOCMLPath() const { 204 assert(!OCML.empty()); 205 return OCML; 206 } 207 208 StringRef getOCKLPath() const { 209 assert(!OCKL.empty()); 210 return OCKL; 211 } 212 213 StringRef getOpenCLPath() const { 214 assert(!OpenCL.empty()); 215 return OpenCL; 216 } 217 218 StringRef getHIPPath() const { 219 assert(!HIP.empty()); 220 return HIP; 221 } 222 223 /// Returns empty string of Asan runtime library is not available. 224 StringRef getAsanRTLPath() const { return AsanRTL; } 225 226 StringRef getWavefrontSize64Path(bool Enabled) const { 227 return WavefrontSize64.get(Enabled); 228 } 229 230 StringRef getFiniteOnlyPath(bool Enabled) const { 231 return FiniteOnly.get(Enabled); 232 } 233 234 StringRef getUnsafeMathPath(bool Enabled) const { 235 return UnsafeMath.get(Enabled); 236 } 237 238 StringRef getDenormalsAreZeroPath(bool Enabled) const { 239 return DenormalsAreZero.get(Enabled); 240 } 241 242 StringRef getCorrectlyRoundedSqrtPath(bool Enabled) const { 243 return CorrectlyRoundedSqrt.get(Enabled); 244 } 245 246 StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const { 247 auto Loc = ABIVersionMap.find(ABIVer.ABIVersion); 248 if (Loc == ABIVersionMap.end()) 249 return StringRef(); 250 return Loc->second; 251 } 252 253 /// Get libdevice file for given architecture 254 std::string getLibDeviceFile(StringRef Gpu) const { 255 return LibDeviceMap.lookup(Gpu); 256 } 257 258 void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, 259 llvm::opt::ArgStringList &CC1Args) const; 260 261 void detectDeviceLibrary(); 262 void detectHIPRuntime(); 263 264 /// Get the values for --rocm-device-lib-path arguments 265 std::vector<std::string> getRocmDeviceLibPathArg() const { 266 return RocmDeviceLibPathArg; 267 } 268 269 /// Get the value for --rocm-path argument 270 StringRef getRocmPathArg() const { return RocmPathArg; } 271 272 /// Get the value for --hip-version argument 273 StringRef getHIPVersionArg() const { return HIPVersionArg; } 274 275 std::string getHIPVersion() const { return DetectedVersion; } 276 }; 277 278 } // end namespace driver 279 } // end namespace clang 280 281 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 282