11#include "clang/Config/config.h"
18#include "llvm/ADT/SmallSet.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Support/Error.h"
22#include "llvm/Support/LineIterator.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/Process.h"
25#include "llvm/Support/VirtualFileSystem.h"
26#include "llvm/TargetParser/AMDGPUTargetParser.h"
27#include "llvm/TargetParser/Host.h"
29#include <system_error>
37RocmInstallationDetector::CommonBitcodeLibsPreferences::
38 CommonBitcodeLibsPreferences(
const Driver &D,
39 const llvm::opt::ArgList &DriverArgs,
42 const bool NeedsASanRT)
45 const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
46 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
50 const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
52 !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
53 options::OPT_mno_wavefrontsize64,
false);
60 const bool DefaultDAZ =
61 (Kind == llvm::AMDGPU::GK_NONE)
63 : !((ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_FMA_F32) &&
64 (ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_DENORMAL_F32));
67 DAZ = IsKnownOffloading
68 ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
69 options::OPT_fno_gpu_flush_denormals_to_zero,
71 : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
73 FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
74 DriverArgs.hasFlag(options::OPT_ffinite_math_only,
75 options::OPT_fno_finite_math_only,
false);
78 DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
79 DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
80 options::OPT_fno_unsafe_math_optimizations,
false);
82 FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
83 DriverArgs.hasFlag(options::OPT_ffast_math,
84 options::OPT_fno_fast_math,
false);
88 GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
89 options::OPT_fno_gpu_sanitize,
true) &&
93void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
94 assert(!Path.empty());
96 const StringRef Suffix(
".bc");
97 const StringRef Suffix2(
".amdgcn.bc");
100 for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
101 !EC && LI != LE; LI = LI.increment(EC)) {
102 StringRef FilePath = LI->path();
103 StringRef
FileName = llvm::sys::path::filename(FilePath);
109 BaseName =
FileName.drop_back(Suffix2.size());
110 else if (
FileName.ends_with(Suffix))
111 BaseName =
FileName.drop_back(Suffix.size());
113 const StringRef ABIVersionPrefix =
"oclc_abi_version_";
114 if (BaseName ==
"ocml") {
116 }
else if (BaseName ==
"ockl") {
118 }
else if (BaseName ==
"opencl") {
120 }
else if (BaseName ==
"asanrtl") {
122 }
else if (BaseName ==
"oclc_finite_only_off") {
123 FiniteOnly.Off = FilePath;
124 }
else if (BaseName ==
"oclc_finite_only_on") {
125 FiniteOnly.On = FilePath;
126 }
else if (BaseName ==
"oclc_unsafe_math_on") {
127 UnsafeMath.On = FilePath;
128 }
else if (BaseName ==
"oclc_unsafe_math_off") {
129 UnsafeMath.Off = FilePath;
130 }
else if (BaseName ==
"oclc_wavefrontsize64_on") {
131 WavefrontSize64.On = FilePath;
132 }
else if (BaseName ==
"oclc_wavefrontsize64_off") {
133 WavefrontSize64.Off = FilePath;
134 }
else if (BaseName.starts_with(ABIVersionPrefix)) {
135 unsigned ABIVersionNumber;
136 if (BaseName.drop_front(ABIVersionPrefix.size())
137 .getAsInteger(0, ABIVersionNumber))
139 ABIVersionMap[ABIVersionNumber] = FilePath.str();
143 const StringRef DeviceLibPrefix =
"oclc_isa_version_";
144 if (!BaseName.starts_with(DeviceLibPrefix))
147 StringRef IsaVersionNumber =
148 BaseName.drop_front(DeviceLibPrefix.size());
150 llvm::Twine GfxName = Twine(
"gfx") + IsaVersionNumber;
152 LibDeviceMap.insert({GfxName.toStringRef(Tmp), FilePath.str()});
159bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef
V) {
160 SmallVector<StringRef, 4> VersionParts;
161 V.split(VersionParts,
'\n');
162 unsigned Major = ~0U;
163 unsigned Minor = ~0U;
164 for (
auto Part : VersionParts) {
165 auto Splits = Part.rtrim().split(
'=');
166 if (Splits.first ==
"HIP_VERSION_MAJOR") {
167 if (Splits.second.getAsInteger(0, Major))
169 }
else if (Splits.first ==
"HIP_VERSION_MINOR") {
170 if (Splits.second.getAsInteger(0, Minor))
172 }
else if (Splits.first ==
"HIP_VERSION_PATCH")
173 VersionPatch = Splits.second.str();
175 if (Major == ~0U || Minor == ~0U)
177 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
179 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
185const SmallVectorImpl<RocmInstallationDetector::Candidate> &
186RocmInstallationDetector::getInstallationPathCandidates() {
189 if (!ROCmSearchDirs.empty())
190 return ROCmSearchDirs;
192 auto DoPrintROCmSearchDirs = [&]() {
193 if (PrintROCmSearchDirs)
194 for (
auto Cand : ROCmSearchDirs) {
195 llvm::errs() <<
"ROCm installation search path: " << Cand.Path <<
'\n';
201 if (!RocmPathArg.empty()) {
202 ROCmSearchDirs.emplace_back(RocmPathArg.str());
203 DoPrintROCmSearchDirs();
204 return ROCmSearchDirs;
205 }
else if (std::optional<std::string> RocmPathEnv =
206 llvm::sys::Process::GetEnv(
"ROCM_PATH")) {
207 if (!RocmPathEnv->empty()) {
208 ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
209 DoPrintROCmSearchDirs();
210 return ROCmSearchDirs;
215 StringRef InstallDir = D.Dir;
220 auto DeduceROCmPath = [](StringRef ClangPath) {
222 StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
223 StringRef ParentName = llvm::sys::path::filename(ParentDir);
226 if (ParentName ==
"bin") {
227 ParentDir = llvm::sys::path::parent_path(ParentDir);
228 ParentName = llvm::sys::path::filename(ParentDir);
233 if (ParentName ==
"llvm" || ParentName.starts_with(
"aomp")) {
234 ParentDir = llvm::sys::path::parent_path(ParentDir);
235 ParentName = llvm::sys::path::filename(ParentDir);
239 if (ParentName ==
"lib")
240 ParentDir = llvm::sys::path::parent_path(ParentDir);
243 return Candidate(ParentDir.str(),
true);
248 ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
252 llvm::SmallString<256> RealClangPath;
253 llvm::sys::fs::real_path(D.getDriverProgramPath(), RealClangPath);
254 auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
255 if (ParentPath != InstallDir)
256 ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
259 auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
260 auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
261 ROCmSearchDirs.emplace_back(ClangRoot.str(),
true);
262 if (RealClangRoot != ClangRoot)
263 ROCmSearchDirs.emplace_back(RealClangRoot.str(),
true);
264 ROCmSearchDirs.emplace_back(D.ResourceDir,
267 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/rocm",
272 std::string LatestROCm;
273 llvm::VersionTuple LatestVer;
275 auto GetROCmVersion = [](StringRef DirName) {
276 llvm::VersionTuple
V;
277 std::string VerStr = DirName.drop_front(strlen(
"rocm-")).str();
280 llvm::replace(VerStr,
'-',
'.');
284 for (llvm::vfs::directory_iterator
285 File = D.getVFS().dir_begin(D.SysRoot +
"/opt", EC),
287 File != FileEnd && !EC;
File.increment(EC)) {
288 llvm::StringRef
FileName = llvm::sys::path::filename(
File->path());
291 if (LatestROCm.empty()) {
293 LatestVer = GetROCmVersion(LatestROCm);
296 auto Ver = GetROCmVersion(
FileName);
297 if (LatestVer < Ver) {
302 if (!LatestROCm.empty())
303 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/" + LatestROCm,
306 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr/local",
308 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr",
311 DoPrintROCmSearchDirs();
312 return ROCmSearchDirs;
316 const Driver &D,
const llvm::Triple &HostTriple,
317 const llvm::opt::ArgList &Args,
bool DetectHIPRuntime)
319 Verbose = Args.hasArg(options::OPT_v);
320 RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
321 PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
322 RocmDeviceLibPathArg =
323 Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
324 HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
325 HIPStdParPathArg = Args.getLastArgValue(options::OPT_hipstdpar_path_EQ);
326 HasHIPStdParLibrary =
327 !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
328 "/hipstdpar_lib.hpp");
329 HIPRocThrustPathArg =
330 Args.getLastArgValue(options::OPT_hipstdpar_thrust_path_EQ);
331 HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
332 D.getVFS().exists(HIPRocThrustPathArg +
"/thrust");
333 HIPRocPrimPathArg = Args.getLastArgValue(options::OPT_hipstdpar_prim_path_EQ);
334 HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
335 D.getVFS().exists(HIPRocPrimPathArg +
"/rocprim");
337 if (
auto *A = Args.getLastArg(options::OPT_hip_version_EQ)) {
338 HIPVersionArg = A->getValue();
339 unsigned Major = ~0U;
340 unsigned Minor = ~0U;
341 SmallVector<StringRef, 3> Parts;
342 HIPVersionArg.split(Parts,
'.');
344 Parts[0].getAsInteger(0, Major);
345 if (Parts.size() > 1)
346 Parts[1].getAsInteger(0, Minor);
347 if (Parts.size() > 2)
348 VersionPatch = Parts[2].str();
349 if (VersionPatch.empty())
351 if (Major != ~0U && Minor == ~0U)
353 if (Major == ~0U || Minor == ~0U)
354 D.Diag(diag::err_drv_invalid_value)
355 << A->getAsString(Args) << HIPVersionArg;
357 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
359 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
361 VersionPatch = DefaultVersionPatch;
363 llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
364 DetectedVersion = (Twine(DefaultVersionMajor) +
"." +
365 Twine(DefaultVersionMinor) +
"." + VersionPatch)
369 if (DetectHIPRuntime)
374 assert(LibDevicePath.empty());
376 if (!RocmDeviceLibPathArg.empty())
377 LibDevicePath = RocmDeviceLibPathArg.back();
378 else if (std::optional<std::string> LibPathEnv =
379 llvm::sys::Process::GetEnv(
"HIP_DEVICE_LIB_PATH"))
380 LibDevicePath = std::move(*LibPathEnv);
382 auto &FS = D.getVFS();
383 if (!LibDevicePath.empty()) {
387 if (!FS.exists(LibDevicePath))
390 scanLibDevicePath(LibDevicePath);
391 HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
396 auto CheckDeviceLib = [&](StringRef Path,
bool StrictChecking) {
397 bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
398 if (CheckLibDevice && !FS.exists(Path))
401 scanLibDevicePath(Path);
403 if (!NoBuiltinLibs) {
405 if (!allGenericLibsValid())
410 if (LibDeviceMap.empty())
417 LibDevicePath = D.ResourceDir;
418 llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
419 "amdgcn",
"bitcode");
420 HasDeviceLibrary = CheckDeviceLib(LibDevicePath,
true);
421 if (HasDeviceLibrary)
426 auto &ROCmDirs = getInstallationPathCandidates();
427 for (
const auto &Candidate : ROCmDirs) {
428 LibDevicePath = Candidate.Path;
429 llvm::sys::path::append(LibDevicePath,
"amdgcn",
"bitcode");
430 HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
431 if (HasDeviceLibrary)
438 if (!HIPPathArg.empty())
439 HIPSearchDirs.emplace_back(HIPPathArg.str());
440 else if (std::optional<std::string> HIPPathEnv =
441 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
442 if (!HIPPathEnv->empty())
443 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
445 if (HIPSearchDirs.empty())
446 HIPSearchDirs.append(getInstallationPathCandidates());
447 auto &FS = D.getVFS();
449 for (
const auto &Candidate : HIPSearchDirs) {
450 InstallPath = Candidate.Path;
451 if (InstallPath.empty() || !FS.exists(InstallPath))
454 BinPath = InstallPath;
455 llvm::sys::path::append(BinPath,
"bin");
456 IncludePath = InstallPath;
457 llvm::sys::path::append(IncludePath,
"include");
458 LibPath = InstallPath;
459 llvm::sys::path::append(LibPath,
"lib");
460 SharePath = InstallPath;
461 llvm::sys::path::append(SharePath,
"share");
464 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
465 llvm::sys::path::append(ParentSharePath,
"share");
468 const Twine &c =
"",
const Twine &d =
"") {
470 llvm::sys::path::append(newpath, a, b, c, d);
474 std::vector<SmallString<0>> VersionFilePaths = {
475 Append(SharePath,
"hip",
"version"),
476 InstallPath != D.SysRoot +
"/usr/local"
477 ?
Append(ParentSharePath,
"hip",
"version")
479 Append(BinPath,
".hipVersion")};
481 for (
const auto &VersionFilePath : VersionFilePaths) {
482 if (VersionFilePath.empty())
484 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
485 FS.getBufferForFile(VersionFilePath);
488 if (HIPVersionArg.empty() && VersionFile)
489 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
492 HasHIPRuntime =
true;
497 if (!Candidate.StrictChecking) {
498 HasHIPRuntime =
true;
502 HasHIPRuntime =
false;
507 OS <<
"Found HIP installation: " << InstallPath <<
", version "
508 << DetectedVersion <<
'\n';
512 ArgStringList &CC1Args)
const {
513 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
514 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
515 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
517 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
532 if (UsesRuntimeWrapper)
533 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
534 CC1Args.push_back(
"-internal-isystem");
535 CC1Args.push_back(DriverArgs.MakeArgString(P));
538 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
540 auto &FS = D.getVFS();
543 if (!HIPStdParPathArg.empty() ||
544 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
545 D.Diag(diag::err_drv_no_hipstdpar_lib);
548 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
549 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
552 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
553 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
556 const char *ThrustPath;
557 if (HasRocThrustLibrary)
558 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
560 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
562 const char *HIPStdParPath;
564 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
566 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
567 "/system/hip/hipstdpar");
569 const char *PrimPath;
570 if (HasRocPrimLibrary)
571 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
573 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
575 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
576 "-idirafter", HIPStdParPath,
"-include",
577 "hipstdpar_lib.hpp"});
580 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
589 D.Diag(diag::err_drv_no_hip_runtime);
593 CC1Args.push_back(
"-idirafter");
595 if (UsesRuntimeWrapper)
596 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
605 const char *LinkingOutput)
const {
607 ArgStringList CmdArgs;
608 if (!Args.hasArg(options::OPT_r)) {
609 CmdArgs.push_back(
"--no-undefined");
610 CmdArgs.push_back(
"-shared");
616 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
617 CmdArgs.push_back(Args.MakeArgString(
618 "-plugin-opt=mcpu=" +
620 Args.getLastArgValue(options::OPT_mcpu_EQ))));
624 Args.AddAllArgs(CmdArgs, options::OPT_L);
628 std::vector<StringRef> Features;
631 if (!Features.empty()) {
633 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
639 if (Args.hasArg(options::OPT_stdlib))
640 CmdArgs.append({
"-lc",
"-lm"});
641 if (Args.hasArg(options::OPT_startfiles)) {
642 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
644 IncludePath =
"/lib";
646 llvm::sys::path::append(P,
"crt1.o");
647 CmdArgs.push_back(Args.MakeArgString(P));
650 CmdArgs.push_back(
"-o");
652 C.addCommand(std::make_unique<Command>(
654 CmdArgs, Inputs, Output));
658 const llvm::Triple &Triple,
659 const llvm::opt::ArgList &Args,
660 std::vector<StringRef> &Features) {
661 if (Args.hasFlag(options::OPT_mwavefrontsize64,
662 options::OPT_mno_wavefrontsize64,
false))
663 Features.push_back(
"+wavefrontsize64");
665 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
666 options::OPT_mno_amdgpu_precise_memory_op,
false))
667 Features.push_back(
"+precise-memory");
670 options::OPT_m_amdgpu_Features_Group);
678 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}) {
679 loadMultilibsFromYAML(Args, D);
695 DerivedArgList *DAL =
698 DAL =
new DerivedArgList(Args.getBaseArgs());
707 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
708 DAL->eraseArg(options::OPT_march_EQ);
709 if (!DAL->hasArg(options::OPT_mcpu_EQ))
710 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
716 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
717 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
718 DAL->eraseArg(options::OPT_mcpu_EQ);
722 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
724 auto &GPUs = *GPUsOrErr;
725 if (!llvm::all_equal(GPUs))
727 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
728 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
729 Args.MakeArgString(GPUs.front()));
733 if (!BoundArch.empty()) {
734 DAL->eraseArg(options::OPT_mcpu_EQ);
735 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
744 auto XnackIt = FeatureMap.find(
"xnack");
745 if (XnackIt != FeatureMap.end()) {
746 DAL->AddFlagArg(
nullptr,
747 Opts.getOption(XnackIt->second ? options::OPT_mxnack
748 : options::OPT_mno_xnack));
751 auto SrameccIt = FeatureMap.find(
"sramecc");
752 if (SrameccIt != FeatureMap.end()) {
753 DAL->AddFlagArg(
nullptr, Opts.getOption(SrameccIt->second
754 ? options::OPT_msramecc
755 : options::OPT_mno_sramecc));
759 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
763 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
766 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
768 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
776 llvm::AMDGPU::GPUKind Kind) {
779 if (Kind == llvm::AMDGPU::GK_NONE)
782 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
786 const bool BothDenormAndFMAFast =
787 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
788 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
789 return !BothDenormAndFMAFast;
793 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
794 const llvm::fltSemantics *FPType)
const {
796 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
797 return llvm::DenormalMode::getIEEE();
802 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
803 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
804 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
805 options::OPT_fno_gpu_flush_denormals_to_zero,
807 return llvm::DenormalMode::getPreserveSign();
809 return llvm::DenormalMode::getIEEE();
812 const StringRef GpuArch =
getGPUArch(DriverArgs);
813 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
817 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
822 return DAZ ? llvm::DenormalMode::getPreserveSign() :
823 llvm::DenormalMode::getIEEE();
827 llvm::AMDGPU::GPUKind Kind) {
828 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
829 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
831 return !HasWave32 || DriverArgs.hasFlag(
832 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
840 if (Triple.getEnvironment() != llvm::Triple::LLVM)
847 DerivedArgList *DAL =
851 for (Arg *A : Args) {
853 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
855 bool IsExplicitDevice =
856 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
858 ? diag::err_drv_unsupported_option_for_target
859 : diag::warn_drv_unsupported_option_for_target)
860 << A->getAsString(Args) <<
getTriple().str();
868 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
873 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
874 options::OPT_fvisibility_ms_compat) &&
876 CC1Args.push_back(
"-fvisibility=hidden");
877 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
891 !DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
892 CC1Args.push_back(
"-disable-llvm-optzns");
901 CC1Args.push_back(
"-Werror=atomic-alignment");
905 ArgStringList &CC1Args)
const {
906 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
907 DriverArgs.hasArg(options::OPT_nostdlibinc))
916 llvm::sys::path::append(Dir, M.includeSuffix());
929 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
934 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
935 if (TargetID.empty())
938 llvm::StringMap<bool> FeatureMap;
940 if (!OptionalGpuArch)
941 return {TargetID.str(), std::nullopt, std::nullopt};
943 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
949 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
951 << *PTID.OptionalTargetID;
960 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
961 Program = A->getValue();
967 return StdoutOrErr.takeError();
970 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
972 GPUArchs.push_back(
Arch.str());
974 if (GPUArchs.empty())
975 return llvm::createStringError(std::error_code(),
976 "No AMD GPU detected in the system");
978 return std::move(GPUArchs);
982 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
985 DeviceOffloadingKind);
990 DriverArgs.hasArg(options::OPT_nostdlib))
993 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1005 if (TT.getEnvironment() == llvm::Triple::LLVM)
1011 StringRef TargetID = BoundArch.empty()
1012 ? DriverArgs.getLastArgValue(options::OPT_mcpu_EQ)
1020 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1029 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
1033 for (
auto [BCFile, Internalize] : BCLibs) {
1035 CC1Args.push_back(
"-mlink-builtin-bitcode");
1037 CC1Args.push_back(
"-mlink-bitcode-file");
1038 CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
1043 StringRef GPUArch, StringRef LibDeviceFile,
1046 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1049 if (LibDeviceFile.empty()) {
1050 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1057 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1059 D.Diag(diag::err_drv_no_rocm_device_lib)
1060 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1068 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1070 const bool NeedsASanRT)
const {
1073 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1074 DeviceOffloadingKind, NeedsASanRT};
1077 bool Internalize =
true) {
1078 if (!BCLib.
Path.empty()) {
1080 BCLibs.emplace_back(BCLib);
1083 auto AddSanBCLibs = [&]() {
1092 else if (Pref.GPUSan && Pref.IsOpenMP)
1097 AddBCLib(LibDeviceFile);
1099 if (!ABIVerPath.empty())
1100 AddBCLib(ABIVerPath);
1107 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1109 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1110 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1120 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1128 auto ProcKind = TT.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
1129 : llvm::AMDGPU::parseArchR600(Processor);
1130 auto Features = TT.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
1131 : llvm::AMDGPU::getArchAttrR600(ProcKind);
1134 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1135 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1140 llvm::StringMap<bool> FeatureMap;
1141 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1142 if (!OptionalGpuArch)
1144 auto Loc = FeatureMap.find(
"xnack");
1145 return (Loc != FeatureMap.end() && Loc->second);
1156 SupportedMask |= SanitizerKind::Address;
1158 return SupportedMask;
1162 StringRef BoundArch)
const {
1164 if ((Kinds & SanitizerKind::Address) && !BoundArch.empty() &&
static StringRef getTriple(const Command &Job)
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)
const char * getOffloadingArch() const
OffloadKind getOffloadingDeviceKind() const
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > executeProgram(llvm::ArrayRef< llvm::StringRef > Args) const
DiagnosticBuilder Diag(unsigned DiagID) const
const llvm::opt::OptTable & getOpts() const
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
StringRef getIncludePath() const
Get the detected path to Rocm's bin directory.
StringRef getUnsafeMathPath(bool Enabled) const
StringRef getOCMLPath() const
StringRef getAsanRTLPath() const
Returns empty string of Asan runtime library is not available.
RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args, bool DetectHIPRuntime=true)
StringRef getOCKLPath() const
StringRef getFiniteOnlyPath(bool Enabled) const
bool hasDeviceLibrary() const
Check whether we detected a valid ROCm device library.
bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, DeviceLibABIVersion ABIVer) const
Check file paths of default bitcode libraries common to AMDGPU based toolchains.
bool hasHIPStdParLibrary() const
Check whether we detected a valid HIP STDPAR Acceleration library.
StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const
llvm::SmallVector< ToolChain::BitCodeLibraryInfo, 12 > getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, StringRef GPUArch, const Action::OffloadKind DeviceOffloadingKind, const bool NeedsASanRT) const
Get file paths of default bitcode libraries common to AMDGPU based toolchains.
bool hasHIPRuntime() const
Check whether we detected a valid HIP runtime.
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const
void detectDeviceLibrary()
StringRef getWavefrontSize64Path(bool Enabled) const
void print(raw_ostream &OS) const
Print information about the detected ROCm installation.
SmallVector< InputInfo, 4 > InputInfoList
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
std::optional< llvm::StringRef > parseTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch, llvm::StringMap< bool > *FeatureMap)
Parse a target ID to get processor and feature map.
llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch)
Get processor name from target ID.
Diagnostic wrappers for TextAPI types for error reporting.
ABI version of device library.
unsigned getAsCodeObjectVersion() const
static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion)
bool requiresLibrary()
Whether ABI version bc file is requested.
static constexpr ResponseFileSupport AtFileCurCP()