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