1fe6060f1SDimitry Andric //===- AMDGPUOpenMP.cpp - AMDGPUOpenMP ToolChain Implementation -*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "AMDGPUOpenMP.h" 10fe6060f1SDimitry Andric #include "AMDGPU.h" 11fe6060f1SDimitry Andric #include "CommonArgs.h" 1269ade1e0SDimitry Andric #include "ToolChains/ROCm.h" 13fe6060f1SDimitry Andric #include "clang/Basic/DiagnosticDriver.h" 14fe6060f1SDimitry Andric #include "clang/Driver/Compilation.h" 15fe6060f1SDimitry Andric #include "clang/Driver/Driver.h" 16fe6060f1SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 17fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h" 18fe6060f1SDimitry Andric #include "clang/Driver/Options.h" 1904eeddc0SDimitry Andric #include "clang/Driver/Tool.h" 2069ade1e0SDimitry Andric #include "llvm/ADT/STLExtras.h" 21fe6060f1SDimitry Andric #include "llvm/Support/FileSystem.h" 22fe6060f1SDimitry Andric #include "llvm/Support/FormatAdapters.h" 23fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h" 24fe6060f1SDimitry Andric #include "llvm/Support/Path.h" 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric using namespace clang::driver; 27fe6060f1SDimitry Andric using namespace clang::driver::toolchains; 28fe6060f1SDimitry Andric using namespace clang::driver::tools; 29fe6060f1SDimitry Andric using namespace clang; 30fe6060f1SDimitry Andric using namespace llvm::opt; 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D, 33fe6060f1SDimitry Andric const llvm::Triple &Triple, 34fe6060f1SDimitry Andric const ToolChain &HostTC, 35fe6060f1SDimitry Andric const ArgList &Args) 36fe6060f1SDimitry Andric : ROCMToolChain(D, Triple, Args), HostTC(HostTC) { 37fe6060f1SDimitry Andric // Lookup binaries into the driver directory, this is used to 38fe6060f1SDimitry Andric // discover the clang-offload-bundler executable. 39fe6060f1SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 40fe6060f1SDimitry Andric } 41fe6060f1SDimitry Andric 42fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::addClangTargetOptions( 43fe6060f1SDimitry Andric const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 44fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadingKind) const { 45fe6060f1SDimitry Andric HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind); 46fe6060f1SDimitry Andric 47*bdd1243dSDimitry Andric StringRef GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ); 48*bdd1243dSDimitry Andric assert(!GPUArch.empty() && "Must have an explicit GPU arch."); 49fe6060f1SDimitry Andric 50fe6060f1SDimitry Andric assert(DeviceOffloadingKind == Action::OFK_OpenMP && 51fe6060f1SDimitry Andric "Only OpenMP offloading kinds are supported."); 52fe6060f1SDimitry Andric 53fe6060f1SDimitry Andric CC1Args.push_back("-target-cpu"); 54fe6060f1SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch)); 55fe6060f1SDimitry Andric CC1Args.push_back("-fcuda-is-device"); 56fe6060f1SDimitry Andric 57fe6060f1SDimitry Andric if (DriverArgs.hasArg(options::OPT_nogpulib)) 58fe6060f1SDimitry Andric return; 59fe6060f1SDimitry Andric 60*bdd1243dSDimitry Andric for (auto BCFile : getDeviceLibs(DriverArgs)) { 61*bdd1243dSDimitry Andric CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode" 62*bdd1243dSDimitry Andric : "-mlink-bitcode-file"); 63*bdd1243dSDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path)); 64*bdd1243dSDimitry Andric } 65*bdd1243dSDimitry Andric 661fd87a68SDimitry Andric // Link the bitcode library late if we're using device LTO. 671fd87a68SDimitry Andric if (getDriver().isUsingLTO(/* IsOffload */ true)) 681fd87a68SDimitry Andric return; 69fe6060f1SDimitry Andric } 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs( 72fe6060f1SDimitry Andric const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 73fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 74fe6060f1SDimitry Andric DerivedArgList *DAL = 75fe6060f1SDimitry Andric HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind); 76fe6060f1SDimitry Andric if (!DAL) 77fe6060f1SDimitry Andric DAL = new DerivedArgList(Args.getBaseArgs()); 78fe6060f1SDimitry Andric 79fe6060f1SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 80fe6060f1SDimitry Andric 8104eeddc0SDimitry Andric if (DeviceOffloadKind == Action::OFK_OpenMP) { 8204eeddc0SDimitry Andric for (Arg *A : Args) 8304eeddc0SDimitry Andric if (!llvm::is_contained(*DAL, A)) 8404eeddc0SDimitry Andric DAL->append(A); 8504eeddc0SDimitry Andric 8681ad6265SDimitry Andric if (!DAL->hasArg(options::OPT_march_EQ)) { 87*bdd1243dSDimitry Andric StringRef Arch = BoundArch; 88*bdd1243dSDimitry Andric if (Arch.empty()) { 89*bdd1243dSDimitry Andric auto ArchsOrErr = getSystemGPUArchs(Args); 90*bdd1243dSDimitry Andric if (!ArchsOrErr) { 91*bdd1243dSDimitry Andric std::string ErrMsg = 92*bdd1243dSDimitry Andric llvm::formatv("{0}", llvm::fmt_consume(ArchsOrErr.takeError())); 93*bdd1243dSDimitry Andric getDriver().Diag(diag::err_drv_undetermined_gpu_arch) 94*bdd1243dSDimitry Andric << llvm::Triple::getArchTypeName(getArch()) << ErrMsg << "-march"; 95*bdd1243dSDimitry Andric Arch = CudaArchToString(CudaArch::HIPDefault); 96*bdd1243dSDimitry Andric } else { 97*bdd1243dSDimitry Andric Arch = Args.MakeArgString(ArchsOrErr->front()); 98*bdd1243dSDimitry Andric } 99*bdd1243dSDimitry Andric } 10004eeddc0SDimitry Andric DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch); 10104eeddc0SDimitry Andric } 10204eeddc0SDimitry Andric 10304eeddc0SDimitry Andric return DAL; 10404eeddc0SDimitry Andric } 10504eeddc0SDimitry Andric 106fe6060f1SDimitry Andric for (Arg *A : Args) { 107fe6060f1SDimitry Andric DAL->append(A); 108fe6060f1SDimitry Andric } 109fe6060f1SDimitry Andric 110fe6060f1SDimitry Andric if (!BoundArch.empty()) { 111fe6060f1SDimitry Andric DAL->eraseArg(options::OPT_march_EQ); 112fe6060f1SDimitry Andric DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), 113fe6060f1SDimitry Andric BoundArch); 114fe6060f1SDimitry Andric } 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric return DAL; 117fe6060f1SDimitry Andric } 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::addClangWarningOptions( 120fe6060f1SDimitry Andric ArgStringList &CC1Args) const { 121fe6060f1SDimitry Andric HostTC.addClangWarningOptions(CC1Args); 122fe6060f1SDimitry Andric } 123fe6060f1SDimitry Andric 124fe6060f1SDimitry Andric ToolChain::CXXStdlibType 125fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const { 126fe6060f1SDimitry Andric return HostTC.GetCXXStdlibType(Args); 127fe6060f1SDimitry Andric } 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs( 130fe6060f1SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args) const { 131fe6060f1SDimitry Andric HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args); 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args, 135fe6060f1SDimitry Andric ArgStringList &CC1Args) const { 136fe6060f1SDimitry Andric HostTC.AddIAMCUIncludeArgs(Args, CC1Args); 137fe6060f1SDimitry Andric } 138fe6060f1SDimitry Andric 139fe6060f1SDimitry Andric SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const { 140fe6060f1SDimitry Andric // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it 141fe6060f1SDimitry Andric // allows sanitizer arguments on the command line if they are supported by the 142fe6060f1SDimitry Andric // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command 143fe6060f1SDimitry Andric // line arguments for any of these "supported" sanitizers. That means that no 144fe6060f1SDimitry Andric // sanitization of device code is actually supported at this time. 145fe6060f1SDimitry Andric // 146fe6060f1SDimitry Andric // This behavior is necessary because the host and device toolchains 147fe6060f1SDimitry Andric // invocations often share the command line, so the device toolchain must 148fe6060f1SDimitry Andric // tolerate flags meant only for the host toolchain. 149fe6060f1SDimitry Andric return HostTC.getSupportedSanitizers(); 150fe6060f1SDimitry Andric } 151fe6060f1SDimitry Andric 152fe6060f1SDimitry Andric VersionTuple 153fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D, 154fe6060f1SDimitry Andric const ArgList &Args) const { 155fe6060f1SDimitry Andric return HostTC.computeMSVCVersion(D, Args); 156fe6060f1SDimitry Andric } 157*bdd1243dSDimitry Andric 158*bdd1243dSDimitry Andric llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> 159*bdd1243dSDimitry Andric AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const { 160*bdd1243dSDimitry Andric if (Args.hasArg(options::OPT_nogpulib)) 161*bdd1243dSDimitry Andric return {}; 162*bdd1243dSDimitry Andric 163*bdd1243dSDimitry Andric if (!RocmInstallation.hasDeviceLibrary()) { 164*bdd1243dSDimitry Andric getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0; 165*bdd1243dSDimitry Andric return {}; 166*bdd1243dSDimitry Andric } 167*bdd1243dSDimitry Andric 168*bdd1243dSDimitry Andric StringRef GpuArch = getProcessorFromTargetID( 169*bdd1243dSDimitry Andric getTriple(), Args.getLastArgValue(options::OPT_march_EQ)); 170*bdd1243dSDimitry Andric 171*bdd1243dSDimitry Andric SmallVector<BitCodeLibraryInfo, 12> BCLibs; 172*bdd1243dSDimitry Andric for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(), 173*bdd1243dSDimitry Andric /*IsOpenMP=*/true)) 174*bdd1243dSDimitry Andric BCLibs.emplace_back(BCLib); 175*bdd1243dSDimitry Andric 176*bdd1243dSDimitry Andric return BCLibs; 177*bdd1243dSDimitry Andric } 178