clang: lib/Driver/ToolChains/HIPAMD.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
22#include "llvm/Support/Alignment.h"
23#include "llvm/Support/FileSystem.h"
24#include "llvm/Support/Path.h"
25#include "llvm/TargetParser/TargetParser.h"
26
30using namespace clang;
32
33#if defined(_WIN32) || defined(_WIN64)
34#define NULL_FILE "nul"
35#else
36#define NULL_FILE "/dev/null"
37#endif
38
39void AMDGCN::Linker::constructLlvmLinkCommand(Compilation &C,
43 const llvm::opt::ArgList &Args) const {
44
45
46 ArgStringList LlvmLinkArgs;
47
48 assert(!Inputs.empty() && "Must have at least one input.");
49
50 LlvmLinkArgs.append({"-o", Output.getFilename()});
51 for (auto Input : Inputs)
52 LlvmLinkArgs.push_back(Input.getFilename());
53
54
55
56 auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
58 TargetID, true);
59
60 const char *LlvmLink =
61 Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
63 LlvmLink, LlvmLinkArgs, Inputs,
64 Output));
65}
66
70 const llvm::opt::ArgList &Args) const {
71
72
73 ArgStringList LldArgs{"-flavor",
74 "gnu",
75 "-m",
76 "elf64_amdgpu",
77 "--no-undefined",
78 "-shared",
79 "-plugin-opt=-amdgpu-internalize-symbols"};
80 if (Args.hasArg(options::OPT_hipstdpar))
81 LldArgs.push_back("-plugin-opt=-amdgpu-enable-hipstdpar");
82
83 auto &TC = getToolChain();
84 auto &D = TC.getDriver();
85 assert(!Inputs.empty() && "Must have at least one input.");
86 bool IsThinLTO = D.getOffloadLTOMode() == LTOK_Thin;
87 addLTOOptions(TC, Args, LldArgs, Output, Inputs[0], IsThinLTO);
88
89
90 std::vectorllvm::StringRef Features;
92
93
94 std::string MAttrString = "-plugin-opt=-mattr=";
96 MAttrString.append(Args.MakeArgString(OneFeature));
97 if (OneFeature != Features.back())
98 MAttrString.append(",");
99 }
100 if (!Features.empty())
101 LldArgs.push_back(Args.MakeArgString(MAttrString));
102
103
104
105
106 if (IsThinLTO)
107 LldArgs.push_back(Args.MakeArgString("-plugin-opt=-force-import-all"));
108
109 for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
110 LldArgs.push_back(
111 Args.MakeArgString(Twine("-plugin-opt=") + A->getValue(0)));
112 }
113
114 if (C.getDriver().isSaveTempsEnabled())
115 LldArgs.push_back("-save-temps");
116
118
119
120
121
122
123
124
125
126
127
128
129 LldArgs.push_back("--whole-archive");
130
131 for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker)) {
132 StringRef ArgVal = Arg->getValue(1);
133 auto SplitArg = ArgVal.split("-mllvm=");
134 if (!SplitArg.second.empty()) {
135 LldArgs.push_back(
136 Args.MakeArgString(Twine("-plugin-opt=") + SplitArg.second));
137 } else {
138 LldArgs.push_back(Args.MakeArgString(ArgVal));
139 }
140 Arg->claim();
141 }
142
143 LldArgs.append({"-o", Output.getFilename()});
144 for (auto Input : Inputs)
145 LldArgs.push_back(Input.getFilename());
146
147
148
149 auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
151 TargetID, true);
152
153 LldArgs.push_back("--no-whole-archive");
154
155 const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
157 Lld, LldArgs, Inputs, Output));
158}
159
160
161
162
163
164
165
166void AMDGCN::Linker::constructLinkAndEmitSpirvCommand(
168 const InputInfo &Output, const llvm::opt::ArgList &Args) const {
169 assert(!Inputs.empty() && "Must have at least one input.");
170
171 constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
172
173
174
175
176 llvm::opt::ArgStringList TrArgs{
177 "--spirv-max-version=1.6",
178 "--spirv-ext=+all",
179 "--spirv-allow-unknown-intrinsics",
180 "--spirv-lower-const-expr",
181 "--spirv-preserve-auxdata",
182 "--spirv-debug-info-version=nonsemantic-shader-200"};
184}
185
186
187
188
192 const ArgList &Args,
193 const char *LinkingOutput) const {
194 if (Inputs.size() > 0 &&
195 Inputs[0].getType() == types::TY_Image &&
196 JA.getType() == types::TY_Object)
198 Args, JA, *this);
199
200 if (JA.getType() == types::TY_HIP_FATBIN)
202 Args, *this);
203
204 if (JA.getType() == types::TY_LLVM_BC)
205 return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
206
207 if (getToolChain().getEffectiveTriple().isSPIRV())
208 return constructLinkAndEmitSpirvCommand(C, JA, Inputs, Output, Args);
209
210 return constructLldCommand(C, JA, Inputs, Output, Args);
211}
212
214 const ToolChain &HostTC, const ArgList &Args)
216
217
219
220
221 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
222 true))
223 return;
224 for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
226 if (K != SanitizerKind::Address)
227 D.getDiags().Report(clang::diag::warn_drv_unsupported_option_for_target)
228 << A->getAsString(Args) << getTriple().str();
229 }
230}
231
233 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
236
238 "Only HIP offloading kinds are supported for GPUs.");
239
240 CC1Args.append({"-fcuda-is-device", "-fno-threadsafe-statics"});
241
242 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
243 false))
244 CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"});
245 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
246 CC1Args.append({"-mllvm", "-amdgpu-enable-hipstdpar"});
247
248 StringRef MaxThreadsPerBlock =
249 DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
250 if (!MaxThreadsPerBlock.empty()) {
251 std::string ArgStr =
252 (Twine("--gpu-max-threads-per-block=") + MaxThreadsPerBlock).str();
253 CC1Args.push_back(DriverArgs.MakeArgStringRef(ArgStr));
254 }
255
256 CC1Args.push_back("-fcuda-allow-variadic-functions");
257
258
259
260 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
261 options::OPT_fvisibility_ms_compat)) {
262 CC1Args.append({"-fvisibility=hidden"});
263 CC1Args.push_back("-fapply-global-visibility-to-externs");
264 }
265
267
268
269
270 if (!DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
271 CC1Args.push_back("-fembed-bitcode=marker");
272 return;
273 }
274
276 CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
277 : "-mlink-bitcode-file");
278 CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
279 }
280}
281
282llvm::opt::DerivedArgList *
284 StringRef BoundArch,
286 DerivedArgList *DAL =
288 if (!DAL)
289 DAL = new DerivedArgList(Args.getBaseArgs());
290
292
293 for (Arg *A : Args) {
295 DAL->append(A);
296 }
297
298 if (!BoundArch.empty()) {
299 DAL->eraseArg(options::OPT_mcpu_EQ);
300 DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
302 }
303
304 return DAL;
305}
306
311}
312
316}
317
321}
322
324 ArgStringList &CC1Args) const {
326}
327
329 const ArgList &Args, ArgStringList &CC1Args) const {
331}
332
334 ArgStringList &CC1Args) const {
336}
337
339 ArgStringList &CC1Args) const {
341}
342
344
345
346
347
348
349
350
351
352
354}
355
357 const ArgList &Args) const {
359}
360
364 if (DriverArgs.hasArg(options::OPT_nogpulib) ||
365 getGPUArch(DriverArgs) == "amdgcnspirv")
366 return {};
367 ArgStringList LibraryPaths;
368
369
371 LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
372
373 addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
374
375
376 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
377 if (!BCLibArgs.empty()) {
378 llvm::for_each(BCLibArgs, [&](StringRef BCName) {
380 for (StringRef LibraryPath : LibraryPaths) {
382 llvm::sys::path::append(Path, BCName);
384 if (llvm::sys::fs::exists(FullName)) {
386 return;
387 }
388 }
389 getDriver().Diag(diag::err_drv_no_such_file) << BCName;
390 });
391 } else {
393 getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
394 return {};
395 }
396 StringRef GpuArch = getGPUArch(DriverArgs);
397 assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
398
399
400 if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
401 options::OPT_fno_gpu_sanitize, true) &&
404 if (AsanRTL.empty()) {
407 "AMDGPU address sanitizer runtime library (asanrtl) is not found. "
408 "Please install ROCm device library which supports address "
409 "sanitizer");
411 return {};
412 } else
413 BCLibs.emplace_back(AsanRTL, false);
414 }
415
416
418
419
421 BCLibs.emplace_back(N);
422
423
424 auto InstLib =
425 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
426 if (InstLib.empty())
427 return BCLibs;
428 if (llvm::sys::fs::exists(InstLib))
429 BCLibs.push_back(InstLib);
430 else
431 getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
432 }
433
434 return BCLibs;
435}
436
438 const llvm::opt::ArgList &DriverArgs) const {
440 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch &&
441 PTID.OptionalTargetID != "amdgcnspirv")
442 getDriver().Diag(clang::diag::err_drv_bad_target_id)
443 << *PTID.OptionalTargetID;
444}
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
types::ID getType() const
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticsEngine & getDiags() const
DiagnosticBuilder Diag(unsigned DiagID) const
const llvm::opt::OptTable & getOpts() const
InputInfo - Wrapper for information about an input source.
const char * getFilename() const
The JSON file list parser is used to communicate input to InstallAPI.
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
static constexpr ResponseFileSupport None()
Returns a ResponseFileSupport indicating that response files are not supported.