12#include "clang/Config/config.h"
19#include "llvm/ADT/SmallSet.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/Option/ArgList.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/LineIterator.h"
24#include "llvm/Support/Path.h"
25#include "llvm/Support/Process.h"
26#include "llvm/Support/VirtualFileSystem.h"
27#include "llvm/TargetParser/AMDGPUTargetParser.h"
28#include "llvm/TargetParser/Host.h"
30#include <system_error>
38RocmInstallationDetector::CommonBitcodeLibsPreferences::
39 CommonBitcodeLibsPreferences(
const Driver &D,
40 const llvm::opt::ArgList &DriverArgs,
43 const bool NeedsASanRT)
46 const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
47 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
51 const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
53 !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
54 options::OPT_mno_wavefrontsize64,
false);
61 const bool DefaultDAZ =
62 (Kind == llvm::AMDGPU::GK_NONE)
64 : !((ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_FMA_F32) &&
65 (ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_DENORMAL_F32));
68 DAZ = IsKnownOffloading
69 ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
70 options::OPT_fno_gpu_flush_denormals_to_zero,
72 : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
74 FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
75 DriverArgs.hasFlag(options::OPT_ffinite_math_only,
76 options::OPT_fno_finite_math_only,
false);
79 DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
80 DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
81 options::OPT_fno_unsafe_math_optimizations,
false);
83 FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
84 DriverArgs.hasFlag(options::OPT_ffast_math,
85 options::OPT_fno_fast_math,
false);
89 GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
90 options::OPT_fno_gpu_sanitize,
true) &&
94void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
95 assert(!Path.empty());
97 const StringRef Suffix(
".bc");
98 const StringRef Suffix2(
".amdgcn.bc");
101 for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
102 !EC && LI != LE; LI = LI.increment(EC)) {
103 StringRef FilePath = LI->path();
104 StringRef
FileName = llvm::sys::path::filename(FilePath);
110 BaseName =
FileName.drop_back(Suffix2.size());
111 else if (
FileName.ends_with(Suffix))
112 BaseName =
FileName.drop_back(Suffix.size());
114 const StringRef ABIVersionPrefix =
"oclc_abi_version_";
115 if (BaseName ==
"ocml") {
117 }
else if (BaseName ==
"ockl") {
119 }
else if (BaseName ==
"opencl") {
121 }
else if (BaseName ==
"asanrtl") {
123 }
else if (BaseName ==
"oclc_finite_only_off") {
124 FiniteOnly.Off = FilePath;
125 }
else if (BaseName ==
"oclc_finite_only_on") {
126 FiniteOnly.On = FilePath;
127 }
else if (BaseName ==
"oclc_unsafe_math_on") {
128 UnsafeMath.On = FilePath;
129 }
else if (BaseName ==
"oclc_unsafe_math_off") {
130 UnsafeMath.Off = FilePath;
131 }
else if (BaseName ==
"oclc_wavefrontsize64_on") {
132 WavefrontSize64.On = FilePath;
133 }
else if (BaseName ==
"oclc_wavefrontsize64_off") {
134 WavefrontSize64.Off = FilePath;
135 }
else if (BaseName.starts_with(ABIVersionPrefix)) {
136 unsigned ABIVersionNumber;
137 if (BaseName.drop_front(ABIVersionPrefix.size())
138 .getAsInteger(0, ABIVersionNumber))
140 ABIVersionMap[ABIVersionNumber] = FilePath.str();
144 const StringRef DeviceLibPrefix =
"oclc_isa_version_";
145 if (!BaseName.starts_with(DeviceLibPrefix))
148 StringRef IsaVersionNumber =
149 BaseName.drop_front(DeviceLibPrefix.size());
151 llvm::Twine GfxName = Twine(
"gfx") + IsaVersionNumber;
153 LibDeviceMap.insert({GfxName.toStringRef(Tmp), FilePath.str()});
160bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef
V) {
161 SmallVector<StringRef, 4> VersionParts;
162 V.split(VersionParts,
'\n');
163 unsigned Major = ~0U;
164 unsigned Minor = ~0U;
165 for (
auto Part : VersionParts) {
166 auto Splits = Part.rtrim().split(
'=');
167 if (Splits.first ==
"HIP_VERSION_MAJOR") {
168 if (Splits.second.getAsInteger(0, Major))
170 }
else if (Splits.first ==
"HIP_VERSION_MINOR") {
171 if (Splits.second.getAsInteger(0, Minor))
173 }
else if (Splits.first ==
"HIP_VERSION_PATCH")
174 VersionPatch = Splits.second.str();
176 if (Major == ~0U || Minor == ~0U)
178 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
180 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
186const SmallVectorImpl<RocmInstallationDetector::Candidate> &
187RocmInstallationDetector::getInstallationPathCandidates() {
190 if (!ROCmSearchDirs.empty())
191 return ROCmSearchDirs;
193 auto DoPrintROCmSearchDirs = [&]() {
194 if (PrintROCmSearchDirs)
195 for (
auto Cand : ROCmSearchDirs) {
196 llvm::errs() <<
"ROCm installation search path: " << Cand.Path <<
'\n';
202 if (!RocmPathArg.empty()) {
203 ROCmSearchDirs.emplace_back(RocmPathArg.str());
204 DoPrintROCmSearchDirs();
205 return ROCmSearchDirs;
206 }
else if (std::optional<std::string> RocmPathEnv =
207 llvm::sys::Process::GetEnv(
"ROCM_PATH")) {
208 if (!RocmPathEnv->empty()) {
209 ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
210 DoPrintROCmSearchDirs();
211 return ROCmSearchDirs;
216 StringRef InstallDir = D.Dir;
221 auto DeduceROCmPath = [](StringRef ClangPath) {
223 StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
224 StringRef ParentName = llvm::sys::path::filename(ParentDir);
227 if (ParentName ==
"bin") {
228 ParentDir = llvm::sys::path::parent_path(ParentDir);
229 ParentName = llvm::sys::path::filename(ParentDir);
234 if (ParentName ==
"llvm" || ParentName.starts_with(
"aomp")) {
235 ParentDir = llvm::sys::path::parent_path(ParentDir);
236 ParentName = llvm::sys::path::filename(ParentDir);
240 if (ParentName ==
"lib")
241 ParentDir = llvm::sys::path::parent_path(ParentDir);
244 return Candidate(ParentDir.str(),
true);
249 ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
253 llvm::SmallString<256> RealClangPath;
254 llvm::sys::fs::real_path(D.getDriverProgramPath(), RealClangPath);
255 auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
256 if (ParentPath != InstallDir)
257 ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
260 auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
261 auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
262 ROCmSearchDirs.emplace_back(ClangRoot.str(),
true);
263 if (RealClangRoot != ClangRoot)
264 ROCmSearchDirs.emplace_back(RealClangRoot.str(),
true);
265 ROCmSearchDirs.emplace_back(D.ResourceDir,
268 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/rocm",
273 std::string LatestROCm;
274 llvm::VersionTuple LatestVer;
276 auto GetROCmVersion = [](StringRef DirName) {
277 llvm::VersionTuple
V;
278 std::string VerStr = DirName.drop_front(strlen(
"rocm-")).str();
281 llvm::replace(VerStr,
'-',
'.');
285 for (llvm::vfs::directory_iterator
286 File = D.getVFS().dir_begin(D.SysRoot +
"/opt", EC),
288 File != FileEnd && !EC;
File.increment(EC)) {
289 llvm::StringRef
FileName = llvm::sys::path::filename(
File->path());
292 if (LatestROCm.empty()) {
294 LatestVer = GetROCmVersion(LatestROCm);
297 auto Ver = GetROCmVersion(
FileName);
298 if (LatestVer < Ver) {
303 if (!LatestROCm.empty())
304 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/" + LatestROCm,
307 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr/local",
309 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr",
312 DoPrintROCmSearchDirs();
313 return ROCmSearchDirs;
317 const Driver &D,
const llvm::Triple &HostTriple,
318 const llvm::opt::ArgList &Args,
bool DetectHIPRuntime)
320 Verbose = Args.hasArg(options::OPT_v);
321 RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
322 PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
323 RocmDeviceLibPathArg =
324 Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
325 HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
326 HIPStdParPathArg = Args.getLastArgValue(options::OPT_hipstdpar_path_EQ);
327 HasHIPStdParLibrary =
328 !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
329 "/hipstdpar_lib.hpp");
330 HIPRocThrustPathArg =
331 Args.getLastArgValue(options::OPT_hipstdpar_thrust_path_EQ);
332 HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
333 D.getVFS().exists(HIPRocThrustPathArg +
"/thrust");
334 HIPRocPrimPathArg = Args.getLastArgValue(options::OPT_hipstdpar_prim_path_EQ);
335 HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
336 D.getVFS().exists(HIPRocPrimPathArg +
"/rocprim");
338 if (
auto *A = Args.getLastArg(options::OPT_hip_version_EQ)) {
339 HIPVersionArg = A->getValue();
340 unsigned Major = ~0U;
341 unsigned Minor = ~0U;
342 SmallVector<StringRef, 3> Parts;
343 HIPVersionArg.split(Parts,
'.');
345 Parts[0].getAsInteger(0, Major);
346 if (Parts.size() > 1)
347 Parts[1].getAsInteger(0, Minor);
348 if (Parts.size() > 2)
349 VersionPatch = Parts[2].str();
350 if (VersionPatch.empty())
352 if (Major != ~0U && Minor == ~0U)
354 if (Major == ~0U || Minor == ~0U)
355 D.Diag(diag::err_drv_invalid_value)
356 << A->getAsString(Args) << HIPVersionArg;
358 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
360 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
362 VersionPatch = DefaultVersionPatch;
364 llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
365 DetectedVersion = (Twine(DefaultVersionMajor) +
"." +
366 Twine(DefaultVersionMinor) +
"." + VersionPatch)
370 if (DetectHIPRuntime)
375 assert(LibDevicePath.empty());
377 if (!RocmDeviceLibPathArg.empty())
378 LibDevicePath = RocmDeviceLibPathArg.back();
379 else if (std::optional<std::string> LibPathEnv =
380 llvm::sys::Process::GetEnv(
"HIP_DEVICE_LIB_PATH"))
381 LibDevicePath = std::move(*LibPathEnv);
383 auto &FS = D.getVFS();
384 if (!LibDevicePath.empty()) {
388 if (!FS.exists(LibDevicePath))
391 scanLibDevicePath(LibDevicePath);
392 HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
397 auto CheckDeviceLib = [&](StringRef Path,
bool StrictChecking) {
398 bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
399 if (CheckLibDevice && !FS.exists(Path))
402 scanLibDevicePath(Path);
404 if (!NoBuiltinLibs) {
406 if (!allGenericLibsValid())
411 if (LibDeviceMap.empty())
418 LibDevicePath = D.ResourceDir;
419 llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
420 "amdgcn",
"bitcode");
421 HasDeviceLibrary = CheckDeviceLib(LibDevicePath,
true);
422 if (HasDeviceLibrary)
427 auto &ROCmDirs = getInstallationPathCandidates();
428 for (
const auto &Candidate : ROCmDirs) {
429 LibDevicePath = Candidate.Path;
430 llvm::sys::path::append(LibDevicePath,
"amdgcn",
"bitcode");
431 HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
432 if (HasDeviceLibrary)
439 if (!HIPPathArg.empty())
440 HIPSearchDirs.emplace_back(HIPPathArg.str());
441 else if (std::optional<std::string> HIPPathEnv =
442 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
443 if (!HIPPathEnv->empty())
444 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
446 if (HIPSearchDirs.empty())
447 HIPSearchDirs.append(getInstallationPathCandidates());
448 auto &FS = D.getVFS();
450 for (
const auto &Candidate : HIPSearchDirs) {
451 InstallPath = Candidate.Path;
452 if (InstallPath.empty() || !FS.exists(InstallPath))
455 BinPath = InstallPath;
456 llvm::sys::path::append(BinPath,
"bin");
457 IncludePath = InstallPath;
458 llvm::sys::path::append(IncludePath,
"include");
459 LibPath = InstallPath;
460 llvm::sys::path::append(LibPath,
"lib");
461 SharePath = InstallPath;
462 llvm::sys::path::append(SharePath,
"share");
465 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
466 llvm::sys::path::append(ParentSharePath,
"share");
469 const Twine &c =
"",
const Twine &d =
"") {
471 llvm::sys::path::append(newpath, a, b, c, d);
475 std::vector<SmallString<0>> VersionFilePaths = {
476 Append(SharePath,
"hip",
"version"),
477 InstallPath != D.SysRoot +
"/usr/local"
478 ?
Append(ParentSharePath,
"hip",
"version")
480 Append(BinPath,
".hipVersion")};
482 for (
const auto &VersionFilePath : VersionFilePaths) {
483 if (VersionFilePath.empty())
485 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
486 FS.getBufferForFile(VersionFilePath);
489 if (HIPVersionArg.empty() && VersionFile)
490 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
493 HasHIPRuntime =
true;
498 if (!Candidate.StrictChecking) {
499 HasHIPRuntime =
true;
503 HasHIPRuntime =
false;
508 OS <<
"Found HIP installation: " << InstallPath <<
", version "
509 << DetectedVersion <<
'\n';
513 ArgStringList &CC1Args)
const {
514 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
515 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
516 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
518 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
533 if (UsesRuntimeWrapper)
534 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
535 CC1Args.push_back(
"-internal-isystem");
536 CC1Args.push_back(DriverArgs.MakeArgString(P));
539 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
541 auto &FS = D.getVFS();
544 if (!HIPStdParPathArg.empty() ||
545 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
546 D.Diag(diag::err_drv_no_hipstdpar_lib);
549 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
550 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
553 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
554 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
557 const char *ThrustPath;
558 if (HasRocThrustLibrary)
559 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
561 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
563 const char *HIPStdParPath;
565 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
567 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
568 "/system/hip/hipstdpar");
570 const char *PrimPath;
571 if (HasRocPrimLibrary)
572 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
574 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
576 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
577 "-idirafter", HIPStdParPath,
"-include",
578 "hipstdpar_lib.hpp"});
581 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
590 D.Diag(diag::err_drv_no_hip_runtime);
594 CC1Args.push_back(
"-idirafter");
597 llvm::sys::path::append(LibHipCxxPath,
"libhipcxx");
598 if (D.getVFS().exists(LibHipCxxPath)) {
599 CC1Args.push_back(
"-idirafter");
600 CC1Args.push_back(DriverArgs.MakeArgString(LibHipCxxPath));
602 if (UsesRuntimeWrapper)
603 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
612 const char *LinkingOutput)
const {
614 ArgStringList CmdArgs;
615 if (!Args.hasArg(options::OPT_r)) {
616 CmdArgs.push_back(
"--no-undefined");
617 CmdArgs.push_back(
"-shared");
620 if (Args.hasArg(options::OPT_hipstdpar))
621 CmdArgs.push_back(
"-plugin-opt=-amdgpu-enable-hipstdpar");
626 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
627 CmdArgs.push_back(Args.MakeArgString(
628 "-plugin-opt=mcpu=" +
630 Args.getLastArgValue(options::OPT_mcpu_EQ))));
634 Args.AddAllArgs(CmdArgs, options::OPT_L);
638 std::vector<StringRef> Features;
641 if (!Features.empty()) {
643 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
649 if (Args.hasArg(options::OPT_stdlib))
650 CmdArgs.append({
"-lc",
"-lm"});
651 if (Args.hasArg(options::OPT_startfiles)) {
652 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
654 IncludePath =
"/lib";
656 llvm::sys::path::append(P,
"crt1.o");
657 CmdArgs.push_back(Args.MakeArgString(P));
660 CmdArgs.push_back(
"-o");
662 C.addCommand(std::make_unique<Command>(
664 CmdArgs, Inputs, Output));
668 const llvm::Triple &Triple,
669 const llvm::opt::ArgList &Args,
670 std::vector<StringRef> &Features,
672 if (Args.hasFlag(options::OPT_mwavefrontsize64,
673 options::OPT_mno_wavefrontsize64,
false))
674 Features.push_back(
"+wavefrontsize64");
676 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
677 options::OPT_mno_amdgpu_precise_memory_op,
false))
678 Features.push_back(
"+precise-memory");
683 if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
685 A->getOption().matches(options::OPT_mxnack) ?
"+xnack" :
"-xnack");
689 Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
690 Features.push_back(A->getOption().matches(options::OPT_msramecc)
697 options::OPT_m_amdgpu_Features_Group);
702 const ArgList &Args,
const ToolChain *HostTC_,
707 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}),
709 ShouldLinkDeviceLibs(ShouldLinkDeviceLibs) {
710 loadMultilibsFromYAML(Args, D);
718 if (Triple.getOS() == llvm::Triple::AMDHSA &&
719 Triple.getEnvironment() != llvm::Triple::LLVM)
720 RocmInstallation->detectDeviceLibrary();
723 getProgramPaths().push_back(getDriver().Dir);
738 DAL =
new DerivedArgList(Args.getBaseArgs());
747 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
748 DAL->eraseArg(options::OPT_march_EQ);
749 if (!DAL->hasArg(options::OPT_mcpu_EQ))
750 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
756 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
757 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
758 DAL->eraseArg(options::OPT_mcpu_EQ);
762 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
764 auto &GPUs = *GPUsOrErr;
765 if (!llvm::all_equal(GPUs))
767 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
768 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
769 Args.MakeArgString(GPUs.front()));
774 DAL->eraseArg(options::OPT_mcpu_EQ);
775 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
786 auto XnackIt = FeatureMap.find(
"xnack");
787 if (XnackIt != FeatureMap.end()) {
788 DAL->AddFlagArg(
nullptr, Opts.getOption(XnackIt->second
789 ? options::OPT_mxnack
790 : options::OPT_mno_xnack));
793 auto SrameccIt = FeatureMap.find(
"sramecc");
794 if (SrameccIt != FeatureMap.end()) {
795 DAL->AddFlagArg(
nullptr,
796 Opts.getOption(SrameccIt->second
797 ? options::OPT_msramecc
798 : options::OPT_mno_sramecc));
804 for (Arg *A : Args) {
806 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
808 bool IsExplicitDevice =
809 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
811 ? diag::err_drv_unsupported_option_for_target
812 : diag::warn_drv_unsupported_option_for_target)
813 << A->getAsString(Args) <<
getTriple().str();
817 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
821 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
824 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
826 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
834 llvm::AMDGPU::GPUKind Kind) {
837 if (Kind == llvm::AMDGPU::GK_NONE)
840 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
844 const bool BothDenormAndFMAFast =
845 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
846 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
847 return !BothDenormAndFMAFast;
851 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
852 const llvm::fltSemantics *FPType)
const {
854 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
855 return llvm::DenormalMode::getIEEE();
862 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
863 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
864 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
865 options::OPT_fno_gpu_flush_denormals_to_zero,
867 return llvm::DenormalMode::getPreserveSign();
869 return llvm::DenormalMode::getIEEE();
872 const StringRef GpuArch =
getGPUArch(DriverArgs);
873 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
877 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
882 return DAZ ? llvm::DenormalMode::getPreserveSign() :
883 llvm::DenormalMode::getIEEE();
887 llvm::AMDGPU::GPUKind Kind) {
888 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
889 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
891 return !HasWave32 || DriverArgs.hasFlag(
892 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
896 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
899 CC1Args.append({
"-fcuda-is-device",
"-fno-threadsafe-statics"});
901 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
903 CC1Args.append({
"-mllvm",
"-amdgpu-internalize-symbols"});
904 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
905 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
909 DriverArgs.AddLastArg(CC1Args, options::OPT_gpu_max_threads_per_block_EQ);
914 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
915 options::OPT_fvisibility_ms_compat) &&
917 CC1Args.push_back(
"-fvisibility=hidden");
918 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
924 !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
925 CC1Args.push_back(
"-fembed-bitcode=marker");
939 if (!DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
940 CC1Args.push_back(
"-disable-llvm-optzns");
948 if (DriverArgs.hasArg(options::OPT_nostdlib))
955 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
965 for (
auto BCFile :
getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
966 CC1Args.push_back(BCFile.ShouldInternalize ?
"-mlink-builtin-bitcode"
967 :
"-mlink-bitcode-file");
968 CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
975 CC1Args.push_back(
"-Werror=atomic-alignment");
979 ArgStringList &CC1Args)
const {
983 HostTC->AddClangSystemIncludeArgs(DriverArgs, CC1Args);
987 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
988 DriverArgs.hasArg(options::OPT_nostdlibinc))
997 llvm::sys::path::append(Dir, M.includeSuffix());
1010 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
1015 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1016 if (TargetID.empty())
1019 llvm::StringMap<bool> FeatureMap;
1021 if (!OptionalGpuArch)
1022 return {TargetID.str(), std::nullopt, std::nullopt};
1024 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
1030 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
1032 << *PTID.OptionalTargetID;
1040 std::string Program;
1041 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1042 Program = A->getValue();
1048 return StdoutOrErr.takeError();
1051 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1053 GPUArchs.push_back(
Arch.str());
1055 if (GPUArchs.empty())
1056 return llvm::createStringError(std::error_code(),
1057 "No AMD GPU detected in the system");
1059 return std::move(GPUArchs);
1063 StringRef GPUArch, StringRef LibDeviceFile,
1066 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1069 if (LibDeviceFile.empty()) {
1070 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1077 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1079 D.Diag(diag::err_drv_no_rocm_device_lib)
1080 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1088 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1090 const bool NeedsASanRT)
const {
1093 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1094 DeviceOffloadingKind, NeedsASanRT};
1097 bool Internalize =
true) {
1098 if (!BCLib.
Path.empty()) {
1100 BCLibs.emplace_back(BCLib);
1103 auto AddSanBCLibs = [&]() {
1112 else if (Pref.GPUSan && Pref.IsOpenMP)
1117 AddBCLib(LibDeviceFile);
1119 if (!ABIVerPath.empty())
1120 AddBCLib(ABIVerPath);
1127 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1129 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1130 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1140 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1150 "spirv should not try to link device libs");
1152 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1163 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1175 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1176 if (!BCLibArgs.empty()) {
1177 ArgStringList LibraryPaths;
1179 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1182 for (StringRef BCName : BCLibArgs) {
1184 for (StringRef LibraryPath : LibraryPaths) {
1186 llvm::sys::path::append(Path, BCName);
1187 if (llvm::sys::fs::exists(Path)) {
1188 BCLibs.emplace_back(Path);
1207 BCLibs.emplace_back(N);
1211 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1212 if (!InstLib.empty()) {
1213 if (llvm::sys::fs::exists(InstLib))
1214 BCLibs.emplace_back(InstLib);
1226 BCLibs.emplace_back(BCLib);
1242 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1250 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1260 return HostTC->GetCXXStdlibType(Args);
1265 const ArgList &Args, ArgStringList &CC1Args)
const {
1267 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1273 ArgStringList &CC1Args)
const {
1275 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1279 ArgStringList &CC1Args)
const {
1280 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1281 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1282 options::OPT_no_offload_inc,
true) &&
1283 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1284 !DriverArgs.hasArg(options::OPT_nobuiltininc))
1285 CC1Args.append({
"-include",
"__clang_gpu_device_functions.h"});
1293 const ArgList &Args)
const {
1295 return HostTC->computeMSVCVersion(D, Args);
1307 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1308 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1318 llvm::AMDGPU::GPUKind ProcKind = llvm::AMDGPU::parseArchAMDGCN(Processor);
1319 unsigned Features = llvm::AMDGPU::getArchAttrAMDGCN(ProcKind);
1322 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1323 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1328 llvm::StringMap<bool> FeatureMap;
1329 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1330 if (!OptionalGpuArch)
1332 auto Loc = FeatureMap.find(
"xnack");
1333 return (Loc != FeatureMap.end() && Loc->second);
1344 SupportedMask |= SanitizerKind::Address;
1346 return SupportedMask;
1352 if ((Kinds & SanitizerKind::Address) && BA &&
static StringRef getTriple(const Command &Job)
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)
BoundArch 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.
LTOKind
Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options.
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.
Represents a bound architecture for offload / multiple architecture compilation.
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()