1*12c85518Srobert //===--- HIPAMD.cpp - HIP Tool and ToolChain Implementations ----*- C++ -*-===//
2*12c85518Srobert //
3*12c85518Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*12c85518Srobert // See https://llvm.org/LICENSE.txt for license information.
5*12c85518Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*12c85518Srobert //
7*12c85518Srobert //===----------------------------------------------------------------------===//
8*12c85518Srobert
9*12c85518Srobert #include "HIPAMD.h"
10*12c85518Srobert #include "AMDGPU.h"
11*12c85518Srobert #include "CommonArgs.h"
12*12c85518Srobert #include "HIPUtility.h"
13*12c85518Srobert #include "clang/Basic/Cuda.h"
14*12c85518Srobert #include "clang/Basic/TargetID.h"
15*12c85518Srobert #include "clang/Driver/Compilation.h"
16*12c85518Srobert #include "clang/Driver/Driver.h"
17*12c85518Srobert #include "clang/Driver/DriverDiagnostic.h"
18*12c85518Srobert #include "clang/Driver/InputInfo.h"
19*12c85518Srobert #include "clang/Driver/Options.h"
20*12c85518Srobert #include "clang/Driver/SanitizerArgs.h"
21*12c85518Srobert #include "llvm/Support/Alignment.h"
22*12c85518Srobert #include "llvm/Support/FileSystem.h"
23*12c85518Srobert #include "llvm/Support/Path.h"
24*12c85518Srobert #include "llvm/Support/TargetParser.h"
25*12c85518Srobert
26*12c85518Srobert using namespace clang::driver;
27*12c85518Srobert using namespace clang::driver::toolchains;
28*12c85518Srobert using namespace clang::driver::tools;
29*12c85518Srobert using namespace clang;
30*12c85518Srobert using namespace llvm::opt;
31*12c85518Srobert
32*12c85518Srobert #if defined(_WIN32) || defined(_WIN64)
33*12c85518Srobert #define NULL_FILE "nul"
34*12c85518Srobert #else
35*12c85518Srobert #define NULL_FILE "/dev/null"
36*12c85518Srobert #endif
37*12c85518Srobert
shouldSkipSanitizeOption(const ToolChain & TC,const llvm::opt::ArgList & DriverArgs,StringRef TargetID,const llvm::opt::Arg * A)38*12c85518Srobert static bool shouldSkipSanitizeOption(const ToolChain &TC,
39*12c85518Srobert const llvm::opt::ArgList &DriverArgs,
40*12c85518Srobert StringRef TargetID,
41*12c85518Srobert const llvm::opt::Arg *A) {
42*12c85518Srobert // For actions without targetID, do nothing.
43*12c85518Srobert if (TargetID.empty())
44*12c85518Srobert return false;
45*12c85518Srobert Option O = A->getOption();
46*12c85518Srobert if (!O.matches(options::OPT_fsanitize_EQ))
47*12c85518Srobert return false;
48*12c85518Srobert
49*12c85518Srobert if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
50*12c85518Srobert options::OPT_fno_gpu_sanitize, true))
51*12c85518Srobert return true;
52*12c85518Srobert
53*12c85518Srobert auto &Diags = TC.getDriver().getDiags();
54*12c85518Srobert
55*12c85518Srobert // For simplicity, we only allow -fsanitize=address
56*12c85518Srobert SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
57*12c85518Srobert if (K != SanitizerKind::Address)
58*12c85518Srobert return true;
59*12c85518Srobert
60*12c85518Srobert llvm::StringMap<bool> FeatureMap;
61*12c85518Srobert auto OptionalGpuArch = parseTargetID(TC.getTriple(), TargetID, &FeatureMap);
62*12c85518Srobert
63*12c85518Srobert assert(OptionalGpuArch && "Invalid Target ID");
64*12c85518Srobert (void)OptionalGpuArch;
65*12c85518Srobert auto Loc = FeatureMap.find("xnack");
66*12c85518Srobert if (Loc == FeatureMap.end() || !Loc->second) {
67*12c85518Srobert Diags.Report(
68*12c85518Srobert clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
69*12c85518Srobert << A->getAsString(DriverArgs) << TargetID << "xnack+";
70*12c85518Srobert return true;
71*12c85518Srobert }
72*12c85518Srobert return false;
73*12c85518Srobert }
74*12c85518Srobert
constructLlvmLinkCommand(Compilation & C,const JobAction & JA,const InputInfoList & Inputs,const InputInfo & Output,const llvm::opt::ArgList & Args) const75*12c85518Srobert void AMDGCN::Linker::constructLlvmLinkCommand(Compilation &C,
76*12c85518Srobert const JobAction &JA,
77*12c85518Srobert const InputInfoList &Inputs,
78*12c85518Srobert const InputInfo &Output,
79*12c85518Srobert const llvm::opt::ArgList &Args) const {
80*12c85518Srobert // Construct llvm-link command.
81*12c85518Srobert // The output from llvm-link is a bitcode file.
82*12c85518Srobert ArgStringList LlvmLinkArgs;
83*12c85518Srobert
84*12c85518Srobert assert(!Inputs.empty() && "Must have at least one input.");
85*12c85518Srobert
86*12c85518Srobert LlvmLinkArgs.append({"-o", Output.getFilename()});
87*12c85518Srobert for (auto Input : Inputs)
88*12c85518Srobert LlvmLinkArgs.push_back(Input.getFilename());
89*12c85518Srobert
90*12c85518Srobert // Look for archive of bundled bitcode in arguments, and add temporary files
91*12c85518Srobert // for the extracted archive of bitcode to inputs.
92*12c85518Srobert auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
93*12c85518Srobert AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LlvmLinkArgs, "amdgcn",
94*12c85518Srobert TargetID,
95*12c85518Srobert /*IsBitCodeSDL=*/true,
96*12c85518Srobert /*PostClangLink=*/false);
97*12c85518Srobert
98*12c85518Srobert const char *LlvmLink =
99*12c85518Srobert Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
100*12c85518Srobert C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
101*12c85518Srobert LlvmLink, LlvmLinkArgs, Inputs,
102*12c85518Srobert Output));
103*12c85518Srobert }
104*12c85518Srobert
constructLldCommand(Compilation & C,const JobAction & JA,const InputInfoList & Inputs,const InputInfo & Output,const llvm::opt::ArgList & Args) const105*12c85518Srobert void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
106*12c85518Srobert const InputInfoList &Inputs,
107*12c85518Srobert const InputInfo &Output,
108*12c85518Srobert const llvm::opt::ArgList &Args) const {
109*12c85518Srobert // Construct lld command.
110*12c85518Srobert // The output from ld.lld is an HSA code object file.
111*12c85518Srobert ArgStringList LldArgs{"-flavor",
112*12c85518Srobert "gnu",
113*12c85518Srobert "-m",
114*12c85518Srobert "elf64_amdgpu",
115*12c85518Srobert "--no-undefined",
116*12c85518Srobert "-shared",
117*12c85518Srobert "-plugin-opt=-amdgpu-internalize-symbols"};
118*12c85518Srobert
119*12c85518Srobert auto &TC = getToolChain();
120*12c85518Srobert auto &D = TC.getDriver();
121*12c85518Srobert assert(!Inputs.empty() && "Must have at least one input.");
122*12c85518Srobert bool IsThinLTO = D.getLTOMode(/*IsOffload=*/true) == LTOK_Thin;
123*12c85518Srobert addLTOOptions(TC, Args, LldArgs, Output, Inputs[0], IsThinLTO);
124*12c85518Srobert
125*12c85518Srobert // Extract all the -m options
126*12c85518Srobert std::vector<llvm::StringRef> Features;
127*12c85518Srobert amdgpu::getAMDGPUTargetFeatures(D, TC.getTriple(), Args, Features);
128*12c85518Srobert
129*12c85518Srobert // Add features to mattr such as cumode
130*12c85518Srobert std::string MAttrString = "-plugin-opt=-mattr=";
131*12c85518Srobert for (auto OneFeature : unifyTargetFeatures(Features)) {
132*12c85518Srobert MAttrString.append(Args.MakeArgString(OneFeature));
133*12c85518Srobert if (OneFeature != Features.back())
134*12c85518Srobert MAttrString.append(",");
135*12c85518Srobert }
136*12c85518Srobert if (!Features.empty())
137*12c85518Srobert LldArgs.push_back(Args.MakeArgString(MAttrString));
138*12c85518Srobert
139*12c85518Srobert // ToDo: Remove this option after AMDGPU backend supports ISA-level linking.
140*12c85518Srobert // Since AMDGPU backend currently does not support ISA-level linking, all
141*12c85518Srobert // called functions need to be imported.
142*12c85518Srobert if (IsThinLTO)
143*12c85518Srobert LldArgs.push_back(Args.MakeArgString("-plugin-opt=-force-import-all"));
144*12c85518Srobert
145*12c85518Srobert for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
146*12c85518Srobert LldArgs.push_back(
147*12c85518Srobert Args.MakeArgString(Twine("-plugin-opt=") + A->getValue(0)));
148*12c85518Srobert }
149*12c85518Srobert
150*12c85518Srobert if (C.getDriver().isSaveTempsEnabled())
151*12c85518Srobert LldArgs.push_back("-save-temps");
152*12c85518Srobert
153*12c85518Srobert addLinkerCompressDebugSectionsOption(TC, Args, LldArgs);
154*12c85518Srobert
155*12c85518Srobert for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker))
156*12c85518Srobert LldArgs.push_back(Arg->getValue(1));
157*12c85518Srobert
158*12c85518Srobert LldArgs.append({"-o", Output.getFilename()});
159*12c85518Srobert for (auto Input : Inputs)
160*12c85518Srobert LldArgs.push_back(Input.getFilename());
161*12c85518Srobert
162*12c85518Srobert // Look for archive of bundled bitcode in arguments, and add temporary files
163*12c85518Srobert // for the extracted archive of bitcode to inputs.
164*12c85518Srobert auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
165*12c85518Srobert AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LldArgs, "amdgcn",
166*12c85518Srobert TargetID,
167*12c85518Srobert /*IsBitCodeSDL=*/true,
168*12c85518Srobert /*PostClangLink=*/false);
169*12c85518Srobert
170*12c85518Srobert const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
171*12c85518Srobert C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
172*12c85518Srobert Lld, LldArgs, Inputs, Output));
173*12c85518Srobert }
174*12c85518Srobert
175*12c85518Srobert // For amdgcn the inputs of the linker job are device bitcode and output is
176*12c85518Srobert // either an object file or bitcode (-emit-llvm). It calls llvm-link, opt,
177*12c85518Srobert // llc, then lld steps.
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const178*12c85518Srobert void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
179*12c85518Srobert const InputInfo &Output,
180*12c85518Srobert const InputInfoList &Inputs,
181*12c85518Srobert const ArgList &Args,
182*12c85518Srobert const char *LinkingOutput) const {
183*12c85518Srobert if (Inputs.size() > 0 &&
184*12c85518Srobert Inputs[0].getType() == types::TY_Image &&
185*12c85518Srobert JA.getType() == types::TY_Object)
186*12c85518Srobert return HIP::constructGenerateObjFileFromHIPFatBinary(C, Output, Inputs,
187*12c85518Srobert Args, JA, *this);
188*12c85518Srobert
189*12c85518Srobert if (JA.getType() == types::TY_HIP_FATBIN)
190*12c85518Srobert return HIP::constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs,
191*12c85518Srobert Args, *this);
192*12c85518Srobert
193*12c85518Srobert if (JA.getType() == types::TY_LLVM_BC)
194*12c85518Srobert return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
195*12c85518Srobert
196*12c85518Srobert return constructLldCommand(C, JA, Inputs, Output, Args);
197*12c85518Srobert }
198*12c85518Srobert
HIPAMDToolChain(const Driver & D,const llvm::Triple & Triple,const ToolChain & HostTC,const ArgList & Args)199*12c85518Srobert HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
200*12c85518Srobert const ToolChain &HostTC, const ArgList &Args)
201*12c85518Srobert : ROCMToolChain(D, Triple, Args), HostTC(HostTC) {
202*12c85518Srobert // Lookup binaries into the driver directory, this is used to
203*12c85518Srobert // discover the clang-offload-bundler executable.
204*12c85518Srobert getProgramPaths().push_back(getDriver().Dir);
205*12c85518Srobert
206*12c85518Srobert // Diagnose unsupported sanitizer options only once.
207*12c85518Srobert if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
208*12c85518Srobert true))
209*12c85518Srobert return;
210*12c85518Srobert for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
211*12c85518Srobert SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
212*12c85518Srobert if (K != SanitizerKind::Address)
213*12c85518Srobert D.getDiags().Report(clang::diag::warn_drv_unsupported_option_for_target)
214*12c85518Srobert << A->getAsString(Args) << getTriple().str();
215*12c85518Srobert }
216*12c85518Srobert }
217*12c85518Srobert
addClangTargetOptions(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadingKind) const218*12c85518Srobert void HIPAMDToolChain::addClangTargetOptions(
219*12c85518Srobert const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
220*12c85518Srobert Action::OffloadKind DeviceOffloadingKind) const {
221*12c85518Srobert HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
222*12c85518Srobert
223*12c85518Srobert assert(DeviceOffloadingKind == Action::OFK_HIP &&
224*12c85518Srobert "Only HIP offloading kinds are supported for GPUs.");
225*12c85518Srobert
226*12c85518Srobert CC1Args.push_back("-fcuda-is-device");
227*12c85518Srobert
228*12c85518Srobert if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
229*12c85518Srobert options::OPT_fno_cuda_approx_transcendentals, false))
230*12c85518Srobert CC1Args.push_back("-fcuda-approx-transcendentals");
231*12c85518Srobert
232*12c85518Srobert if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
233*12c85518Srobert false))
234*12c85518Srobert CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"});
235*12c85518Srobert
236*12c85518Srobert StringRef MaxThreadsPerBlock =
237*12c85518Srobert DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
238*12c85518Srobert if (!MaxThreadsPerBlock.empty()) {
239*12c85518Srobert std::string ArgStr =
240*12c85518Srobert (Twine("--gpu-max-threads-per-block=") + MaxThreadsPerBlock).str();
241*12c85518Srobert CC1Args.push_back(DriverArgs.MakeArgStringRef(ArgStr));
242*12c85518Srobert }
243*12c85518Srobert
244*12c85518Srobert CC1Args.push_back("-fcuda-allow-variadic-functions");
245*12c85518Srobert
246*12c85518Srobert // Default to "hidden" visibility, as object level linking will not be
247*12c85518Srobert // supported for the foreseeable future.
248*12c85518Srobert if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
249*12c85518Srobert options::OPT_fvisibility_ms_compat)) {
250*12c85518Srobert CC1Args.append({"-fvisibility=hidden"});
251*12c85518Srobert CC1Args.push_back("-fapply-global-visibility-to-externs");
252*12c85518Srobert }
253*12c85518Srobert
254*12c85518Srobert for (auto BCFile : getDeviceLibs(DriverArgs)) {
255*12c85518Srobert CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
256*12c85518Srobert : "-mlink-bitcode-file");
257*12c85518Srobert CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
258*12c85518Srobert }
259*12c85518Srobert }
260*12c85518Srobert
261*12c85518Srobert llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind DeviceOffloadKind) const262*12c85518Srobert HIPAMDToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
263*12c85518Srobert StringRef BoundArch,
264*12c85518Srobert Action::OffloadKind DeviceOffloadKind) const {
265*12c85518Srobert DerivedArgList *DAL =
266*12c85518Srobert HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
267*12c85518Srobert if (!DAL)
268*12c85518Srobert DAL = new DerivedArgList(Args.getBaseArgs());
269*12c85518Srobert
270*12c85518Srobert const OptTable &Opts = getDriver().getOpts();
271*12c85518Srobert
272*12c85518Srobert for (Arg *A : Args) {
273*12c85518Srobert if (!shouldSkipArgument(A) &&
274*12c85518Srobert !shouldSkipSanitizeOption(*this, Args, BoundArch, A))
275*12c85518Srobert DAL->append(A);
276*12c85518Srobert }
277*12c85518Srobert
278*12c85518Srobert if (!BoundArch.empty()) {
279*12c85518Srobert DAL->eraseArg(options::OPT_mcpu_EQ);
280*12c85518Srobert DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
281*12c85518Srobert checkTargetID(*DAL);
282*12c85518Srobert }
283*12c85518Srobert
284*12c85518Srobert return DAL;
285*12c85518Srobert }
286*12c85518Srobert
buildLinker() const287*12c85518Srobert Tool *HIPAMDToolChain::buildLinker() const {
288*12c85518Srobert assert(getTriple().getArch() == llvm::Triple::amdgcn);
289*12c85518Srobert return new tools::AMDGCN::Linker(*this);
290*12c85518Srobert }
291*12c85518Srobert
addClangWarningOptions(ArgStringList & CC1Args) const292*12c85518Srobert void HIPAMDToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
293*12c85518Srobert HostTC.addClangWarningOptions(CC1Args);
294*12c85518Srobert }
295*12c85518Srobert
296*12c85518Srobert ToolChain::CXXStdlibType
GetCXXStdlibType(const ArgList & Args) const297*12c85518Srobert HIPAMDToolChain::GetCXXStdlibType(const ArgList &Args) const {
298*12c85518Srobert return HostTC.GetCXXStdlibType(Args);
299*12c85518Srobert }
300*12c85518Srobert
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const301*12c85518Srobert void HIPAMDToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
302*12c85518Srobert ArgStringList &CC1Args) const {
303*12c85518Srobert HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
304*12c85518Srobert }
305*12c85518Srobert
AddClangCXXStdlibIncludeArgs(const ArgList & Args,ArgStringList & CC1Args) const306*12c85518Srobert void HIPAMDToolChain::AddClangCXXStdlibIncludeArgs(
307*12c85518Srobert const ArgList &Args, ArgStringList &CC1Args) const {
308*12c85518Srobert HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
309*12c85518Srobert }
310*12c85518Srobert
AddIAMCUIncludeArgs(const ArgList & Args,ArgStringList & CC1Args) const311*12c85518Srobert void HIPAMDToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
312*12c85518Srobert ArgStringList &CC1Args) const {
313*12c85518Srobert HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
314*12c85518Srobert }
315*12c85518Srobert
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const316*12c85518Srobert void HIPAMDToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
317*12c85518Srobert ArgStringList &CC1Args) const {
318*12c85518Srobert RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
319*12c85518Srobert }
320*12c85518Srobert
getSupportedSanitizers() const321*12c85518Srobert SanitizerMask HIPAMDToolChain::getSupportedSanitizers() const {
322*12c85518Srobert // The HIPAMDToolChain only supports sanitizers in the sense that it allows
323*12c85518Srobert // sanitizer arguments on the command line if they are supported by the host
324*12c85518Srobert // toolchain. The HIPAMDToolChain will actually ignore any command line
325*12c85518Srobert // arguments for any of these "supported" sanitizers. That means that no
326*12c85518Srobert // sanitization of device code is actually supported at this time.
327*12c85518Srobert //
328*12c85518Srobert // This behavior is necessary because the host and device toolchains
329*12c85518Srobert // invocations often share the command line, so the device toolchain must
330*12c85518Srobert // tolerate flags meant only for the host toolchain.
331*12c85518Srobert return HostTC.getSupportedSanitizers();
332*12c85518Srobert }
333*12c85518Srobert
computeMSVCVersion(const Driver * D,const ArgList & Args) const334*12c85518Srobert VersionTuple HIPAMDToolChain::computeMSVCVersion(const Driver *D,
335*12c85518Srobert const ArgList &Args) const {
336*12c85518Srobert return HostTC.computeMSVCVersion(D, Args);
337*12c85518Srobert }
338*12c85518Srobert
339*12c85518Srobert llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
getDeviceLibs(const llvm::opt::ArgList & DriverArgs) const340*12c85518Srobert HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
341*12c85518Srobert llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
342*12c85518Srobert if (DriverArgs.hasArg(options::OPT_nogpulib))
343*12c85518Srobert return {};
344*12c85518Srobert ArgStringList LibraryPaths;
345*12c85518Srobert
346*12c85518Srobert // Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
347*12c85518Srobert for (StringRef Path : RocmInstallation.getRocmDeviceLibPathArg())
348*12c85518Srobert LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
349*12c85518Srobert
350*12c85518Srobert addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
351*12c85518Srobert
352*12c85518Srobert // Maintain compatability with --hip-device-lib.
353*12c85518Srobert auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
354*12c85518Srobert if (!BCLibArgs.empty()) {
355*12c85518Srobert llvm::for_each(BCLibArgs, [&](StringRef BCName) {
356*12c85518Srobert StringRef FullName;
357*12c85518Srobert for (StringRef LibraryPath : LibraryPaths) {
358*12c85518Srobert SmallString<128> Path(LibraryPath);
359*12c85518Srobert llvm::sys::path::append(Path, BCName);
360*12c85518Srobert FullName = Path;
361*12c85518Srobert if (llvm::sys::fs::exists(FullName)) {
362*12c85518Srobert BCLibs.push_back(FullName);
363*12c85518Srobert return;
364*12c85518Srobert }
365*12c85518Srobert }
366*12c85518Srobert getDriver().Diag(diag::err_drv_no_such_file) << BCName;
367*12c85518Srobert });
368*12c85518Srobert } else {
369*12c85518Srobert if (!RocmInstallation.hasDeviceLibrary()) {
370*12c85518Srobert getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
371*12c85518Srobert return {};
372*12c85518Srobert }
373*12c85518Srobert StringRef GpuArch = getGPUArch(DriverArgs);
374*12c85518Srobert assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
375*12c85518Srobert
376*12c85518Srobert // If --hip-device-lib is not set, add the default bitcode libraries.
377*12c85518Srobert if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
378*12c85518Srobert options::OPT_fno_gpu_sanitize, true) &&
379*12c85518Srobert getSanitizerArgs(DriverArgs).needsAsanRt()) {
380*12c85518Srobert auto AsanRTL = RocmInstallation.getAsanRTLPath();
381*12c85518Srobert if (AsanRTL.empty()) {
382*12c85518Srobert unsigned DiagID = getDriver().getDiags().getCustomDiagID(
383*12c85518Srobert DiagnosticsEngine::Error,
384*12c85518Srobert "AMDGPU address sanitizer runtime library (asanrtl) is not found. "
385*12c85518Srobert "Please install ROCm device library which supports address "
386*12c85518Srobert "sanitizer");
387*12c85518Srobert getDriver().Diag(DiagID);
388*12c85518Srobert return {};
389*12c85518Srobert } else
390*12c85518Srobert BCLibs.emplace_back(AsanRTL, /*ShouldInternalize=*/false);
391*12c85518Srobert }
392*12c85518Srobert
393*12c85518Srobert // Add the HIP specific bitcode library.
394*12c85518Srobert BCLibs.push_back(RocmInstallation.getHIPPath());
395*12c85518Srobert
396*12c85518Srobert // Add common device libraries like ocml etc.
397*12c85518Srobert for (StringRef N : getCommonDeviceLibNames(DriverArgs, GpuArch.str()))
398*12c85518Srobert BCLibs.emplace_back(N);
399*12c85518Srobert
400*12c85518Srobert // Add instrument lib.
401*12c85518Srobert auto InstLib =
402*12c85518Srobert DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
403*12c85518Srobert if (InstLib.empty())
404*12c85518Srobert return BCLibs;
405*12c85518Srobert if (llvm::sys::fs::exists(InstLib))
406*12c85518Srobert BCLibs.push_back(InstLib);
407*12c85518Srobert else
408*12c85518Srobert getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
409*12c85518Srobert }
410*12c85518Srobert
411*12c85518Srobert return BCLibs;
412*12c85518Srobert }
413*12c85518Srobert
checkTargetID(const llvm::opt::ArgList & DriverArgs) const414*12c85518Srobert void HIPAMDToolChain::checkTargetID(
415*12c85518Srobert const llvm::opt::ArgList &DriverArgs) const {
416*12c85518Srobert auto PTID = getParsedTargetID(DriverArgs);
417*12c85518Srobert if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
418*12c85518Srobert getDriver().Diag(clang::diag::err_drv_bad_target_id)
419*12c85518Srobert << *PTID.OptionalTargetID;
420*12c85518Srobert }
421*12c85518Srobert }
422