/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 18 | : ROCMToolChain(D, Triple, Args), HostTC(HostTC) { |
37 | | // Lookup binaries into the driver directory, this is used to |
38 | | // discover the 'amdgpu-arch' executable. |
39 | 18 | getProgramPaths().push_back(getDriver().Dir); |
40 | 18 | } |
41 | | |
42 | | void AMDGPUOpenMPToolChain::addClangTargetOptions( |
43 | | const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, |
44 | 9 | Action::OffloadKind DeviceOffloadingKind) const { |
45 | 9 | HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind); |
46 | | |
47 | 9 | StringRef GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ); |
48 | 9 | assert(!GPUArch.empty() && "Must have an explicit GPU arch."); |
49 | | |
50 | 9 | assert(DeviceOffloadingKind == Action::OFK_OpenMP && |
51 | 9 | "Only OpenMP offloading kinds are supported."); |
52 | | |
53 | 9 | CC1Args.push_back("-target-cpu"); |
54 | 9 | CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch)); |
55 | 9 | CC1Args.push_back("-fcuda-is-device"); |
56 | | |
57 | 9 | if (DriverArgs.hasArg(options::OPT_nogpulib)) |
58 | 8 | return; |
59 | | |
60 | 9 | for (auto BCFile : getDeviceLibs(DriverArgs))1 { |
61 | 9 | CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode" |
62 | 9 | : "-mlink-bitcode-file"0 ); |
63 | 9 | CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path)); |
64 | 9 | } |
65 | | |
66 | | // Link the bitcode library late if we're using device LTO. |
67 | 1 | if (getDriver().isUsingLTO(/* IsOffload */ true)) |
68 | 0 | return; |
69 | 1 | } |
70 | | |
71 | | llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs( |
72 | | const llvm::opt::DerivedArgList &Args, StringRef BoundArch, |
73 | 15 | Action::OffloadKind DeviceOffloadKind) const { |
74 | 15 | DerivedArgList *DAL = |
75 | 15 | HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind); |
76 | 15 | if (!DAL) |
77 | 2 | DAL = new DerivedArgList(Args.getBaseArgs()); |
78 | | |
79 | 15 | const OptTable &Opts = getDriver().getOpts(); |
80 | | |
81 | 15 | if (DeviceOffloadKind == Action::OFK_OpenMP) { |
82 | 13 | for (Arg *A : Args) |
83 | 111 | if (!llvm::is_contained(*DAL, A)) |
84 | 0 | DAL->append(A); |
85 | | |
86 | 13 | if (!DAL->hasArg(options::OPT_march_EQ)) { |
87 | 9 | StringRef Arch = BoundArch; |
88 | 9 | if (Arch.empty()) { |
89 | 0 | auto ArchsOrErr = getSystemGPUArchs(Args); |
90 | 0 | if (!ArchsOrErr) { |
91 | 0 | std::string ErrMsg = |
92 | 0 | llvm::formatv("{0}", llvm::fmt_consume(ArchsOrErr.takeError())); |
93 | 0 | getDriver().Diag(diag::err_drv_undetermined_gpu_arch) |
94 | 0 | << llvm::Triple::getArchTypeName(getArch()) << ErrMsg << "-march"; |
95 | 0 | Arch = CudaArchToString(CudaArch::HIPDefault); |
96 | 0 | } else { |
97 | 0 | Arch = Args.MakeArgString(ArchsOrErr->front()); |
98 | 0 | } |
99 | 0 | } |
100 | 9 | DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch); |
101 | 9 | } |
102 | | |
103 | 13 | return DAL; |
104 | 13 | } |
105 | | |
106 | 22 | for (Arg *A : Args)2 { |
107 | 22 | DAL->append(A); |
108 | 22 | } |
109 | | |
110 | 2 | if (!BoundArch.empty()) { |
111 | 1 | DAL->eraseArg(options::OPT_march_EQ); |
112 | 1 | DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), |
113 | 1 | BoundArch); |
114 | 1 | } |
115 | | |
116 | 2 | return DAL; |
117 | 15 | } |
118 | | |
119 | | void AMDGPUOpenMPToolChain::addClangWarningOptions( |
120 | 9 | ArgStringList &CC1Args) const { |
121 | 9 | HostTC.addClangWarningOptions(CC1Args); |
122 | 9 | } |
123 | | |
124 | | ToolChain::CXXStdlibType |
125 | 0 | AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const { |
126 | 0 | return HostTC.GetCXXStdlibType(Args); |
127 | 0 | } |
128 | | |
129 | | void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs( |
130 | 17 | const ArgList &DriverArgs, ArgStringList &CC1Args) const { |
131 | 17 | HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args); |
132 | 17 | } |
133 | | |
134 | | void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args, |
135 | 0 | ArgStringList &CC1Args) const { |
136 | 0 | HostTC.AddIAMCUIncludeArgs(Args, CC1Args); |
137 | 0 | } |
138 | | |
139 | 9 | 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 | 9 | return HostTC.getSupportedSanitizers(); |
150 | 9 | } |
151 | | |
152 | | VersionTuple |
153 | | AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D, |
154 | 9 | const ArgList &Args) const { |
155 | 9 | return HostTC.computeMSVCVersion(D, Args); |
156 | 9 | } |
157 | | |
158 | | llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> |
159 | 1 | AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const { |
160 | 1 | if (Args.hasArg(options::OPT_nogpulib)) |
161 | 0 | return {}; |
162 | | |
163 | 1 | if (!RocmInstallation->hasDeviceLibrary()) { |
164 | 0 | getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0; |
165 | 0 | return {}; |
166 | 0 | } |
167 | | |
168 | 1 | StringRef GpuArch = getProcessorFromTargetID( |
169 | 1 | getTriple(), Args.getLastArgValue(options::OPT_march_EQ)); |
170 | | |
171 | 1 | SmallVector<BitCodeLibraryInfo, 12> BCLibs; |
172 | 1 | for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(), |
173 | 1 | /*IsOpenMP=*/true)) |
174 | 9 | BCLibs.emplace_back(BCLib); |
175 | | |
176 | 1 | return BCLibs; |
177 | 1 | } |