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
;
34 static bool checkSystemForAMDGPU(const ArgList
&Args
, const AMDGPUToolChain
&TC
,
35 std::string
&GPUArch
) {
36 if (auto Err
= TC
.getSystemGPUArch(Args
, GPUArch
)) {
38 llvm::formatv("{0}", llvm::fmt_consume(std::move(Err
)));
39 TC
.getDriver().Diag(diag::err_drv_undetermined_amdgpu_arch
) << ErrMsg
;
47 AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver
&D
,
48 const llvm::Triple
&Triple
,
49 const ToolChain
&HostTC
,
51 : ROCMToolChain(D
, Triple
, Args
), HostTC(HostTC
) {
52 // Lookup binaries into the driver directory, this is used to
53 // discover the clang-offload-bundler executable.
54 getProgramPaths().push_back(getDriver().Dir
);
57 void AMDGPUOpenMPToolChain::addClangTargetOptions(
58 const llvm::opt::ArgList
&DriverArgs
, llvm::opt::ArgStringList
&CC1Args
,
59 Action::OffloadKind DeviceOffloadingKind
) const {
60 HostTC
.addClangTargetOptions(DriverArgs
, CC1Args
, DeviceOffloadingKind
);
62 std::string GPUArch
= DriverArgs
.getLastArgValue(options::OPT_march_EQ
).str();
63 if (GPUArch
.empty()) {
64 if (!checkSystemForAMDGPU(DriverArgs
, *this, GPUArch
))
68 assert(DeviceOffloadingKind
== Action::OFK_OpenMP
&&
69 "Only OpenMP offloading kinds are supported.");
71 CC1Args
.push_back("-target-cpu");
72 CC1Args
.push_back(DriverArgs
.MakeArgStringRef(GPUArch
));
73 CC1Args
.push_back("-fcuda-is-device");
75 if (DriverArgs
.hasArg(options::OPT_nogpulib
))
78 for (auto BCFile
: getDeviceLibs(DriverArgs
)) {
79 CC1Args
.push_back(BCFile
.ShouldInternalize
? "-mlink-builtin-bitcode"
80 : "-mlink-bitcode-file");
81 CC1Args
.push_back(DriverArgs
.MakeArgString(BCFile
.Path
));
84 // Link the bitcode library late if we're using device LTO.
85 if (getDriver().isUsingLTO(/* IsOffload */ true))
88 addOpenMPDeviceRTL(getDriver(), DriverArgs
, CC1Args
, GPUArch
, getTriple());
91 llvm::opt::DerivedArgList
*AMDGPUOpenMPToolChain::TranslateArgs(
92 const llvm::opt::DerivedArgList
&Args
, StringRef BoundArch
,
93 Action::OffloadKind DeviceOffloadKind
) const {
95 HostTC
.TranslateArgs(Args
, BoundArch
, DeviceOffloadKind
);
97 DAL
= new DerivedArgList(Args
.getBaseArgs());
99 const OptTable
&Opts
= getDriver().getOpts();
101 if (DeviceOffloadKind
== Action::OFK_OpenMP
) {
103 if (!llvm::is_contained(*DAL
, A
))
106 if (!DAL
->hasArg(options::OPT_march_EQ
)) {
107 std::string Arch
= BoundArch
.str();
108 if (BoundArch
.empty())
109 checkSystemForAMDGPU(Args
, *this, Arch
);
110 DAL
->AddJoinedArg(nullptr, Opts
.getOption(options::OPT_march_EQ
), Arch
);
116 for (Arg
*A
: Args
) {
120 if (!BoundArch
.empty()) {
121 DAL
->eraseArg(options::OPT_march_EQ
);
122 DAL
->AddJoinedArg(nullptr, Opts
.getOption(options::OPT_march_EQ
),
129 void AMDGPUOpenMPToolChain::addClangWarningOptions(
130 ArgStringList
&CC1Args
) const {
131 HostTC
.addClangWarningOptions(CC1Args
);
134 ToolChain::CXXStdlibType
135 AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList
&Args
) const {
136 return HostTC
.GetCXXStdlibType(Args
);
139 void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs(
140 const ArgList
&DriverArgs
, ArgStringList
&CC1Args
) const {
141 HostTC
.AddClangSystemIncludeArgs(DriverArgs
, CC1Args
);
144 void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList
&Args
,
145 ArgStringList
&CC1Args
) const {
146 HostTC
.AddIAMCUIncludeArgs(Args
, CC1Args
);
149 SanitizerMask
AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
150 // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
151 // allows sanitizer arguments on the command line if they are supported by the
152 // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
153 // line arguments for any of these "supported" sanitizers. That means that no
154 // sanitization of device code is actually supported at this time.
156 // This behavior is necessary because the host and device toolchains
157 // invocations often share the command line, so the device toolchain must
158 // tolerate flags meant only for the host toolchain.
159 return HostTC
.getSupportedSanitizers();
163 AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver
*D
,
164 const ArgList
&Args
) const {
165 return HostTC
.computeMSVCVersion(D
, Args
);
168 llvm::SmallVector
<ToolChain::BitCodeLibraryInfo
, 12>
169 AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList
&Args
) const {
170 if (Args
.hasArg(options::OPT_nogpulib
))
173 if (!RocmInstallation
.hasDeviceLibrary()) {
174 getDriver().Diag(diag::err_drv_no_rocm_device_lib
) << 0;
178 StringRef GpuArch
= getProcessorFromTargetID(
179 getTriple(), Args
.getLastArgValue(options::OPT_march_EQ
));
181 SmallVector
<BitCodeLibraryInfo
, 12> BCLibs
;
182 for (auto BCLib
: getCommonDeviceLibNames(Args
, GpuArch
.str(),
184 BCLibs
.emplace_back(BCLib
);