xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
AMDGPUOpenMPToolChain(const Driver & D,const llvm::Triple & Triple,const ToolChain & HostTC,const ArgList & Args)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 
addClangTargetOptions(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadingKind) const42 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   assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
48          "Only OpenMP offloading kinds are supported.");
49 
50   if (DriverArgs.hasArg(options::OPT_nogpulib))
51     return;
52 
53   for (auto BCFile : getDeviceLibs(DriverArgs)) {
54     CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
55                                                : "-mlink-bitcode-file");
56     CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
57   }
58 
59   // Link the bitcode library late if we're using device LTO.
60   if (getDriver().isUsingLTO(/* IsOffload */ true))
61     return;
62 }
63 
TranslateArgs(const llvm::opt::DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind DeviceOffloadKind) const64 llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
65     const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
66     Action::OffloadKind DeviceOffloadKind) const {
67   DerivedArgList *DAL =
68       HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
69   if (!DAL)
70     DAL = new DerivedArgList(Args.getBaseArgs());
71 
72   const OptTable &Opts = getDriver().getOpts();
73 
74   if (DeviceOffloadKind == Action::OFK_OpenMP) {
75     for (Arg *A : Args)
76       if (!llvm::is_contained(*DAL, A))
77         DAL->append(A);
78 
79     if (!DAL->hasArg(options::OPT_march_EQ)) {
80       StringRef Arch = BoundArch;
81       if (Arch.empty()) {
82         auto ArchsOrErr = getSystemGPUArchs(Args);
83         if (!ArchsOrErr) {
84           std::string ErrMsg =
85               llvm::formatv("{0}", llvm::fmt_consume(ArchsOrErr.takeError()));
86           getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
87               << llvm::Triple::getArchTypeName(getArch()) << ErrMsg << "-march";
88           Arch = OffloadArchToString(OffloadArch::HIPDefault);
89         } else {
90           Arch = Args.MakeArgString(ArchsOrErr->front());
91         }
92       }
93       DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch);
94     }
95 
96     return DAL;
97   }
98 
99   for (Arg *A : Args) {
100     DAL->append(A);
101   }
102 
103   if (!BoundArch.empty()) {
104     DAL->eraseArg(options::OPT_march_EQ);
105     DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
106                       BoundArch);
107   }
108 
109   return DAL;
110 }
111 
addClangWarningOptions(ArgStringList & CC1Args) const112 void AMDGPUOpenMPToolChain::addClangWarningOptions(
113     ArgStringList &CC1Args) const {
114   AMDGPUToolChain::addClangWarningOptions(CC1Args);
115   HostTC.addClangWarningOptions(CC1Args);
116 }
117 
118 ToolChain::CXXStdlibType
GetCXXStdlibType(const ArgList & Args) const119 AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const {
120   return HostTC.GetCXXStdlibType(Args);
121 }
122 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const123 void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs(
124     const ArgList &DriverArgs, ArgStringList &CC1Args) const {
125   HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
126 }
127 
AddIAMCUIncludeArgs(const ArgList & Args,ArgStringList & CC1Args) const128 void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
129                                                 ArgStringList &CC1Args) const {
130   HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
131 }
132 
getSupportedSanitizers() const133 SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
134   // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
135   // allows sanitizer arguments on the command line if they are supported by the
136   // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
137   // line arguments for any of these "supported" sanitizers. That means that no
138   // sanitization of device code is actually supported at this time.
139   //
140   // This behavior is necessary because the host and device toolchains
141   // invocations often share the command line, so the device toolchain must
142   // tolerate flags meant only for the host toolchain.
143   return HostTC.getSupportedSanitizers();
144 }
145 
146 VersionTuple
computeMSVCVersion(const Driver * D,const ArgList & Args) const147 AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
148                                           const ArgList &Args) const {
149   return HostTC.computeMSVCVersion(D, Args);
150 }
151 
152 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
getDeviceLibs(const llvm::opt::ArgList & Args) const153 AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const {
154   if (Args.hasArg(options::OPT_nogpulib))
155     return {};
156 
157   if (!RocmInstallation->hasDeviceLibrary()) {
158     getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
159     return {};
160   }
161 
162   StringRef GpuArch = getProcessorFromTargetID(
163       getTriple(), Args.getLastArgValue(options::OPT_march_EQ));
164 
165   SmallVector<BitCodeLibraryInfo, 12> BCLibs;
166   for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(),
167                                             /*IsOpenMP=*/true))
168     BCLibs.emplace_back(BCLib);
169 
170   return BCLibs;
171 }
172