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");
596 if (UsesRuntimeWrapper)
597 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
606 const char *LinkingOutput)
const {
608 ArgStringList CmdArgs;
609 if (!Args.hasArg(options::OPT_r)) {
610 CmdArgs.push_back(
"--no-undefined");
611 CmdArgs.push_back(
"-shared");
614 if (Args.hasArg(options::OPT_hipstdpar))
615 CmdArgs.push_back(
"-plugin-opt=-amdgpu-enable-hipstdpar");
620 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
621 CmdArgs.push_back(Args.MakeArgString(
622 "-plugin-opt=mcpu=" +
624 Args.getLastArgValue(options::OPT_mcpu_EQ))));
628 Args.AddAllArgs(CmdArgs, options::OPT_L);
632 std::vector<StringRef> Features;
635 if (!Features.empty()) {
637 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
643 if (Args.hasArg(options::OPT_stdlib))
644 CmdArgs.append({
"-lc",
"-lm"});
645 if (Args.hasArg(options::OPT_startfiles)) {
646 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
648 IncludePath =
"/lib";
650 llvm::sys::path::append(P,
"crt1.o");
651 CmdArgs.push_back(Args.MakeArgString(P));
654 CmdArgs.push_back(
"-o");
656 C.addCommand(std::make_unique<Command>(
658 CmdArgs, Inputs, Output));
662 const llvm::Triple &Triple,
663 const llvm::opt::ArgList &Args,
664 std::vector<StringRef> &Features,
666 if (Args.hasFlag(options::OPT_mwavefrontsize64,
667 options::OPT_mno_wavefrontsize64,
false))
668 Features.push_back(
"+wavefrontsize64");
670 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
671 options::OPT_mno_amdgpu_precise_memory_op,
false))
672 Features.push_back(
"+precise-memory");
677 if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
679 A->getOption().matches(options::OPT_mxnack) ?
"+xnack" :
"-xnack");
683 Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
684 Features.push_back(A->getOption().matches(options::OPT_msramecc)
691 options::OPT_m_amdgpu_Features_Group);
696 const ArgList &Args,
const ToolChain *HostTC_,
701 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}),
703 ShouldLinkDeviceLibs(ShouldLinkDeviceLibs) {
704 loadMultilibsFromYAML(Args, D);
712 if (Triple.getOS() == llvm::Triple::AMDHSA &&
713 Triple.getEnvironment() != llvm::Triple::LLVM)
714 RocmInstallation->detectDeviceLibrary();
717 getProgramPaths().push_back(getDriver().Dir);
732 DAL =
new DerivedArgList(Args.getBaseArgs());
741 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
742 DAL->eraseArg(options::OPT_march_EQ);
743 if (!DAL->hasArg(options::OPT_mcpu_EQ))
744 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
750 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
751 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
752 DAL->eraseArg(options::OPT_mcpu_EQ);
756 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
758 auto &GPUs = *GPUsOrErr;
759 if (!llvm::all_equal(GPUs))
761 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
762 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
763 Args.MakeArgString(GPUs.front()));
768 DAL->eraseArg(options::OPT_mcpu_EQ);
769 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
780 auto XnackIt = FeatureMap.find(
"xnack");
781 if (XnackIt != FeatureMap.end()) {
782 DAL->AddFlagArg(
nullptr, Opts.getOption(XnackIt->second
783 ? options::OPT_mxnack
784 : options::OPT_mno_xnack));
787 auto SrameccIt = FeatureMap.find(
"sramecc");
788 if (SrameccIt != FeatureMap.end()) {
789 DAL->AddFlagArg(
nullptr,
790 Opts.getOption(SrameccIt->second
791 ? options::OPT_msramecc
792 : options::OPT_mno_sramecc));
798 for (Arg *A : Args) {
800 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
802 bool IsExplicitDevice =
803 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
805 ? diag::err_drv_unsupported_option_for_target
806 : diag::warn_drv_unsupported_option_for_target)
807 << A->getAsString(Args) <<
getTriple().str();
811 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
815 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
818 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
820 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
828 llvm::AMDGPU::GPUKind Kind) {
831 if (Kind == llvm::AMDGPU::GK_NONE)
834 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
838 const bool BothDenormAndFMAFast =
839 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
840 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
841 return !BothDenormAndFMAFast;
845 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
846 const llvm::fltSemantics *FPType)
const {
848 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
849 return llvm::DenormalMode::getIEEE();
856 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
857 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
858 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
859 options::OPT_fno_gpu_flush_denormals_to_zero,
861 return llvm::DenormalMode::getPreserveSign();
863 return llvm::DenormalMode::getIEEE();
866 const StringRef GpuArch =
getGPUArch(DriverArgs);
867 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
871 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
876 return DAZ ? llvm::DenormalMode::getPreserveSign() :
877 llvm::DenormalMode::getIEEE();
881 llvm::AMDGPU::GPUKind Kind) {
882 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
883 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
885 return !HasWave32 || DriverArgs.hasFlag(
886 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
890 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
893 CC1Args.append({
"-fcuda-is-device",
"-fno-threadsafe-statics"});
895 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
897 CC1Args.append({
"-mllvm",
"-amdgpu-internalize-symbols"});
898 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
899 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
903 DriverArgs.AddLastArg(CC1Args, options::OPT_gpu_max_threads_per_block_EQ);
908 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
909 options::OPT_fvisibility_ms_compat) &&
911 CC1Args.push_back(
"-fvisibility=hidden");
912 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
918 !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
919 CC1Args.push_back(
"-fembed-bitcode=marker");
933 if (!DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
934 CC1Args.push_back(
"-disable-llvm-optzns");
942 if (DriverArgs.hasArg(options::OPT_nostdlib))
949 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
959 for (
auto BCFile :
getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
960 CC1Args.push_back(BCFile.ShouldInternalize ?
"-mlink-builtin-bitcode"
961 :
"-mlink-bitcode-file");
962 CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
969 CC1Args.push_back(
"-Werror=atomic-alignment");
973 ArgStringList &CC1Args)
const {
977 HostTC->AddClangSystemIncludeArgs(DriverArgs, CC1Args);
981 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
982 DriverArgs.hasArg(options::OPT_nostdlibinc))
991 llvm::sys::path::append(Dir, M.includeSuffix());
1004 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
1009 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1010 if (TargetID.empty())
1013 llvm::StringMap<bool> FeatureMap;
1015 if (!OptionalGpuArch)
1016 return {TargetID.str(), std::nullopt, std::nullopt};
1018 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
1024 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
1026 << *PTID.OptionalTargetID;
1034 std::string Program;
1035 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1036 Program = A->getValue();
1042 return StdoutOrErr.takeError();
1045 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1047 GPUArchs.push_back(
Arch.str());
1049 if (GPUArchs.empty())
1050 return llvm::createStringError(std::error_code(),
1051 "No AMD GPU detected in the system");
1053 return std::move(GPUArchs);
1057 StringRef GPUArch, StringRef LibDeviceFile,
1060 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1063 if (LibDeviceFile.empty()) {
1064 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1071 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1073 D.Diag(diag::err_drv_no_rocm_device_lib)
1074 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1082 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1084 const bool NeedsASanRT)
const {
1087 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1088 DeviceOffloadingKind, NeedsASanRT};
1091 bool Internalize =
true) {
1092 if (!BCLib.
Path.empty()) {
1094 BCLibs.emplace_back(BCLib);
1097 auto AddSanBCLibs = [&]() {
1106 else if (Pref.GPUSan && Pref.IsOpenMP)
1111 AddBCLib(LibDeviceFile);
1113 if (!ABIVerPath.empty())
1114 AddBCLib(ABIVerPath);
1121 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1123 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1124 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1134 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1144 "spirv should not try to link device libs");
1146 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1157 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1169 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1170 if (!BCLibArgs.empty()) {
1171 ArgStringList LibraryPaths;
1173 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1176 for (StringRef BCName : BCLibArgs) {
1178 for (StringRef LibraryPath : LibraryPaths) {
1180 llvm::sys::path::append(Path, BCName);
1181 if (llvm::sys::fs::exists(Path)) {
1182 BCLibs.emplace_back(Path);
1201 BCLibs.emplace_back(N);
1205 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1206 if (!InstLib.empty()) {
1207 if (llvm::sys::fs::exists(InstLib))
1208 BCLibs.emplace_back(InstLib);
1220 BCLibs.emplace_back(BCLib);
1236 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1244 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1254 return HostTC->GetCXXStdlibType(Args);
1259 const ArgList &Args, ArgStringList &CC1Args)
const {
1261 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1267 ArgStringList &CC1Args)
const {
1269 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1273 ArgStringList &CC1Args)
const {
1274 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1275 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1276 options::OPT_no_offload_inc,
true) &&
1277 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1278 !DriverArgs.hasArg(options::OPT_nobuiltininc))
1279 CC1Args.append({
"-include",
"__clang_gpu_device_functions.h"});
1287 const ArgList &Args)
const {
1289 return HostTC->computeMSVCVersion(D, Args);
1301 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1302 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1312 llvm::AMDGPU::GPUKind ProcKind = llvm::AMDGPU::parseArchAMDGCN(Processor);
1313 unsigned Features = llvm::AMDGPU::getArchAttrAMDGCN(ProcKind);
1316 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1317 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1322 llvm::StringMap<bool> FeatureMap;
1323 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1324 if (!OptionalGpuArch)
1326 auto Loc = FeatureMap.find(
"xnack");
1327 return (Loc != FeatureMap.end() && Loc->second);
1338 SupportedMask |= SanitizerKind::Address;
1340 return SupportedMask;
1346 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()