xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
15ffd83dbSDimitry Andric //===--- ROCm.h - ROCm installation detector --------------------*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H
105ffd83dbSDimitry Andric #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H
115ffd83dbSDimitry Andric 
125ffd83dbSDimitry Andric #include "clang/Basic/Cuda.h"
135ffd83dbSDimitry Andric #include "clang/Basic/LLVM.h"
145ffd83dbSDimitry Andric #include "clang/Driver/Driver.h"
155ffd83dbSDimitry Andric #include "clang/Driver/Options.h"
165ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h"
185ffd83dbSDimitry Andric #include "llvm/Option/ArgList.h"
195ffd83dbSDimitry Andric #include "llvm/Support/VersionTuple.h"
2006c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
215ffd83dbSDimitry Andric 
225ffd83dbSDimitry Andric namespace clang {
235ffd83dbSDimitry Andric namespace driver {
245ffd83dbSDimitry Andric 
2581ad6265SDimitry Andric /// ABI version of device library.
2681ad6265SDimitry Andric struct DeviceLibABIVersion {
2781ad6265SDimitry Andric   unsigned ABIVersion = 0;
2881ad6265SDimitry Andric   DeviceLibABIVersion(unsigned V) : ABIVersion(V) {}
2981ad6265SDimitry Andric   static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) {
3081ad6265SDimitry Andric     if (CodeObjectVersion < 4)
3181ad6265SDimitry Andric       CodeObjectVersion = 4;
3281ad6265SDimitry Andric     return DeviceLibABIVersion(CodeObjectVersion * 100);
3381ad6265SDimitry Andric   }
3481ad6265SDimitry Andric   /// Whether ABI version bc file is requested.
3581ad6265SDimitry Andric   /// ABIVersion is code object version multiplied by 100. Code object v4
3681ad6265SDimitry Andric   /// and below works with ROCm 5.0 and below which does not have
3781ad6265SDimitry Andric   /// abi_version_*.bc. Code object v5 requires abi_version_500.bc.
3881ad6265SDimitry Andric   bool requiresLibrary() { return ABIVersion >= 500; }
3981ad6265SDimitry Andric   std::string toString() {
4081ad6265SDimitry Andric     assert(ABIVersion % 100 == 0 && "Not supported");
4181ad6265SDimitry Andric     return Twine(ABIVersion / 100).str();
4281ad6265SDimitry Andric   }
4381ad6265SDimitry Andric };
4481ad6265SDimitry Andric 
455ffd83dbSDimitry Andric /// A class to find a viable ROCM installation
465ffd83dbSDimitry Andric /// TODO: Generalize to handle libclc.
475ffd83dbSDimitry Andric class RocmInstallationDetector {
485ffd83dbSDimitry Andric private:
495ffd83dbSDimitry Andric   struct ConditionalLibrary {
505ffd83dbSDimitry Andric     SmallString<0> On;
515ffd83dbSDimitry Andric     SmallString<0> Off;
525ffd83dbSDimitry Andric 
535ffd83dbSDimitry Andric     bool isValid() const { return !On.empty() && !Off.empty(); }
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric     StringRef get(bool Enabled) const {
565ffd83dbSDimitry Andric       assert(isValid());
575ffd83dbSDimitry Andric       return Enabled ? On : Off;
585ffd83dbSDimitry Andric     }
595ffd83dbSDimitry Andric   };
605ffd83dbSDimitry Andric 
615ffd83dbSDimitry Andric   // Installation path candidate.
625ffd83dbSDimitry Andric   struct Candidate {
635ffd83dbSDimitry Andric     llvm::SmallString<0> Path;
645ffd83dbSDimitry Andric     bool StrictChecking;
65fe6060f1SDimitry Andric     // Release string for ROCm packages built with SPACK if not empty. The
66fe6060f1SDimitry Andric     // installation directories of ROCm packages built with SPACK follow the
67fe6060f1SDimitry Andric     // convention <package_name>-<rocm_release_string>-<hash>.
68fe6060f1SDimitry Andric     std::string SPACKReleaseStr;
695ffd83dbSDimitry Andric 
70fe6060f1SDimitry Andric     bool isSPACK() const { return !SPACKReleaseStr.empty(); }
71fe6060f1SDimitry Andric     Candidate(std::string Path, bool StrictChecking = false,
72fe6060f1SDimitry Andric               StringRef SPACKReleaseStr = {})
73fe6060f1SDimitry Andric         : Path(Path), StrictChecking(StrictChecking),
74fe6060f1SDimitry Andric           SPACKReleaseStr(SPACKReleaseStr.str()) {}
755ffd83dbSDimitry Andric   };
765ffd83dbSDimitry Andric 
775ffd83dbSDimitry Andric   const Driver &D;
785ffd83dbSDimitry Andric   bool HasHIPRuntime = false;
795ffd83dbSDimitry Andric   bool HasDeviceLibrary = false;
80*5f757f3fSDimitry Andric   bool HasHIPStdParLibrary = false;
81*5f757f3fSDimitry Andric   bool HasRocThrustLibrary = false;
82*5f757f3fSDimitry Andric   bool HasRocPrimLibrary = false;
835ffd83dbSDimitry Andric 
845ffd83dbSDimitry Andric   // Default version if not detected or specified.
855ffd83dbSDimitry Andric   const unsigned DefaultVersionMajor = 3;
865ffd83dbSDimitry Andric   const unsigned DefaultVersionMinor = 5;
875ffd83dbSDimitry Andric   const char *DefaultVersionPatch = "0";
885ffd83dbSDimitry Andric 
895ffd83dbSDimitry Andric   // The version string in Major.Minor.Patch format.
905ffd83dbSDimitry Andric   std::string DetectedVersion;
915ffd83dbSDimitry Andric   // Version containing major and minor.
925ffd83dbSDimitry Andric   llvm::VersionTuple VersionMajorMinor;
935ffd83dbSDimitry Andric   // Version containing patch.
945ffd83dbSDimitry Andric   std::string VersionPatch;
955ffd83dbSDimitry Andric 
965ffd83dbSDimitry Andric   // ROCm path specified by --rocm-path.
975ffd83dbSDimitry Andric   StringRef RocmPathArg;
985ffd83dbSDimitry Andric   // ROCm device library paths specified by --rocm-device-lib-path.
995ffd83dbSDimitry Andric   std::vector<std::string> RocmDeviceLibPathArg;
100fe6060f1SDimitry Andric   // HIP runtime path specified by --hip-path.
101fe6060f1SDimitry Andric   StringRef HIPPathArg;
102*5f757f3fSDimitry Andric   // HIP Standard Parallel Algorithm acceleration library specified by
103*5f757f3fSDimitry Andric   // --hipstdpar-path
104*5f757f3fSDimitry Andric   StringRef HIPStdParPathArg;
105*5f757f3fSDimitry Andric   // rocThrust algorithm library specified by --hipstdpar-thrust-path
106*5f757f3fSDimitry Andric   StringRef HIPRocThrustPathArg;
107*5f757f3fSDimitry Andric   // rocPrim algorithm library specified by --hipstdpar-prim-path
108*5f757f3fSDimitry Andric   StringRef HIPRocPrimPathArg;
1095ffd83dbSDimitry Andric   // HIP version specified by --hip-version.
1105ffd83dbSDimitry Andric   StringRef HIPVersionArg;
1115ffd83dbSDimitry Andric   // Wheter -nogpulib is specified.
1125ffd83dbSDimitry Andric   bool NoBuiltinLibs = false;
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   // Paths
1155ffd83dbSDimitry Andric   SmallString<0> InstallPath;
1165ffd83dbSDimitry Andric   SmallString<0> BinPath;
1175ffd83dbSDimitry Andric   SmallString<0> LibPath;
1185ffd83dbSDimitry Andric   SmallString<0> LibDevicePath;
1195ffd83dbSDimitry Andric   SmallString<0> IncludePath;
120bdd1243dSDimitry Andric   SmallString<0> SharePath;
1215ffd83dbSDimitry Andric   llvm::StringMap<std::string> LibDeviceMap;
1225ffd83dbSDimitry Andric 
1235ffd83dbSDimitry Andric   // Libraries that are always linked.
1245ffd83dbSDimitry Andric   SmallString<0> OCML;
1255ffd83dbSDimitry Andric   SmallString<0> OCKL;
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric   // Libraries that are always linked depending on the language
1285ffd83dbSDimitry Andric   SmallString<0> OpenCL;
1295ffd83dbSDimitry Andric   SmallString<0> HIP;
1305ffd83dbSDimitry Andric 
131fe6060f1SDimitry Andric   // Asan runtime library
132fe6060f1SDimitry Andric   SmallString<0> AsanRTL;
133fe6060f1SDimitry Andric 
1345ffd83dbSDimitry Andric   // Libraries swapped based on compile flags.
1355ffd83dbSDimitry Andric   ConditionalLibrary WavefrontSize64;
1365ffd83dbSDimitry Andric   ConditionalLibrary FiniteOnly;
1375ffd83dbSDimitry Andric   ConditionalLibrary UnsafeMath;
1385ffd83dbSDimitry Andric   ConditionalLibrary DenormalsAreZero;
1395ffd83dbSDimitry Andric   ConditionalLibrary CorrectlyRoundedSqrt;
1405ffd83dbSDimitry Andric 
14181ad6265SDimitry Andric   // Maps ABI version to library path. The version number is in the format of
14281ad6265SDimitry Andric   // three digits as used in the ABI version library name.
14381ad6265SDimitry Andric   std::map<unsigned, std::string> ABIVersionMap;
14481ad6265SDimitry Andric 
145fe6060f1SDimitry Andric   // Cache ROCm installation search paths.
146fe6060f1SDimitry Andric   SmallVector<Candidate, 4> ROCmSearchDirs;
147fe6060f1SDimitry Andric   bool PrintROCmSearchDirs;
148fe6060f1SDimitry Andric   bool Verbose;
149fe6060f1SDimitry Andric 
1505ffd83dbSDimitry Andric   bool allGenericLibsValid() const {
1515ffd83dbSDimitry Andric     return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() &&
1525ffd83dbSDimitry Andric            WavefrontSize64.isValid() && FiniteOnly.isValid() &&
1535ffd83dbSDimitry Andric            UnsafeMath.isValid() && DenormalsAreZero.isValid() &&
1545ffd83dbSDimitry Andric            CorrectlyRoundedSqrt.isValid();
1555ffd83dbSDimitry Andric   }
1565ffd83dbSDimitry Andric 
1575ffd83dbSDimitry Andric   void scanLibDevicePath(llvm::StringRef Path);
158e8d8bef9SDimitry Andric   bool parseHIPVersionFile(llvm::StringRef V);
159fe6060f1SDimitry Andric   const SmallVectorImpl<Candidate> &getInstallationPathCandidates();
160fe6060f1SDimitry Andric 
161fe6060f1SDimitry Andric   /// Find the path to a SPACK package under the ROCm candidate installation
162fe6060f1SDimitry Andric   /// directory if the candidate is a SPACK ROCm candidate. \returns empty
163fe6060f1SDimitry Andric   /// string if the candidate is not SPACK ROCm candidate or the requested
164fe6060f1SDimitry Andric   /// package is not found.
165fe6060f1SDimitry Andric   llvm::SmallString<0> findSPACKPackage(const Candidate &Cand,
166fe6060f1SDimitry Andric                                         StringRef PackageName);
1675ffd83dbSDimitry Andric 
1685ffd83dbSDimitry Andric public:
1695ffd83dbSDimitry Andric   RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
1705ffd83dbSDimitry Andric                            const llvm::opt::ArgList &Args,
1715ffd83dbSDimitry Andric                            bool DetectHIPRuntime = true,
1725ffd83dbSDimitry Andric                            bool DetectDeviceLib = false);
1735ffd83dbSDimitry Andric 
174fe6060f1SDimitry Andric   /// Get file paths of default bitcode libraries common to AMDGPU based
175fe6060f1SDimitry Andric   /// toolchains.
176fe6060f1SDimitry Andric   llvm::SmallVector<std::string, 12>
177fe6060f1SDimitry Andric   getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs,
178fe6060f1SDimitry Andric                        StringRef LibDeviceFile, bool Wave64, bool DAZ,
179fe6060f1SDimitry Andric                        bool FiniteOnly, bool UnsafeMathOpt,
18081ad6265SDimitry Andric                        bool FastRelaxedMath, bool CorrectSqrt,
18181ad6265SDimitry Andric                        DeviceLibABIVersion ABIVer, bool isOpenMP) const;
18281ad6265SDimitry Andric   /// Check file paths of default bitcode libraries common to AMDGPU based
18381ad6265SDimitry Andric   /// toolchains. \returns false if there are invalid or missing files.
18481ad6265SDimitry Andric   bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile,
18581ad6265SDimitry Andric                               DeviceLibABIVersion ABIVer) const;
1865ffd83dbSDimitry Andric 
1875ffd83dbSDimitry Andric   /// Check whether we detected a valid HIP runtime.
1885ffd83dbSDimitry Andric   bool hasHIPRuntime() const { return HasHIPRuntime; }
1895ffd83dbSDimitry Andric 
1905ffd83dbSDimitry Andric   /// Check whether we detected a valid ROCm device library.
1915ffd83dbSDimitry Andric   bool hasDeviceLibrary() const { return HasDeviceLibrary; }
1925ffd83dbSDimitry Andric 
193*5f757f3fSDimitry Andric   /// Check whether we detected a valid HIP STDPAR Acceleration library.
194*5f757f3fSDimitry Andric   bool hasHIPStdParLibrary() const { return HasHIPStdParLibrary; }
195*5f757f3fSDimitry Andric 
1965ffd83dbSDimitry Andric   /// Print information about the detected ROCm installation.
1975ffd83dbSDimitry Andric   void print(raw_ostream &OS) const;
1985ffd83dbSDimitry Andric 
1995ffd83dbSDimitry Andric   /// Get the detected Rocm install's version.
2005ffd83dbSDimitry Andric   // RocmVersion version() const { return Version; }
2015ffd83dbSDimitry Andric 
2025ffd83dbSDimitry Andric   /// Get the detected Rocm installation path.
2035ffd83dbSDimitry Andric   StringRef getInstallPath() const { return InstallPath; }
2045ffd83dbSDimitry Andric 
2055ffd83dbSDimitry Andric   /// Get the detected path to Rocm's bin directory.
2065ffd83dbSDimitry Andric   // StringRef getBinPath() const { return BinPath; }
2075ffd83dbSDimitry Andric 
2085ffd83dbSDimitry Andric   /// Get the detected Rocm Include path.
2095ffd83dbSDimitry Andric   StringRef getIncludePath() const { return IncludePath; }
2105ffd83dbSDimitry Andric 
2115ffd83dbSDimitry Andric   /// Get the detected Rocm library path.
2125ffd83dbSDimitry Andric   StringRef getLibPath() const { return LibPath; }
2135ffd83dbSDimitry Andric 
2145ffd83dbSDimitry Andric   /// Get the detected Rocm device library path.
2155ffd83dbSDimitry Andric   StringRef getLibDevicePath() const { return LibDevicePath; }
2165ffd83dbSDimitry Andric 
2175ffd83dbSDimitry Andric   StringRef getOCMLPath() const {
2185ffd83dbSDimitry Andric     assert(!OCML.empty());
2195ffd83dbSDimitry Andric     return OCML;
2205ffd83dbSDimitry Andric   }
2215ffd83dbSDimitry Andric 
2225ffd83dbSDimitry Andric   StringRef getOCKLPath() const {
2235ffd83dbSDimitry Andric     assert(!OCKL.empty());
2245ffd83dbSDimitry Andric     return OCKL;
2255ffd83dbSDimitry Andric   }
2265ffd83dbSDimitry Andric 
2275ffd83dbSDimitry Andric   StringRef getOpenCLPath() const {
2285ffd83dbSDimitry Andric     assert(!OpenCL.empty());
2295ffd83dbSDimitry Andric     return OpenCL;
2305ffd83dbSDimitry Andric   }
2315ffd83dbSDimitry Andric 
2325ffd83dbSDimitry Andric   StringRef getHIPPath() const {
2335ffd83dbSDimitry Andric     assert(!HIP.empty());
2345ffd83dbSDimitry Andric     return HIP;
2355ffd83dbSDimitry Andric   }
2365ffd83dbSDimitry Andric 
237fe6060f1SDimitry Andric   /// Returns empty string of Asan runtime library is not available.
238fe6060f1SDimitry Andric   StringRef getAsanRTLPath() const { return AsanRTL; }
239fe6060f1SDimitry Andric 
2405ffd83dbSDimitry Andric   StringRef getWavefrontSize64Path(bool Enabled) const {
2415ffd83dbSDimitry Andric     return WavefrontSize64.get(Enabled);
2425ffd83dbSDimitry Andric   }
2435ffd83dbSDimitry Andric 
2445ffd83dbSDimitry Andric   StringRef getFiniteOnlyPath(bool Enabled) const {
2455ffd83dbSDimitry Andric     return FiniteOnly.get(Enabled);
2465ffd83dbSDimitry Andric   }
2475ffd83dbSDimitry Andric 
2485ffd83dbSDimitry Andric   StringRef getUnsafeMathPath(bool Enabled) const {
2495ffd83dbSDimitry Andric     return UnsafeMath.get(Enabled);
2505ffd83dbSDimitry Andric   }
2515ffd83dbSDimitry Andric 
2525ffd83dbSDimitry Andric   StringRef getDenormalsAreZeroPath(bool Enabled) const {
2535ffd83dbSDimitry Andric     return DenormalsAreZero.get(Enabled);
2545ffd83dbSDimitry Andric   }
2555ffd83dbSDimitry Andric 
2565ffd83dbSDimitry Andric   StringRef getCorrectlyRoundedSqrtPath(bool Enabled) const {
2575ffd83dbSDimitry Andric     return CorrectlyRoundedSqrt.get(Enabled);
2585ffd83dbSDimitry Andric   }
2595ffd83dbSDimitry Andric 
26081ad6265SDimitry Andric   StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const {
26181ad6265SDimitry Andric     auto Loc = ABIVersionMap.find(ABIVer.ABIVersion);
26281ad6265SDimitry Andric     if (Loc == ABIVersionMap.end())
26381ad6265SDimitry Andric       return StringRef();
26481ad6265SDimitry Andric     return Loc->second;
26581ad6265SDimitry Andric   }
26681ad6265SDimitry Andric 
2675ffd83dbSDimitry Andric   /// Get libdevice file for given architecture
268bdd1243dSDimitry Andric   StringRef getLibDeviceFile(StringRef Gpu) const {
269bdd1243dSDimitry Andric     auto Loc = LibDeviceMap.find(Gpu);
270bdd1243dSDimitry Andric     if (Loc == LibDeviceMap.end())
271bdd1243dSDimitry Andric       return "";
272bdd1243dSDimitry Andric     return Loc->second;
2735ffd83dbSDimitry Andric   }
2745ffd83dbSDimitry Andric 
2755ffd83dbSDimitry Andric   void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2765ffd83dbSDimitry Andric                          llvm::opt::ArgStringList &CC1Args) const;
2775ffd83dbSDimitry Andric 
2785ffd83dbSDimitry Andric   void detectDeviceLibrary();
2795ffd83dbSDimitry Andric   void detectHIPRuntime();
2805ffd83dbSDimitry Andric 
2815ffd83dbSDimitry Andric   /// Get the values for --rocm-device-lib-path arguments
282bdd1243dSDimitry Andric   ArrayRef<std::string> getRocmDeviceLibPathArg() const {
2835ffd83dbSDimitry Andric     return RocmDeviceLibPathArg;
2845ffd83dbSDimitry Andric   }
2855ffd83dbSDimitry Andric 
2865ffd83dbSDimitry Andric   /// Get the value for --rocm-path argument
2875ffd83dbSDimitry Andric   StringRef getRocmPathArg() const { return RocmPathArg; }
2885ffd83dbSDimitry Andric 
2895ffd83dbSDimitry Andric   /// Get the value for --hip-version argument
2905ffd83dbSDimitry Andric   StringRef getHIPVersionArg() const { return HIPVersionArg; }
2915ffd83dbSDimitry Andric 
292bdd1243dSDimitry Andric   StringRef getHIPVersion() const { return DetectedVersion; }
2935ffd83dbSDimitry Andric };
2945ffd83dbSDimitry Andric 
2955ffd83dbSDimitry Andric } // end namespace driver
2965ffd83dbSDimitry Andric } // end namespace clang
2975ffd83dbSDimitry Andric 
2985ffd83dbSDimitry Andric #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H
299