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