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
26using namespace clang::driver;
27using namespace clang::driver::toolchains;
28using namespace clang::driver::tools;
29using namespace clang;
30using namespace llvm::opt;
31
32AMDGPUOpenMPToolChain::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(Elt: getDriver().Dir);
40}
41
42void AMDGPUOpenMPToolChain::addClangTargetOptions(
43 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
44 Action::OffloadKind DeviceOffloadingKind) const {
45 HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind: DeviceOffloadingKind);
46
47 StringRef GPUArch = DriverArgs.getLastArgValue(options::Id: 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(Elt: "-target-cpu");
54 CC1Args.push_back(Elt: DriverArgs.MakeArgStringRef(Str: GPUArch));
55 CC1Args.push_back(Elt: "-fcuda-is-device");
56
57 if (DriverArgs.hasArg(options::OPT_nogpulib))
58 return;
59
60 for (auto BCFile : getDeviceLibs(Args: DriverArgs)) {
61 CC1Args.push_back(Elt: BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
62 : "-mlink-bitcode-file");
63 CC1Args.push_back(Elt: DriverArgs.MakeArgString(Str: 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
71llvm::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(Range&: *DAL, Element: 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(Fmt: "{0}", Vals: llvm::fmt_consume(Item: ArchsOrErr.takeError()));
93 getDriver().Diag(diag::DiagID: err_drv_undetermined_gpu_arch)
94 << llvm::Triple::getArchTypeName(Kind: getArch()) << ErrMsg << "-march";
95 Arch = CudaArchToString(A: CudaArch::HIPDefault);
96 } else {
97 Arch = Args.MakeArgString(Str: ArchsOrErr->front());
98 }
99 }
100 DAL->AddJoinedArg(BaseArg: nullptr, Opt: Opts.getOption(options::Opt: OPT_march_EQ), Value: 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::Id: OPT_march_EQ);
112 DAL->AddJoinedArg(BaseArg: nullptr, Opt: Opts.getOption(options::Opt: OPT_march_EQ),
113 Value: BoundArch);
114 }
115
116 return DAL;
117}
118
119void AMDGPUOpenMPToolChain::addClangWarningOptions(
120 ArgStringList &CC1Args) const {
121 AMDGPUToolChain::addClangWarningOptions(CC1Args);
122 HostTC.addClangWarningOptions(CC1Args);
123}
124
125ToolChain::CXXStdlibType
126AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const {
127 return HostTC.GetCXXStdlibType(Args);
128}
129
130void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs(
131 const ArgList &DriverArgs, ArgStringList &CC1Args) const {
132 HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
133}
134
135void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
136 ArgStringList &CC1Args) const {
137 HostTC.AddIAMCUIncludeArgs(DriverArgs: Args, CC1Args);
138}
139
140SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
141 // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
142 // allows sanitizer arguments on the command line if they are supported by the
143 // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
144 // line arguments for any of these "supported" sanitizers. That means that no
145 // sanitization of device code is actually supported at this time.
146 //
147 // This behavior is necessary because the host and device toolchains
148 // invocations often share the command line, so the device toolchain must
149 // tolerate flags meant only for the host toolchain.
150 return HostTC.getSupportedSanitizers();
151}
152
153VersionTuple
154AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
155 const ArgList &Args) const {
156 return HostTC.computeMSVCVersion(D, Args);
157}
158
159llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
160AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const {
161 if (Args.hasArg(options::OPT_nogpulib))
162 return {};
163
164 if (!RocmInstallation->hasDeviceLibrary()) {
165 getDriver().Diag(diag::DiagID: err_drv_no_rocm_device_lib) << 0;
166 return {};
167 }
168
169 StringRef GpuArch = getProcessorFromTargetID(
170 getTriple(), Args.getLastArgValue(options::Id: OPT_march_EQ));
171
172 SmallVector<BitCodeLibraryInfo, 12> BCLibs;
173 for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(),
174 /*IsOpenMP=*/true))
175 BCLibs.emplace_back(BCLib);
176
177 return BCLibs;
178}
179

source code of clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp