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