1 //===- AMDGPUOpenMP.cpp - AMDGPUOpenMP ToolChain Implementation -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "AMDGPUOpenMP.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"
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
;
32 AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver
&D
,
33 const llvm::Triple
&Triple
,
34 const ToolChain
&HostTC
,
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
);
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
);
47 StringRef GPUArch
= DriverArgs
.getLastArgValue(options::OPT_march_EQ
);
48 assert(!GPUArch
.empty() && "Must have an explicit GPU arch.");
50 assert(DeviceOffloadingKind
== Action::OFK_OpenMP
&&
51 "Only OpenMP offloading kinds are supported.");
53 CC1Args
.push_back("-target-cpu");
54 CC1Args
.push_back(DriverArgs
.MakeArgStringRef(GPUArch
));
55 CC1Args
.push_back("-fcuda-is-device");
57 if (DriverArgs
.hasArg(options::OPT_nogpulib
))
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
));
66 // Link the bitcode library late if we're using device LTO.
67 if (getDriver().isUsingLTO(/* IsOffload */ true))
71 llvm::opt::DerivedArgList
*AMDGPUOpenMPToolChain::TranslateArgs(
72 const llvm::opt::DerivedArgList
&Args
, StringRef BoundArch
,
73 Action::OffloadKind DeviceOffloadKind
) const {
75 HostTC
.TranslateArgs(Args
, BoundArch
, DeviceOffloadKind
);
77 DAL
= new DerivedArgList(Args
.getBaseArgs());
79 const OptTable
&Opts
= getDriver().getOpts();
81 if (DeviceOffloadKind
== Action::OFK_OpenMP
) {
83 if (!llvm::is_contained(*DAL
, A
))
86 if (!DAL
->hasArg(options::OPT_march_EQ
)) {
87 StringRef Arch
= BoundArch
;
89 auto ArchsOrErr
= getSystemGPUArchs(Args
);
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
);
97 Arch
= Args
.MakeArgString(ArchsOrErr
->front());
100 DAL
->AddJoinedArg(nullptr, Opts
.getOption(options::OPT_march_EQ
), Arch
);
106 for (Arg
*A
: Args
) {
110 if (!BoundArch
.empty()) {
111 DAL
->eraseArg(options::OPT_march_EQ
);
112 DAL
->AddJoinedArg(nullptr, Opts
.getOption(options::OPT_march_EQ
),
119 void AMDGPUOpenMPToolChain::addClangWarningOptions(
120 ArgStringList
&CC1Args
) const {
121 HostTC
.addClangWarningOptions(CC1Args
);
124 ToolChain::CXXStdlibType
125 AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList
&Args
) const {
126 return HostTC
.GetCXXStdlibType(Args
);
129 void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs(
130 const ArgList
&DriverArgs
, ArgStringList
&CC1Args
) const {
131 HostTC
.AddClangSystemIncludeArgs(DriverArgs
, CC1Args
);
134 void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList
&Args
,
135 ArgStringList
&CC1Args
) const {
136 HostTC
.AddIAMCUIncludeArgs(Args
, CC1Args
);
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.
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();
153 AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver
*D
,
154 const ArgList
&Args
) const {
155 return HostTC
.computeMSVCVersion(D
, Args
);
158 llvm::SmallVector
<ToolChain::BitCodeLibraryInfo
, 12>
159 AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList
&Args
) const {
160 if (Args
.hasArg(options::OPT_nogpulib
))
163 if (!RocmInstallation
->hasDeviceLibrary()) {
164 getDriver().Diag(diag::err_drv_no_rocm_device_lib
) << 0;
168 StringRef GpuArch
= getProcessorFromTargetID(
169 getTriple(), Args
.getLastArgValue(options::OPT_march_EQ
));
171 SmallVector
<BitCodeLibraryInfo
, 12> BCLibs
;
172 for (auto BCLib
: getCommonDeviceLibNames(Args
, GpuArch
.str(),
174 BCLibs
.emplace_back(BCLib
);