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