xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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