File: | clang/lib/Driver/Driver.cpp |
Warning: | line 3458, column 5 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===// | |||
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 "clang/Driver/Driver.h" | |||
10 | #include "InputInfo.h" | |||
11 | #include "ToolChains/AIX.h" | |||
12 | #include "ToolChains/AMDGPU.h" | |||
13 | #include "ToolChains/AMDGPUOpenMP.h" | |||
14 | #include "ToolChains/AVR.h" | |||
15 | #include "ToolChains/Ananas.h" | |||
16 | #include "ToolChains/BareMetal.h" | |||
17 | #include "ToolChains/Clang.h" | |||
18 | #include "ToolChains/CloudABI.h" | |||
19 | #include "ToolChains/Contiki.h" | |||
20 | #include "ToolChains/CrossWindows.h" | |||
21 | #include "ToolChains/Cuda.h" | |||
22 | #include "ToolChains/Darwin.h" | |||
23 | #include "ToolChains/DragonFly.h" | |||
24 | #include "ToolChains/FreeBSD.h" | |||
25 | #include "ToolChains/Fuchsia.h" | |||
26 | #include "ToolChains/Gnu.h" | |||
27 | #include "ToolChains/HIP.h" | |||
28 | #include "ToolChains/Haiku.h" | |||
29 | #include "ToolChains/Hexagon.h" | |||
30 | #include "ToolChains/Hurd.h" | |||
31 | #include "ToolChains/Lanai.h" | |||
32 | #include "ToolChains/Linux.h" | |||
33 | #include "ToolChains/MSP430.h" | |||
34 | #include "ToolChains/MSVC.h" | |||
35 | #include "ToolChains/MinGW.h" | |||
36 | #include "ToolChains/Minix.h" | |||
37 | #include "ToolChains/MipsLinux.h" | |||
38 | #include "ToolChains/Myriad.h" | |||
39 | #include "ToolChains/NaCl.h" | |||
40 | #include "ToolChains/NetBSD.h" | |||
41 | #include "ToolChains/OpenBSD.h" | |||
42 | #include "ToolChains/PPCLinux.h" | |||
43 | #include "ToolChains/PS4CPU.h" | |||
44 | #include "ToolChains/RISCVToolchain.h" | |||
45 | #include "ToolChains/Solaris.h" | |||
46 | #include "ToolChains/TCE.h" | |||
47 | #include "ToolChains/VEToolchain.h" | |||
48 | #include "ToolChains/WebAssembly.h" | |||
49 | #include "ToolChains/XCore.h" | |||
50 | #include "ToolChains/ZOS.h" | |||
51 | #include "clang/Basic/TargetID.h" | |||
52 | #include "clang/Basic/Version.h" | |||
53 | #include "clang/Config/config.h" | |||
54 | #include "clang/Driver/Action.h" | |||
55 | #include "clang/Driver/Compilation.h" | |||
56 | #include "clang/Driver/DriverDiagnostic.h" | |||
57 | #include "clang/Driver/Job.h" | |||
58 | #include "clang/Driver/Options.h" | |||
59 | #include "clang/Driver/SanitizerArgs.h" | |||
60 | #include "clang/Driver/Tool.h" | |||
61 | #include "clang/Driver/ToolChain.h" | |||
62 | #include "llvm/ADT/ArrayRef.h" | |||
63 | #include "llvm/ADT/STLExtras.h" | |||
64 | #include "llvm/ADT/SmallSet.h" | |||
65 | #include "llvm/ADT/StringExtras.h" | |||
66 | #include "llvm/ADT/StringSet.h" | |||
67 | #include "llvm/ADT/StringSwitch.h" | |||
68 | #include "llvm/Config/llvm-config.h" | |||
69 | #include "llvm/Option/Arg.h" | |||
70 | #include "llvm/Option/ArgList.h" | |||
71 | #include "llvm/Option/OptSpecifier.h" | |||
72 | #include "llvm/Option/OptTable.h" | |||
73 | #include "llvm/Option/Option.h" | |||
74 | #include "llvm/Support/CommandLine.h" | |||
75 | #include "llvm/Support/ErrorHandling.h" | |||
76 | #include "llvm/Support/ExitCodes.h" | |||
77 | #include "llvm/Support/FileSystem.h" | |||
78 | #include "llvm/Support/FormatVariadic.h" | |||
79 | #include "llvm/Support/Host.h" | |||
80 | #include "llvm/Support/MD5.h" | |||
81 | #include "llvm/Support/Path.h" | |||
82 | #include "llvm/Support/PrettyStackTrace.h" | |||
83 | #include "llvm/Support/Process.h" | |||
84 | #include "llvm/Support/Program.h" | |||
85 | #include "llvm/Support/StringSaver.h" | |||
86 | #include "llvm/Support/TargetRegistry.h" | |||
87 | #include "llvm/Support/VirtualFileSystem.h" | |||
88 | #include "llvm/Support/raw_ostream.h" | |||
89 | #include <map> | |||
90 | #include <memory> | |||
91 | #include <utility> | |||
92 | #if LLVM_ON_UNIX1 | |||
93 | #include <unistd.h> // getpid | |||
94 | #endif | |||
95 | ||||
96 | using namespace clang::driver; | |||
97 | using namespace clang; | |||
98 | using namespace llvm::opt; | |||
99 | ||||
100 | static llvm::Triple getHIPOffloadTargetTriple() { | |||
101 | static const llvm::Triple T("amdgcn-amd-amdhsa"); | |||
102 | return T; | |||
103 | } | |||
104 | ||||
105 | // static | |||
106 | std::string Driver::GetResourcesPath(StringRef BinaryPath, | |||
107 | StringRef CustomResourceDir) { | |||
108 | // Since the resource directory is embedded in the module hash, it's important | |||
109 | // that all places that need it call this function, so that they get the | |||
110 | // exact same string ("a/../b/" and "b/" get different hashes, for example). | |||
111 | ||||
112 | // Dir is bin/ or lib/, depending on where BinaryPath is. | |||
113 | std::string Dir = std::string(llvm::sys::path::parent_path(BinaryPath)); | |||
114 | ||||
115 | SmallString<128> P(Dir); | |||
116 | if (CustomResourceDir != "") { | |||
117 | llvm::sys::path::append(P, CustomResourceDir); | |||
118 | } else { | |||
119 | // On Windows, libclang.dll is in bin/. | |||
120 | // On non-Windows, libclang.so/.dylib is in lib/. | |||
121 | // With a static-library build of libclang, LibClangPath will contain the | |||
122 | // path of the embedding binary, which for LLVM binaries will be in bin/. | |||
123 | // ../lib gets us to lib/ in both cases. | |||
124 | P = llvm::sys::path::parent_path(Dir); | |||
125 | llvm::sys::path::append(P, Twine("lib") + CLANG_LIBDIR_SUFFIX"", "clang", | |||
126 | CLANG_VERSION_STRING"13.0.0"); | |||
127 | } | |||
128 | ||||
129 | return std::string(P.str()); | |||
130 | } | |||
131 | ||||
132 | Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, | |||
133 | DiagnosticsEngine &Diags, std::string Title, | |||
134 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) | |||
135 | : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), | |||
136 | SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None), | |||
137 | ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT""), | |||
138 | DriverTitle(Title), CCPrintStatReportFilename(), CCPrintOptionsFilename(), | |||
139 | CCPrintHeadersFilename(), CCLogDiagnosticsFilename(), | |||
140 | CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), | |||
141 | CCLogDiagnostics(false), CCGenDiagnostics(false), | |||
142 | CCPrintProcessStats(false), TargetTriple(TargetTriple), | |||
143 | CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true), | |||
144 | GenReproducer(false), SuppressMissingInputWarning(false) { | |||
145 | // Provide a sane fallback if no VFS is specified. | |||
146 | if (!this->VFS) | |||
147 | this->VFS = llvm::vfs::getRealFileSystem(); | |||
148 | ||||
149 | Name = std::string(llvm::sys::path::filename(ClangExecutable)); | |||
150 | Dir = std::string(llvm::sys::path::parent_path(ClangExecutable)); | |||
151 | InstalledDir = Dir; // Provide a sensible default installed dir. | |||
152 | ||||
153 | if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) { | |||
154 | // Prepend InstalledDir if SysRoot is relative | |||
155 | SmallString<128> P(InstalledDir); | |||
156 | llvm::sys::path::append(P, SysRoot); | |||
157 | SysRoot = std::string(P); | |||
158 | } | |||
159 | ||||
160 | #if defined(CLANG_CONFIG_FILE_SYSTEM_DIR) | |||
161 | SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR; | |||
162 | #endif | |||
163 | #if defined(CLANG_CONFIG_FILE_USER_DIR) | |||
164 | UserConfigDir = CLANG_CONFIG_FILE_USER_DIR; | |||
165 | #endif | |||
166 | ||||
167 | // Compute the path to the resource directory. | |||
168 | ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR""); | |||
169 | } | |||
170 | ||||
171 | void Driver::ParseDriverMode(StringRef ProgramName, | |||
172 | ArrayRef<const char *> Args) { | |||
173 | if (ClangNameParts.isEmpty()) | |||
174 | ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName); | |||
175 | setDriverModeFromOption(ClangNameParts.DriverMode); | |||
176 | ||||
177 | for (const char *ArgPtr : Args) { | |||
178 | // Ignore nullptrs, they are the response file's EOL markers. | |||
179 | if (ArgPtr == nullptr) | |||
180 | continue; | |||
181 | const StringRef Arg = ArgPtr; | |||
182 | setDriverModeFromOption(Arg); | |||
183 | } | |||
184 | } | |||
185 | ||||
186 | void Driver::setDriverModeFromOption(StringRef Opt) { | |||
187 | const std::string OptName = | |||
188 | getOpts().getOption(options::OPT_driver_mode).getPrefixedName(); | |||
189 | if (!Opt.startswith(OptName)) | |||
190 | return; | |||
191 | StringRef Value = Opt.drop_front(OptName.size()); | |||
192 | ||||
193 | if (auto M = llvm::StringSwitch<llvm::Optional<DriverMode>>(Value) | |||
194 | .Case("gcc", GCCMode) | |||
195 | .Case("g++", GXXMode) | |||
196 | .Case("cpp", CPPMode) | |||
197 | .Case("cl", CLMode) | |||
198 | .Case("flang", FlangMode) | |||
199 | .Default(None)) | |||
200 | Mode = *M; | |||
201 | else | |||
202 | Diag(diag::err_drv_unsupported_option_argument) << OptName << Value; | |||
203 | } | |||
204 | ||||
205 | InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings, | |||
206 | bool IsClCompatMode, | |||
207 | bool &ContainsError) { | |||
208 | llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); | |||
209 | ContainsError = false; | |||
210 | ||||
211 | unsigned IncludedFlagsBitmask; | |||
212 | unsigned ExcludedFlagsBitmask; | |||
213 | std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = | |||
214 | getIncludeExcludeOptionFlagMasks(IsClCompatMode); | |||
215 | ||||
216 | // Make sure that Flang-only options don't pollute the Clang output | |||
217 | // TODO: Make sure that Clang-only options don't pollute Flang output | |||
218 | if (!IsFlangMode()) | |||
219 | ExcludedFlagsBitmask |= options::FlangOnlyOption; | |||
220 | ||||
221 | unsigned MissingArgIndex, MissingArgCount; | |||
222 | InputArgList Args = | |||
223 | getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, | |||
224 | IncludedFlagsBitmask, ExcludedFlagsBitmask); | |||
225 | ||||
226 | // Check for missing argument error. | |||
227 | if (MissingArgCount) { | |||
228 | Diag(diag::err_drv_missing_argument) | |||
229 | << Args.getArgString(MissingArgIndex) << MissingArgCount; | |||
230 | ContainsError |= | |||
231 | Diags.getDiagnosticLevel(diag::err_drv_missing_argument, | |||
232 | SourceLocation()) > DiagnosticsEngine::Warning; | |||
233 | } | |||
234 | ||||
235 | // Check for unsupported options. | |||
236 | for (const Arg *A : Args) { | |||
237 | if (A->getOption().hasFlag(options::Unsupported)) { | |||
238 | unsigned DiagID; | |||
239 | auto ArgString = A->getAsString(Args); | |||
240 | std::string Nearest; | |||
241 | if (getOpts().findNearest( | |||
242 | ArgString, Nearest, IncludedFlagsBitmask, | |||
243 | ExcludedFlagsBitmask | options::Unsupported) > 1) { | |||
244 | DiagID = diag::err_drv_unsupported_opt; | |||
245 | Diag(DiagID) << ArgString; | |||
246 | } else { | |||
247 | DiagID = diag::err_drv_unsupported_opt_with_suggestion; | |||
248 | Diag(DiagID) << ArgString << Nearest; | |||
249 | } | |||
250 | ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > | |||
251 | DiagnosticsEngine::Warning; | |||
252 | continue; | |||
253 | } | |||
254 | ||||
255 | // Warn about -mcpu= without an argument. | |||
256 | if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) { | |||
257 | Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args); | |||
258 | ContainsError |= Diags.getDiagnosticLevel( | |||
259 | diag::warn_drv_empty_joined_argument, | |||
260 | SourceLocation()) > DiagnosticsEngine::Warning; | |||
261 | } | |||
262 | } | |||
263 | ||||
264 | for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) { | |||
265 | unsigned DiagID; | |||
266 | auto ArgString = A->getAsString(Args); | |||
267 | std::string Nearest; | |||
268 | if (getOpts().findNearest( | |||
269 | ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) { | |||
270 | DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl | |||
271 | : diag::err_drv_unknown_argument; | |||
272 | Diags.Report(DiagID) << ArgString; | |||
273 | } else { | |||
274 | DiagID = IsCLMode() | |||
275 | ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion | |||
276 | : diag::err_drv_unknown_argument_with_suggestion; | |||
277 | Diags.Report(DiagID) << ArgString << Nearest; | |||
278 | } | |||
279 | ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > | |||
280 | DiagnosticsEngine::Warning; | |||
281 | } | |||
282 | ||||
283 | return Args; | |||
284 | } | |||
285 | ||||
286 | // Determine which compilation mode we are in. We look for options which | |||
287 | // affect the phase, starting with the earliest phases, and record which | |||
288 | // option we used to determine the final phase. | |||
289 | phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, | |||
290 | Arg **FinalPhaseArg) const { | |||
291 | Arg *PhaseArg = nullptr; | |||
292 | phases::ID FinalPhase; | |||
293 | ||||
294 | // -{E,EP,P,M,MM} only run the preprocessor. | |||
295 | if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || | |||
296 | (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) || | |||
297 | (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || | |||
298 | (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) { | |||
299 | FinalPhase = phases::Preprocess; | |||
300 | ||||
301 | // --precompile only runs up to precompilation. | |||
302 | } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) { | |||
303 | FinalPhase = phases::Precompile; | |||
304 | ||||
305 | // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. | |||
306 | } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || | |||
307 | (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || | |||
308 | (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || | |||
309 | (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || | |||
310 | (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || | |||
311 | (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || | |||
312 | (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || | |||
313 | (PhaseArg = DAL.getLastArg(options::OPT__analyze)) || | |||
314 | (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { | |||
315 | FinalPhase = phases::Compile; | |||
316 | ||||
317 | // -S only runs up to the backend. | |||
318 | } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) { | |||
319 | FinalPhase = phases::Backend; | |||
320 | ||||
321 | // -c compilation only runs up to the assembler. | |||
322 | } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) { | |||
323 | FinalPhase = phases::Assemble; | |||
324 | ||||
325 | // Otherwise do everything. | |||
326 | } else | |||
327 | FinalPhase = phases::Link; | |||
328 | ||||
329 | if (FinalPhaseArg) | |||
330 | *FinalPhaseArg = PhaseArg; | |||
331 | ||||
332 | return FinalPhase; | |||
333 | } | |||
334 | ||||
335 | static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts, | |||
336 | StringRef Value, bool Claim = true) { | |||
337 | Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value, | |||
338 | Args.getBaseArgs().MakeIndex(Value), Value.data()); | |||
339 | Args.AddSynthesizedArg(A); | |||
340 | if (Claim) | |||
341 | A->claim(); | |||
342 | return A; | |||
343 | } | |||
344 | ||||
345 | DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { | |||
346 | const llvm::opt::OptTable &Opts = getOpts(); | |||
347 | DerivedArgList *DAL = new DerivedArgList(Args); | |||
348 | ||||
349 | bool HasNostdlib = Args.hasArg(options::OPT_nostdlib); | |||
350 | bool HasNostdlibxx = Args.hasArg(options::OPT_nostdlibxx); | |||
351 | bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs); | |||
352 | for (Arg *A : Args) { | |||
353 | // Unfortunately, we have to parse some forwarding options (-Xassembler, | |||
354 | // -Xlinker, -Xpreprocessor) because we either integrate their functionality | |||
355 | // (assembler and preprocessor), or bypass a previous driver ('collect2'). | |||
356 | ||||
357 | // Rewrite linker options, to replace --no-demangle with a custom internal | |||
358 | // option. | |||
359 | if ((A->getOption().matches(options::OPT_Wl_COMMA) || | |||
360 | A->getOption().matches(options::OPT_Xlinker)) && | |||
361 | A->containsValue("--no-demangle")) { | |||
362 | // Add the rewritten no-demangle argument. | |||
363 | DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_Xlinker__no_demangle)); | |||
364 | ||||
365 | // Add the remaining values as Xlinker arguments. | |||
366 | for (StringRef Val : A->getValues()) | |||
367 | if (Val != "--no-demangle") | |||
368 | DAL->AddSeparateArg(A, Opts.getOption(options::OPT_Xlinker), Val); | |||
369 | ||||
370 | continue; | |||
371 | } | |||
372 | ||||
373 | // Rewrite preprocessor options, to replace -Wp,-MD,FOO which is used by | |||
374 | // some build systems. We don't try to be complete here because we don't | |||
375 | // care to encourage this usage model. | |||
376 | if (A->getOption().matches(options::OPT_Wp_COMMA) && | |||
377 | (A->getValue(0) == StringRef("-MD") || | |||
378 | A->getValue(0) == StringRef("-MMD"))) { | |||
379 | // Rewrite to -MD/-MMD along with -MF. | |||
380 | if (A->getValue(0) == StringRef("-MD")) | |||
381 | DAL->AddFlagArg(A, Opts.getOption(options::OPT_MD)); | |||
382 | else | |||
383 | DAL->AddFlagArg(A, Opts.getOption(options::OPT_MMD)); | |||
384 | if (A->getNumValues() == 2) | |||
385 | DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue(1)); | |||
386 | continue; | |||
387 | } | |||
388 | ||||
389 | // Rewrite reserved library names. | |||
390 | if (A->getOption().matches(options::OPT_l)) { | |||
391 | StringRef Value = A->getValue(); | |||
392 | ||||
393 | // Rewrite unless -nostdlib is present. | |||
394 | if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx && | |||
395 | Value == "stdc++") { | |||
396 | DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_stdcxx)); | |||
397 | continue; | |||
398 | } | |||
399 | ||||
400 | // Rewrite unconditionally. | |||
401 | if (Value == "cc_kext") { | |||
402 | DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_cckext)); | |||
403 | continue; | |||
404 | } | |||
405 | } | |||
406 | ||||
407 | // Pick up inputs via the -- option. | |||
408 | if (A->getOption().matches(options::OPT__DASH_DASH)) { | |||
409 | A->claim(); | |||
410 | for (StringRef Val : A->getValues()) | |||
411 | DAL->append(MakeInputArg(*DAL, Opts, Val, false)); | |||
412 | continue; | |||
413 | } | |||
414 | ||||
415 | DAL->append(A); | |||
416 | } | |||
417 | ||||
418 | // Enforce -static if -miamcu is present. | |||
419 | if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) | |||
420 | DAL->AddFlagArg(0, Opts.getOption(options::OPT_static)); | |||
421 | ||||
422 | // Add a default value of -mlinker-version=, if one was given and the user | |||
423 | // didn't specify one. | |||
424 | #if defined(HOST_LINK_VERSION) | |||
425 | if (!Args.hasArg(options::OPT_mlinker_version_EQ) && | |||
426 | strlen(HOST_LINK_VERSION) > 0) { | |||
427 | DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mlinker_version_EQ), | |||
428 | HOST_LINK_VERSION); | |||
429 | DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim(); | |||
430 | } | |||
431 | #endif | |||
432 | ||||
433 | return DAL; | |||
434 | } | |||
435 | ||||
436 | /// Compute target triple from args. | |||
437 | /// | |||
438 | /// This routine provides the logic to compute a target triple from various | |||
439 | /// args passed to the driver and the default triple string. | |||
440 | static llvm::Triple computeTargetTriple(const Driver &D, | |||
441 | StringRef TargetTriple, | |||
442 | const ArgList &Args, | |||
443 | StringRef DarwinArchName = "") { | |||
444 | // FIXME: Already done in Compilation *Driver::BuildCompilation | |||
445 | if (const Arg *A = Args.getLastArg(options::OPT_target)) | |||
446 | TargetTriple = A->getValue(); | |||
447 | ||||
448 | llvm::Triple Target(llvm::Triple::normalize(TargetTriple)); | |||
449 | ||||
450 | // GNU/Hurd's triples should have been -hurd-gnu*, but were historically made | |||
451 | // -gnu* only, and we can not change this, so we have to detect that case as | |||
452 | // being the Hurd OS. | |||
453 | if (TargetTriple.find("-unknown-gnu") != StringRef::npos || | |||
454 | TargetTriple.find("-pc-gnu") != StringRef::npos) | |||
455 | Target.setOSName("hurd"); | |||
456 | ||||
457 | // Handle Apple-specific options available here. | |||
458 | if (Target.isOSBinFormatMachO()) { | |||
459 | // If an explicit Darwin arch name is given, that trumps all. | |||
460 | if (!DarwinArchName.empty()) { | |||
461 | tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName); | |||
462 | return Target; | |||
463 | } | |||
464 | ||||
465 | // Handle the Darwin '-arch' flag. | |||
466 | if (Arg *A = Args.getLastArg(options::OPT_arch)) { | |||
467 | StringRef ArchName = A->getValue(); | |||
468 | tools::darwin::setTripleTypeForMachOArchName(Target, ArchName); | |||
469 | } | |||
470 | } | |||
471 | ||||
472 | // Handle pseudo-target flags '-mlittle-endian'/'-EL' and | |||
473 | // '-mbig-endian'/'-EB'. | |||
474 | if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian, | |||
475 | options::OPT_mbig_endian)) { | |||
476 | if (A->getOption().matches(options::OPT_mlittle_endian)) { | |||
477 | llvm::Triple LE = Target.getLittleEndianArchVariant(); | |||
478 | if (LE.getArch() != llvm::Triple::UnknownArch) | |||
479 | Target = std::move(LE); | |||
480 | } else { | |||
481 | llvm::Triple BE = Target.getBigEndianArchVariant(); | |||
482 | if (BE.getArch() != llvm::Triple::UnknownArch) | |||
483 | Target = std::move(BE); | |||
484 | } | |||
485 | } | |||
486 | ||||
487 | // Skip further flag support on OSes which don't support '-m32' or '-m64'. | |||
488 | if (Target.getArch() == llvm::Triple::tce || | |||
489 | Target.getOS() == llvm::Triple::Minix) | |||
490 | return Target; | |||
491 | ||||
492 | // On AIX, the env OBJECT_MODE may affect the resulting arch variant. | |||
493 | if (Target.isOSAIX()) { | |||
494 | if (Optional<std::string> ObjectModeValue = | |||
495 | llvm::sys::Process::GetEnv("OBJECT_MODE")) { | |||
496 | StringRef ObjectMode = *ObjectModeValue; | |||
497 | llvm::Triple::ArchType AT = llvm::Triple::UnknownArch; | |||
498 | ||||
499 | if (ObjectMode.equals("64")) { | |||
500 | AT = Target.get64BitArchVariant().getArch(); | |||
501 | } else if (ObjectMode.equals("32")) { | |||
502 | AT = Target.get32BitArchVariant().getArch(); | |||
503 | } else { | |||
504 | D.Diag(diag::err_drv_invalid_object_mode) << ObjectMode; | |||
505 | } | |||
506 | ||||
507 | if (AT != llvm::Triple::UnknownArch && AT != Target.getArch()) | |||
508 | Target.setArch(AT); | |||
509 | } | |||
510 | } | |||
511 | ||||
512 | // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'. | |||
513 | Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32, | |||
514 | options::OPT_m32, options::OPT_m16); | |||
515 | if (A) { | |||
516 | llvm::Triple::ArchType AT = llvm::Triple::UnknownArch; | |||
517 | ||||
518 | if (A->getOption().matches(options::OPT_m64)) { | |||
519 | AT = Target.get64BitArchVariant().getArch(); | |||
520 | if (Target.getEnvironment() == llvm::Triple::GNUX32) | |||
521 | Target.setEnvironment(llvm::Triple::GNU); | |||
522 | } else if (A->getOption().matches(options::OPT_mx32) && | |||
523 | Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) { | |||
524 | AT = llvm::Triple::x86_64; | |||
525 | Target.setEnvironment(llvm::Triple::GNUX32); | |||
526 | } else if (A->getOption().matches(options::OPT_m32)) { | |||
527 | AT = Target.get32BitArchVariant().getArch(); | |||
528 | if (Target.getEnvironment() == llvm::Triple::GNUX32) | |||
529 | Target.setEnvironment(llvm::Triple::GNU); | |||
530 | } else if (A->getOption().matches(options::OPT_m16) && | |||
531 | Target.get32BitArchVariant().getArch() == llvm::Triple::x86) { | |||
532 | AT = llvm::Triple::x86; | |||
533 | Target.setEnvironment(llvm::Triple::CODE16); | |||
534 | } | |||
535 | ||||
536 | if (AT != llvm::Triple::UnknownArch && AT != Target.getArch()) | |||
537 | Target.setArch(AT); | |||
538 | } | |||
539 | ||||
540 | // Handle -miamcu flag. | |||
541 | if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) { | |||
542 | if (Target.get32BitArchVariant().getArch() != llvm::Triple::x86) | |||
543 | D.Diag(diag::err_drv_unsupported_opt_for_target) << "-miamcu" | |||
544 | << Target.str(); | |||
545 | ||||
546 | if (A && !A->getOption().matches(options::OPT_m32)) | |||
547 | D.Diag(diag::err_drv_argument_not_allowed_with) | |||
548 | << "-miamcu" << A->getBaseArg().getAsString(Args); | |||
549 | ||||
550 | Target.setArch(llvm::Triple::x86); | |||
551 | Target.setArchName("i586"); | |||
552 | Target.setEnvironment(llvm::Triple::UnknownEnvironment); | |||
553 | Target.setEnvironmentName(""); | |||
554 | Target.setOS(llvm::Triple::ELFIAMCU); | |||
555 | Target.setVendor(llvm::Triple::UnknownVendor); | |||
556 | Target.setVendorName("intel"); | |||
557 | } | |||
558 | ||||
559 | // If target is MIPS adjust the target triple | |||
560 | // accordingly to provided ABI name. | |||
561 | A = Args.getLastArg(options::OPT_mabi_EQ); | |||
562 | if (A && Target.isMIPS()) { | |||
563 | StringRef ABIName = A->getValue(); | |||
564 | if (ABIName == "32") { | |||
565 | Target = Target.get32BitArchVariant(); | |||
566 | if (Target.getEnvironment() == llvm::Triple::GNUABI64 || | |||
567 | Target.getEnvironment() == llvm::Triple::GNUABIN32) | |||
568 | Target.setEnvironment(llvm::Triple::GNU); | |||
569 | } else if (ABIName == "n32") { | |||
570 | Target = Target.get64BitArchVariant(); | |||
571 | if (Target.getEnvironment() == llvm::Triple::GNU || | |||
572 | Target.getEnvironment() == llvm::Triple::GNUABI64) | |||
573 | Target.setEnvironment(llvm::Triple::GNUABIN32); | |||
574 | } else if (ABIName == "64") { | |||
575 | Target = Target.get64BitArchVariant(); | |||
576 | if (Target.getEnvironment() == llvm::Triple::GNU || | |||
577 | Target.getEnvironment() == llvm::Triple::GNUABIN32) | |||
578 | Target.setEnvironment(llvm::Triple::GNUABI64); | |||
579 | } | |||
580 | } | |||
581 | ||||
582 | // If target is RISC-V adjust the target triple according to | |||
583 | // provided architecture name | |||
584 | A = Args.getLastArg(options::OPT_march_EQ); | |||
585 | if (A && Target.isRISCV()) { | |||
586 | StringRef ArchName = A->getValue(); | |||
587 | if (ArchName.startswith_lower("rv32")) | |||
588 | Target.setArch(llvm::Triple::riscv32); | |||
589 | else if (ArchName.startswith_lower("rv64")) | |||
590 | Target.setArch(llvm::Triple::riscv64); | |||
591 | } | |||
592 | ||||
593 | return Target; | |||
594 | } | |||
595 | ||||
596 | // Parse the LTO options and record the type of LTO compilation | |||
597 | // based on which -f(no-)?lto(=.*)? option occurs last. | |||
598 | void Driver::setLTOMode(const llvm::opt::ArgList &Args) { | |||
599 | LTOMode = LTOK_None; | |||
600 | if (!Args.hasFlag(options::OPT_flto, options::OPT_flto_EQ, | |||
601 | options::OPT_fno_lto, false)) | |||
602 | return; | |||
603 | ||||
604 | StringRef LTOName("full"); | |||
605 | ||||
606 | const Arg *A = Args.getLastArg(options::OPT_flto_EQ); | |||
607 | if (A) | |||
608 | LTOName = A->getValue(); | |||
609 | ||||
610 | LTOMode = llvm::StringSwitch<LTOKind>(LTOName) | |||
611 | .Case("full", LTOK_Full) | |||
612 | .Case("thin", LTOK_Thin) | |||
613 | .Default(LTOK_Unknown); | |||
614 | ||||
615 | if (LTOMode == LTOK_Unknown) { | |||
616 | assert(A)(static_cast <bool> (A) ? void (0) : __assert_fail ("A" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 616, __extension__ __PRETTY_FUNCTION__)); | |||
617 | Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() | |||
618 | << A->getValue(); | |||
619 | } | |||
620 | } | |||
621 | ||||
622 | /// Compute the desired OpenMP runtime from the flags provided. | |||
623 | Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const { | |||
624 | StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME"libomp"); | |||
625 | ||||
626 | const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ); | |||
627 | if (A) | |||
628 | RuntimeName = A->getValue(); | |||
629 | ||||
630 | auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName) | |||
631 | .Case("libomp", OMPRT_OMP) | |||
632 | .Case("libgomp", OMPRT_GOMP) | |||
633 | .Case("libiomp5", OMPRT_IOMP5) | |||
634 | .Default(OMPRT_Unknown); | |||
635 | ||||
636 | if (RT == OMPRT_Unknown) { | |||
637 | if (A) | |||
638 | Diag(diag::err_drv_unsupported_option_argument) | |||
639 | << A->getOption().getName() << A->getValue(); | |||
640 | else | |||
641 | // FIXME: We could use a nicer diagnostic here. | |||
642 | Diag(diag::err_drv_unsupported_opt) << "-fopenmp"; | |||
643 | } | |||
644 | ||||
645 | return RT; | |||
646 | } | |||
647 | ||||
648 | void Driver::CreateOffloadingDeviceToolChains(Compilation &C, | |||
649 | InputList &Inputs) { | |||
650 | ||||
651 | // | |||
652 | // CUDA/HIP | |||
653 | // | |||
654 | // We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA | |||
655 | // or HIP type. However, mixed CUDA/HIP compilation is not supported. | |||
656 | bool IsCuda = | |||
657 | llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) { | |||
658 | return types::isCuda(I.first); | |||
659 | }); | |||
660 | bool IsHIP = | |||
661 | llvm::any_of(Inputs, | |||
662 | [](std::pair<types::ID, const llvm::opt::Arg *> &I) { | |||
663 | return types::isHIP(I.first); | |||
664 | }) || | |||
665 | C.getInputArgs().hasArg(options::OPT_hip_link); | |||
666 | if (IsCuda && IsHIP) { | |||
667 | Diag(clang::diag::err_drv_mix_cuda_hip); | |||
668 | return; | |||
669 | } | |||
670 | if (IsCuda) { | |||
671 | const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>(); | |||
672 | const llvm::Triple &HostTriple = HostTC->getTriple(); | |||
673 | StringRef DeviceTripleStr; | |||
674 | auto OFK = Action::OFK_Cuda; | |||
675 | DeviceTripleStr = | |||
676 | HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda"; | |||
677 | llvm::Triple CudaTriple(DeviceTripleStr); | |||
678 | // Use the CUDA and host triples as the key into the ToolChains map, | |||
679 | // because the device toolchain we create depends on both. | |||
680 | auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()]; | |||
681 | if (!CudaTC) { | |||
682 | CudaTC = std::make_unique<toolchains::CudaToolChain>( | |||
683 | *this, CudaTriple, *HostTC, C.getInputArgs(), OFK); | |||
684 | } | |||
685 | C.addOffloadDeviceToolChain(CudaTC.get(), OFK); | |||
686 | } else if (IsHIP) { | |||
687 | const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>(); | |||
688 | const llvm::Triple &HostTriple = HostTC->getTriple(); | |||
689 | auto OFK = Action::OFK_HIP; | |||
690 | llvm::Triple HIPTriple = getHIPOffloadTargetTriple(); | |||
691 | // Use the HIP and host triples as the key into the ToolChains map, | |||
692 | // because the device toolchain we create depends on both. | |||
693 | auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()]; | |||
694 | if (!HIPTC) { | |||
695 | HIPTC = std::make_unique<toolchains::HIPToolChain>( | |||
696 | *this, HIPTriple, *HostTC, C.getInputArgs()); | |||
697 | } | |||
698 | C.addOffloadDeviceToolChain(HIPTC.get(), OFK); | |||
699 | } | |||
700 | ||||
701 | // | |||
702 | // OpenMP | |||
703 | // | |||
704 | // We need to generate an OpenMP toolchain if the user specified targets with | |||
705 | // the -fopenmp-targets option. | |||
706 | if (Arg *OpenMPTargets = | |||
707 | C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) { | |||
708 | if (OpenMPTargets->getNumValues()) { | |||
709 | // We expect that -fopenmp-targets is always used in conjunction with the | |||
710 | // option -fopenmp specifying a valid runtime with offloading support, | |||
711 | // i.e. libomp or libiomp. | |||
712 | bool HasValidOpenMPRuntime = C.getInputArgs().hasFlag( | |||
713 | options::OPT_fopenmp, options::OPT_fopenmp_EQ, | |||
714 | options::OPT_fno_openmp, false); | |||
715 | if (HasValidOpenMPRuntime) { | |||
716 | OpenMPRuntimeKind OpenMPKind = getOpenMPRuntime(C.getInputArgs()); | |||
717 | HasValidOpenMPRuntime = | |||
718 | OpenMPKind == OMPRT_OMP || OpenMPKind == OMPRT_IOMP5; | |||
719 | } | |||
720 | ||||
721 | if (HasValidOpenMPRuntime) { | |||
722 | llvm::StringMap<const char *> FoundNormalizedTriples; | |||
723 | for (const char *Val : OpenMPTargets->getValues()) { | |||
724 | llvm::Triple TT(Val); | |||
725 | std::string NormalizedName = TT.normalize(); | |||
726 | ||||
727 | // Make sure we don't have a duplicate triple. | |||
728 | auto Duplicate = FoundNormalizedTriples.find(NormalizedName); | |||
729 | if (Duplicate != FoundNormalizedTriples.end()) { | |||
730 | Diag(clang::diag::warn_drv_omp_offload_target_duplicate) | |||
731 | << Val << Duplicate->second; | |||
732 | continue; | |||
733 | } | |||
734 | ||||
735 | // Store the current triple so that we can check for duplicates in the | |||
736 | // following iterations. | |||
737 | FoundNormalizedTriples[NormalizedName] = Val; | |||
738 | ||||
739 | // If the specified target is invalid, emit a diagnostic. | |||
740 | if (TT.getArch() == llvm::Triple::UnknownArch) | |||
741 | Diag(clang::diag::err_drv_invalid_omp_target) << Val; | |||
742 | else { | |||
743 | const ToolChain *TC; | |||
744 | // Device toolchains have to be selected differently. They pair host | |||
745 | // and device in their implementation. | |||
746 | if (TT.isNVPTX() || TT.isAMDGCN()) { | |||
747 | const ToolChain *HostTC = | |||
748 | C.getSingleOffloadToolChain<Action::OFK_Host>(); | |||
749 | assert(HostTC && "Host toolchain should be always defined.")(static_cast <bool> (HostTC && "Host toolchain should be always defined." ) ? void (0) : __assert_fail ("HostTC && \"Host toolchain should be always defined.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 749, __extension__ __PRETTY_FUNCTION__)); | |||
750 | auto &DeviceTC = | |||
751 | ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()]; | |||
752 | if (!DeviceTC) { | |||
753 | if (TT.isNVPTX()) | |||
754 | DeviceTC = std::make_unique<toolchains::CudaToolChain>( | |||
755 | *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP); | |||
756 | else if (TT.isAMDGCN()) | |||
757 | DeviceTC = | |||
758 | std::make_unique<toolchains::AMDGPUOpenMPToolChain>( | |||
759 | *this, TT, *HostTC, C.getInputArgs()); | |||
760 | else | |||
761 | assert(DeviceTC && "Device toolchain not defined.")(static_cast <bool> (DeviceTC && "Device toolchain not defined." ) ? void (0) : __assert_fail ("DeviceTC && \"Device toolchain not defined.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 761, __extension__ __PRETTY_FUNCTION__)); | |||
762 | } | |||
763 | ||||
764 | TC = DeviceTC.get(); | |||
765 | } else | |||
766 | TC = &getToolChain(C.getInputArgs(), TT); | |||
767 | C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP); | |||
768 | } | |||
769 | } | |||
770 | } else | |||
771 | Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets); | |||
772 | } else | |||
773 | Diag(clang::diag::warn_drv_empty_joined_argument) | |||
774 | << OpenMPTargets->getAsString(C.getInputArgs()); | |||
775 | } | |||
776 | ||||
777 | // | |||
778 | // TODO: Add support for other offloading programming models here. | |||
779 | // | |||
780 | } | |||
781 | ||||
782 | /// Looks the given directories for the specified file. | |||
783 | /// | |||
784 | /// \param[out] FilePath File path, if the file was found. | |||
785 | /// \param[in] Dirs Directories used for the search. | |||
786 | /// \param[in] FileName Name of the file to search for. | |||
787 | /// \return True if file was found. | |||
788 | /// | |||
789 | /// Looks for file specified by FileName sequentially in directories specified | |||
790 | /// by Dirs. | |||
791 | /// | |||
792 | static bool searchForFile(SmallVectorImpl<char> &FilePath, | |||
793 | ArrayRef<StringRef> Dirs, StringRef FileName) { | |||
794 | SmallString<128> WPath; | |||
795 | for (const StringRef &Dir : Dirs) { | |||
796 | if (Dir.empty()) | |||
797 | continue; | |||
798 | WPath.clear(); | |||
799 | llvm::sys::path::append(WPath, Dir, FileName); | |||
800 | llvm::sys::path::native(WPath); | |||
801 | if (llvm::sys::fs::is_regular_file(WPath)) { | |||
802 | FilePath = std::move(WPath); | |||
803 | return true; | |||
804 | } | |||
805 | } | |||
806 | return false; | |||
807 | } | |||
808 | ||||
809 | bool Driver::readConfigFile(StringRef FileName) { | |||
810 | // Try reading the given file. | |||
811 | SmallVector<const char *, 32> NewCfgArgs; | |||
812 | if (!llvm::cl::readConfigFile(FileName, Saver, NewCfgArgs)) { | |||
813 | Diag(diag::err_drv_cannot_read_config_file) << FileName; | |||
814 | return true; | |||
815 | } | |||
816 | ||||
817 | // Read options from config file. | |||
818 | llvm::SmallString<128> CfgFileName(FileName); | |||
819 | llvm::sys::path::native(CfgFileName); | |||
820 | ConfigFile = std::string(CfgFileName); | |||
821 | bool ContainErrors; | |||
822 | CfgOptions = std::make_unique<InputArgList>( | |||
823 | ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors)); | |||
824 | if (ContainErrors) { | |||
825 | CfgOptions.reset(); | |||
826 | return true; | |||
827 | } | |||
828 | ||||
829 | if (CfgOptions->hasArg(options::OPT_config)) { | |||
830 | CfgOptions.reset(); | |||
831 | Diag(diag::err_drv_nested_config_file); | |||
832 | return true; | |||
833 | } | |||
834 | ||||
835 | // Claim all arguments that come from a configuration file so that the driver | |||
836 | // does not warn on any that is unused. | |||
837 | for (Arg *A : *CfgOptions) | |||
838 | A->claim(); | |||
839 | return false; | |||
840 | } | |||
841 | ||||
842 | bool Driver::loadConfigFile() { | |||
843 | std::string CfgFileName; | |||
844 | bool FileSpecifiedExplicitly = false; | |||
845 | ||||
846 | // Process options that change search path for config files. | |||
847 | if (CLOptions) { | |||
848 | if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) { | |||
849 | SmallString<128> CfgDir; | |||
850 | CfgDir.append( | |||
851 | CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ)); | |||
852 | if (!CfgDir.empty()) { | |||
853 | if (llvm::sys::fs::make_absolute(CfgDir).value() != 0) | |||
854 | SystemConfigDir.clear(); | |||
855 | else | |||
856 | SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end()); | |||
857 | } | |||
858 | } | |||
859 | if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) { | |||
860 | SmallString<128> CfgDir; | |||
861 | CfgDir.append( | |||
862 | CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ)); | |||
863 | if (!CfgDir.empty()) { | |||
864 | if (llvm::sys::fs::make_absolute(CfgDir).value() != 0) | |||
865 | UserConfigDir.clear(); | |||
866 | else | |||
867 | UserConfigDir = std::string(CfgDir.begin(), CfgDir.end()); | |||
868 | } | |||
869 | } | |||
870 | } | |||
871 | ||||
872 | // First try to find config file specified in command line. | |||
873 | if (CLOptions) { | |||
874 | std::vector<std::string> ConfigFiles = | |||
875 | CLOptions->getAllArgValues(options::OPT_config); | |||
876 | if (ConfigFiles.size() > 1) { | |||
877 | if (!std::all_of(ConfigFiles.begin(), ConfigFiles.end(), | |||
878 | [ConfigFiles](const std::string &s) { | |||
879 | return s == ConfigFiles[0]; | |||
880 | })) { | |||
881 | Diag(diag::err_drv_duplicate_config); | |||
882 | return true; | |||
883 | } | |||
884 | } | |||
885 | ||||
886 | if (!ConfigFiles.empty()) { | |||
887 | CfgFileName = ConfigFiles.front(); | |||
888 | assert(!CfgFileName.empty())(static_cast <bool> (!CfgFileName.empty()) ? void (0) : __assert_fail ("!CfgFileName.empty()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 888, __extension__ __PRETTY_FUNCTION__)); | |||
889 | ||||
890 | // If argument contains directory separator, treat it as a path to | |||
891 | // configuration file. | |||
892 | if (llvm::sys::path::has_parent_path(CfgFileName)) { | |||
893 | SmallString<128> CfgFilePath; | |||
894 | if (llvm::sys::path::is_relative(CfgFileName)) | |||
895 | llvm::sys::fs::current_path(CfgFilePath); | |||
896 | llvm::sys::path::append(CfgFilePath, CfgFileName); | |||
897 | if (!llvm::sys::fs::is_regular_file(CfgFilePath)) { | |||
898 | Diag(diag::err_drv_config_file_not_exist) << CfgFilePath; | |||
899 | return true; | |||
900 | } | |||
901 | return readConfigFile(CfgFilePath); | |||
902 | } | |||
903 | ||||
904 | FileSpecifiedExplicitly = true; | |||
905 | } | |||
906 | } | |||
907 | ||||
908 | // If config file is not specified explicitly, try to deduce configuration | |||
909 | // from executable name. For instance, an executable 'armv7l-clang' will | |||
910 | // search for config file 'armv7l-clang.cfg'. | |||
911 | if (CfgFileName.empty() && !ClangNameParts.TargetPrefix.empty()) | |||
912 | CfgFileName = ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix; | |||
913 | ||||
914 | if (CfgFileName.empty()) | |||
915 | return false; | |||
916 | ||||
917 | // Determine architecture part of the file name, if it is present. | |||
918 | StringRef CfgFileArch = CfgFileName; | |||
919 | size_t ArchPrefixLen = CfgFileArch.find('-'); | |||
920 | if (ArchPrefixLen == StringRef::npos) | |||
921 | ArchPrefixLen = CfgFileArch.size(); | |||
922 | llvm::Triple CfgTriple; | |||
923 | CfgFileArch = CfgFileArch.take_front(ArchPrefixLen); | |||
924 | CfgTriple = llvm::Triple(llvm::Triple::normalize(CfgFileArch)); | |||
925 | if (CfgTriple.getArch() == llvm::Triple::ArchType::UnknownArch) | |||
926 | ArchPrefixLen = 0; | |||
927 | ||||
928 | if (!StringRef(CfgFileName).endswith(".cfg")) | |||
929 | CfgFileName += ".cfg"; | |||
930 | ||||
931 | // If config file starts with architecture name and command line options | |||
932 | // redefine architecture (with options like -m32 -LE etc), try finding new | |||
933 | // config file with that architecture. | |||
934 | SmallString<128> FixedConfigFile; | |||
935 | size_t FixedArchPrefixLen = 0; | |||
936 | if (ArchPrefixLen) { | |||
937 | // Get architecture name from config file name like 'i386.cfg' or | |||
938 | // 'armv7l-clang.cfg'. | |||
939 | // Check if command line options changes effective triple. | |||
940 | llvm::Triple EffectiveTriple = computeTargetTriple(*this, | |||
941 | CfgTriple.getTriple(), *CLOptions); | |||
942 | if (CfgTriple.getArch() != EffectiveTriple.getArch()) { | |||
943 | FixedConfigFile = EffectiveTriple.getArchName(); | |||
944 | FixedArchPrefixLen = FixedConfigFile.size(); | |||
945 | // Append the rest of original file name so that file name transforms | |||
946 | // like: i386-clang.cfg -> x86_64-clang.cfg. | |||
947 | if (ArchPrefixLen < CfgFileName.size()) | |||
948 | FixedConfigFile += CfgFileName.substr(ArchPrefixLen); | |||
949 | } | |||
950 | } | |||
951 | ||||
952 | // Prepare list of directories where config file is searched for. | |||
953 | StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir}; | |||
954 | ||||
955 | // Try to find config file. First try file with corrected architecture. | |||
956 | llvm::SmallString<128> CfgFilePath; | |||
957 | if (!FixedConfigFile.empty()) { | |||
958 | if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile)) | |||
959 | return readConfigFile(CfgFilePath); | |||
960 | // If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'. | |||
961 | FixedConfigFile.resize(FixedArchPrefixLen); | |||
962 | FixedConfigFile.append(".cfg"); | |||
963 | if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile)) | |||
964 | return readConfigFile(CfgFilePath); | |||
965 | } | |||
966 | ||||
967 | // Then try original file name. | |||
968 | if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName)) | |||
969 | return readConfigFile(CfgFilePath); | |||
970 | ||||
971 | // Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'. | |||
972 | if (!ClangNameParts.ModeSuffix.empty() && | |||
973 | !ClangNameParts.TargetPrefix.empty()) { | |||
974 | CfgFileName.assign(ClangNameParts.TargetPrefix); | |||
975 | CfgFileName.append(".cfg"); | |||
976 | if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName)) | |||
977 | return readConfigFile(CfgFilePath); | |||
978 | } | |||
979 | ||||
980 | // Report error but only if config file was specified explicitly, by option | |||
981 | // --config. If it was deduced from executable name, it is not an error. | |||
982 | if (FileSpecifiedExplicitly) { | |||
983 | Diag(diag::err_drv_config_file_not_found) << CfgFileName; | |||
984 | for (const StringRef &SearchDir : CfgFileSearchDirs) | |||
985 | if (!SearchDir.empty()) | |||
986 | Diag(diag::note_drv_config_file_searched_in) << SearchDir; | |||
987 | return true; | |||
988 | } | |||
989 | ||||
990 | return false; | |||
991 | } | |||
992 | ||||
993 | Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { | |||
994 | llvm::PrettyStackTraceString CrashInfo("Compilation construction"); | |||
995 | ||||
996 | // FIXME: Handle environment options which affect driver behavior, somewhere | |||
997 | // (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS. | |||
998 | ||||
999 | // We look for the driver mode option early, because the mode can affect | |||
1000 | // how other options are parsed. | |||
1001 | ParseDriverMode(ClangExecutable, ArgList.slice(1)); | |||
1002 | ||||
1003 | // FIXME: What are we going to do with -V and -b? | |||
1004 | ||||
1005 | // Arguments specified in command line. | |||
1006 | bool ContainsError; | |||
1007 | CLOptions = std::make_unique<InputArgList>( | |||
1008 | ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError)); | |||
1009 | ||||
1010 | // Try parsing configuration file. | |||
1011 | if (!ContainsError) | |||
1012 | ContainsError = loadConfigFile(); | |||
1013 | bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr); | |||
1014 | ||||
1015 | // All arguments, from both config file and command line. | |||
1016 | InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions) | |||
1017 | : std::move(*CLOptions)); | |||
1018 | ||||
1019 | // The args for config files or /clang: flags belong to different InputArgList | |||
1020 | // objects than Args. This copies an Arg from one of those other InputArgLists | |||
1021 | // to the ownership of Args. | |||
1022 | auto appendOneArg = [&Args](const Arg *Opt, const Arg *BaseArg) { | |||
1023 | unsigned Index = Args.MakeIndex(Opt->getSpelling()); | |||
1024 | Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Args.getArgString(Index), | |||
1025 | Index, BaseArg); | |||
1026 | Copy->getValues() = Opt->getValues(); | |||
1027 | if (Opt->isClaimed()) | |||
1028 | Copy->claim(); | |||
1029 | Copy->setOwnsValues(Opt->getOwnsValues()); | |||
1030 | Opt->setOwnsValues(false); | |||
1031 | Args.append(Copy); | |||
1032 | }; | |||
1033 | ||||
1034 | if (HasConfigFile) | |||
1035 | for (auto *Opt : *CLOptions) { | |||
1036 | if (Opt->getOption().matches(options::OPT_config)) | |||
1037 | continue; | |||
1038 | const Arg *BaseArg = &Opt->getBaseArg(); | |||
1039 | if (BaseArg == Opt) | |||
1040 | BaseArg = nullptr; | |||
1041 | appendOneArg(Opt, BaseArg); | |||
1042 | } | |||
1043 | ||||
1044 | // In CL mode, look for any pass-through arguments | |||
1045 | if (IsCLMode() && !ContainsError) { | |||
1046 | SmallVector<const char *, 16> CLModePassThroughArgList; | |||
1047 | for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) { | |||
1048 | A->claim(); | |||
1049 | CLModePassThroughArgList.push_back(A->getValue()); | |||
1050 | } | |||
1051 | ||||
1052 | if (!CLModePassThroughArgList.empty()) { | |||
1053 | // Parse any pass through args using default clang processing rather | |||
1054 | // than clang-cl processing. | |||
1055 | auto CLModePassThroughOptions = std::make_unique<InputArgList>( | |||
1056 | ParseArgStrings(CLModePassThroughArgList, false, ContainsError)); | |||
1057 | ||||
1058 | if (!ContainsError) | |||
1059 | for (auto *Opt : *CLModePassThroughOptions) { | |||
1060 | appendOneArg(Opt, nullptr); | |||
1061 | } | |||
1062 | } | |||
1063 | } | |||
1064 | ||||
1065 | // Check for working directory option before accessing any files | |||
1066 | if (Arg *WD = Args.getLastArg(options::OPT_working_directory)) | |||
1067 | if (VFS->setCurrentWorkingDirectory(WD->getValue())) | |||
1068 | Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue(); | |||
1069 | ||||
1070 | // FIXME: This stuff needs to go into the Compilation, not the driver. | |||
1071 | bool CCCPrintPhases; | |||
1072 | ||||
1073 | // Silence driver warnings if requested | |||
1074 | Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w)); | |||
1075 | ||||
1076 | // -no-canonical-prefixes is used very early in main. | |||
1077 | Args.ClaimAllArgs(options::OPT_no_canonical_prefixes); | |||
1078 | ||||
1079 | // f(no-)integated-cc1 is also used very early in main. | |||
1080 | Args.ClaimAllArgs(options::OPT_fintegrated_cc1); | |||
1081 | Args.ClaimAllArgs(options::OPT_fno_integrated_cc1); | |||
1082 | ||||
1083 | // Ignore -pipe. | |||
1084 | Args.ClaimAllArgs(options::OPT_pipe); | |||
1085 | ||||
1086 | // Extract -ccc args. | |||
1087 | // | |||
1088 | // FIXME: We need to figure out where this behavior should live. Most of it | |||
1089 | // should be outside in the client; the parts that aren't should have proper | |||
1090 | // options, either by introducing new ones or by overloading gcc ones like -V | |||
1091 | // or -b. | |||
1092 | CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases); | |||
1093 | CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings); | |||
1094 | if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name)) | |||
1095 | CCCGenericGCCName = A->getValue(); | |||
1096 | GenReproducer = Args.hasFlag(options::OPT_gen_reproducer, | |||
1097 | options::OPT_fno_crash_diagnostics, | |||
1098 | !!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")); | |||
1099 | ||||
1100 | // Process -fproc-stat-report options. | |||
1101 | if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) { | |||
1102 | CCPrintProcessStats = true; | |||
1103 | CCPrintStatReportFilename = A->getValue(); | |||
1104 | } | |||
1105 | if (Args.hasArg(options::OPT_fproc_stat_report)) | |||
1106 | CCPrintProcessStats = true; | |||
1107 | ||||
1108 | // FIXME: TargetTriple is used by the target-prefixed calls to as/ld | |||
1109 | // and getToolChain is const. | |||
1110 | if (IsCLMode()) { | |||
1111 | // clang-cl targets MSVC-style Win32. | |||
1112 | llvm::Triple T(TargetTriple); | |||
1113 | T.setOS(llvm::Triple::Win32); | |||
1114 | T.setVendor(llvm::Triple::PC); | |||
1115 | T.setEnvironment(llvm::Triple::MSVC); | |||
1116 | T.setObjectFormat(llvm::Triple::COFF); | |||
1117 | TargetTriple = T.str(); | |||
1118 | } | |||
1119 | if (const Arg *A = Args.getLastArg(options::OPT_target)) | |||
1120 | TargetTriple = A->getValue(); | |||
1121 | if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir)) | |||
1122 | Dir = InstalledDir = A->getValue(); | |||
1123 | for (const Arg *A : Args.filtered(options::OPT_B)) { | |||
1124 | A->claim(); | |||
1125 | PrefixDirs.push_back(A->getValue(0)); | |||
1126 | } | |||
1127 | if (Optional<std::string> CompilerPathValue = | |||
1128 | llvm::sys::Process::GetEnv("COMPILER_PATH")) { | |||
1129 | StringRef CompilerPath = *CompilerPathValue; | |||
1130 | while (!CompilerPath.empty()) { | |||
1131 | std::pair<StringRef, StringRef> Split = | |||
1132 | CompilerPath.split(llvm::sys::EnvPathSeparator); | |||
1133 | PrefixDirs.push_back(std::string(Split.first)); | |||
1134 | CompilerPath = Split.second; | |||
1135 | } | |||
1136 | } | |||
1137 | if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) | |||
1138 | SysRoot = A->getValue(); | |||
1139 | if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ)) | |||
1140 | DyldPrefix = A->getValue(); | |||
1141 | ||||
1142 | if (const Arg *A = Args.getLastArg(options::OPT_resource_dir)) | |||
1143 | ResourceDir = A->getValue(); | |||
1144 | ||||
1145 | if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) { | |||
1146 | SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue()) | |||
1147 | .Case("cwd", SaveTempsCwd) | |||
1148 | .Case("obj", SaveTempsObj) | |||
1149 | .Default(SaveTempsCwd); | |||
1150 | } | |||
1151 | ||||
1152 | setLTOMode(Args); | |||
1153 | ||||
1154 | // Process -fembed-bitcode= flags. | |||
1155 | if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) { | |||
1156 | StringRef Name = A->getValue(); | |||
1157 | unsigned Model = llvm::StringSwitch<unsigned>(Name) | |||
1158 | .Case("off", EmbedNone) | |||
1159 | .Case("all", EmbedBitcode) | |||
1160 | .Case("bitcode", EmbedBitcode) | |||
1161 | .Case("marker", EmbedMarker) | |||
1162 | .Default(~0U); | |||
1163 | if (Model == ~0U) { | |||
1164 | Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) | |||
1165 | << Name; | |||
1166 | } else | |||
1167 | BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model); | |||
1168 | } | |||
1169 | ||||
1170 | std::unique_ptr<llvm::opt::InputArgList> UArgs = | |||
1171 | std::make_unique<InputArgList>(std::move(Args)); | |||
1172 | ||||
1173 | // Perform the default argument translations. | |||
1174 | DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs); | |||
1175 | ||||
1176 | // Owned by the host. | |||
1177 | const ToolChain &TC = getToolChain( | |||
1178 | *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs)); | |||
1179 | ||||
1180 | // The compilation takes ownership of Args. | |||
1181 | Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs, | |||
1182 | ContainsError); | |||
1183 | ||||
1184 | if (!HandleImmediateArgs(*C)) | |||
1185 | return C; | |||
1186 | ||||
1187 | // Construct the list of inputs. | |||
1188 | InputList Inputs; | |||
1189 | BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); | |||
1190 | ||||
1191 | // Populate the tool chains for the offloading devices, if any. | |||
1192 | CreateOffloadingDeviceToolChains(*C, Inputs); | |||
1193 | ||||
1194 | // Construct the list of abstract actions to perform for this compilation. On | |||
1195 | // MachO targets this uses the driver-driver and universal actions. | |||
1196 | if (TC.getTriple().isOSBinFormatMachO()) | |||
1197 | BuildUniversalActions(*C, C->getDefaultToolChain(), Inputs); | |||
1198 | else | |||
1199 | BuildActions(*C, C->getArgs(), Inputs, C->getActions()); | |||
1200 | ||||
1201 | if (CCCPrintPhases) { | |||
1202 | PrintActions(*C); | |||
1203 | return C; | |||
1204 | } | |||
1205 | ||||
1206 | BuildJobs(*C); | |||
1207 | ||||
1208 | return C; | |||
1209 | } | |||
1210 | ||||
1211 | static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) { | |||
1212 | llvm::opt::ArgStringList ASL; | |||
1213 | for (const auto *A : Args) | |||
1214 | A->render(Args, ASL); | |||
1215 | ||||
1216 | for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) { | |||
1217 | if (I != ASL.begin()) | |||
1218 | OS << ' '; | |||
1219 | llvm::sys::printArg(OS, *I, true); | |||
1220 | } | |||
1221 | OS << '\n'; | |||
1222 | } | |||
1223 | ||||
1224 | bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename, | |||
1225 | SmallString<128> &CrashDiagDir) { | |||
1226 | using namespace llvm::sys; | |||
1227 | assert(llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() &&(static_cast <bool> (llvm::Triple(llvm::sys::getProcessTriple ()).isOSDarwin() && "Only knows about .crash files on Darwin" ) ? void (0) : __assert_fail ("llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() && \"Only knows about .crash files on Darwin\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 1228, __extension__ __PRETTY_FUNCTION__)) | |||
1228 | "Only knows about .crash files on Darwin")(static_cast <bool> (llvm::Triple(llvm::sys::getProcessTriple ()).isOSDarwin() && "Only knows about .crash files on Darwin" ) ? void (0) : __assert_fail ("llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() && \"Only knows about .crash files on Darwin\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 1228, __extension__ __PRETTY_FUNCTION__)); | |||
1229 | ||||
1230 | // The .crash file can be found on at ~/Library/Logs/DiagnosticReports/ | |||
1231 | // (or /Library/Logs/DiagnosticReports for root) and has the filename pattern | |||
1232 | // clang-<VERSION>_<YYYY-MM-DD-HHMMSS>_<hostname>.crash. | |||
1233 | path::home_directory(CrashDiagDir); | |||
1234 | if (CrashDiagDir.startswith("/var/root")) | |||
1235 | CrashDiagDir = "/"; | |||
1236 | path::append(CrashDiagDir, "Library/Logs/DiagnosticReports"); | |||
1237 | int PID = | |||
1238 | #if LLVM_ON_UNIX1 | |||
1239 | getpid(); | |||
1240 | #else | |||
1241 | 0; | |||
1242 | #endif | |||
1243 | std::error_code EC; | |||
1244 | fs::file_status FileStatus; | |||
1245 | TimePoint<> LastAccessTime; | |||
1246 | SmallString<128> CrashFilePath; | |||
1247 | // Lookup the .crash files and get the one generated by a subprocess spawned | |||
1248 | // by this driver invocation. | |||
1249 | for (fs::directory_iterator File(CrashDiagDir, EC), FileEnd; | |||
1250 | File != FileEnd && !EC; File.increment(EC)) { | |||
1251 | StringRef FileName = path::filename(File->path()); | |||
1252 | if (!FileName.startswith(Name)) | |||
1253 | continue; | |||
1254 | if (fs::status(File->path(), FileStatus)) | |||
1255 | continue; | |||
1256 | llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CrashFile = | |||
1257 | llvm::MemoryBuffer::getFile(File->path()); | |||
1258 | if (!CrashFile) | |||
1259 | continue; | |||
1260 | // The first line should start with "Process:", otherwise this isn't a real | |||
1261 | // .crash file. | |||
1262 | StringRef Data = CrashFile.get()->getBuffer(); | |||
1263 | if (!Data.startswith("Process:")) | |||
1264 | continue; | |||
1265 | // Parse parent process pid line, e.g: "Parent Process: clang-4.0 [79141]" | |||
1266 | size_t ParentProcPos = Data.find("Parent Process:"); | |||
1267 | if (ParentProcPos == StringRef::npos) | |||
1268 | continue; | |||
1269 | size_t LineEnd = Data.find_first_of("\n", ParentProcPos); | |||
1270 | if (LineEnd == StringRef::npos) | |||
1271 | continue; | |||
1272 | StringRef ParentProcess = Data.slice(ParentProcPos+15, LineEnd).trim(); | |||
1273 | int OpenBracket = -1, CloseBracket = -1; | |||
1274 | for (size_t i = 0, e = ParentProcess.size(); i < e; ++i) { | |||
1275 | if (ParentProcess[i] == '[') | |||
1276 | OpenBracket = i; | |||
1277 | if (ParentProcess[i] == ']') | |||
1278 | CloseBracket = i; | |||
1279 | } | |||
1280 | // Extract the parent process PID from the .crash file and check whether | |||
1281 | // it matches this driver invocation pid. | |||
1282 | int CrashPID; | |||
1283 | if (OpenBracket < 0 || CloseBracket < 0 || | |||
1284 | ParentProcess.slice(OpenBracket + 1, CloseBracket) | |||
1285 | .getAsInteger(10, CrashPID) || CrashPID != PID) { | |||
1286 | continue; | |||
1287 | } | |||
1288 | ||||
1289 | // Found a .crash file matching the driver pid. To avoid getting an older | |||
1290 | // and misleading crash file, continue looking for the most recent. | |||
1291 | // FIXME: the driver can dispatch multiple cc1 invocations, leading to | |||
1292 | // multiple crashes poiting to the same parent process. Since the driver | |||
1293 | // does not collect pid information for the dispatched invocation there's | |||
1294 | // currently no way to distinguish among them. | |||
1295 | const auto FileAccessTime = FileStatus.getLastModificationTime(); | |||
1296 | if (FileAccessTime > LastAccessTime) { | |||
1297 | CrashFilePath.assign(File->path()); | |||
1298 | LastAccessTime = FileAccessTime; | |||
1299 | } | |||
1300 | } | |||
1301 | ||||
1302 | // If found, copy it over to the location of other reproducer files. | |||
1303 | if (!CrashFilePath.empty()) { | |||
1304 | EC = fs::copy_file(CrashFilePath, ReproCrashFilename); | |||
1305 | if (EC) | |||
1306 | return false; | |||
1307 | return true; | |||
1308 | } | |||
1309 | ||||
1310 | return false; | |||
1311 | } | |||
1312 | ||||
1313 | // When clang crashes, produce diagnostic information including the fully | |||
1314 | // preprocessed source file(s). Request that the developer attach the | |||
1315 | // diagnostic information to a bug report. | |||
1316 | void Driver::generateCompilationDiagnostics( | |||
1317 | Compilation &C, const Command &FailingCommand, | |||
1318 | StringRef AdditionalInformation, CompilationDiagnosticReport *Report) { | |||
1319 | if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) | |||
1320 | return; | |||
1321 | ||||
1322 | // Don't try to generate diagnostics for link or dsymutil jobs. | |||
1323 | if (FailingCommand.getCreator().isLinkJob() || | |||
1324 | FailingCommand.getCreator().isDsymutilJob()) | |||
1325 | return; | |||
1326 | ||||
1327 | // Print the version of the compiler. | |||
1328 | PrintVersion(C, llvm::errs()); | |||
1329 | ||||
1330 | // Suppress driver output and emit preprocessor output to temp file. | |||
1331 | Mode = CPPMode; | |||
1332 | CCGenDiagnostics = true; | |||
1333 | ||||
1334 | // Save the original job command(s). | |||
1335 | Command Cmd = FailingCommand; | |||
1336 | ||||
1337 | // Keep track of whether we produce any errors while trying to produce | |||
1338 | // preprocessed sources. | |||
1339 | DiagnosticErrorTrap Trap(Diags); | |||
1340 | ||||
1341 | // Suppress tool output. | |||
1342 | C.initCompilationForDiagnostics(); | |||
1343 | ||||
1344 | // Construct the list of inputs. | |||
1345 | InputList Inputs; | |||
1346 | BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs); | |||
1347 | ||||
1348 | for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) { | |||
1349 | bool IgnoreInput = false; | |||
1350 | ||||
1351 | // Ignore input from stdin or any inputs that cannot be preprocessed. | |||
1352 | // Check type first as not all linker inputs have a value. | |||
1353 | if (types::getPreprocessedType(it->first) == types::TY_INVALID) { | |||
1354 | IgnoreInput = true; | |||
1355 | } else if (!strcmp(it->second->getValue(), "-")) { | |||
1356 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1357 | << "Error generating preprocessed source(s) - " | |||
1358 | "ignoring input from stdin."; | |||
1359 | IgnoreInput = true; | |||
1360 | } | |||
1361 | ||||
1362 | if (IgnoreInput) { | |||
1363 | it = Inputs.erase(it); | |||
1364 | ie = Inputs.end(); | |||
1365 | } else { | |||
1366 | ++it; | |||
1367 | } | |||
1368 | } | |||
1369 | ||||
1370 | if (Inputs.empty()) { | |||
1371 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1372 | << "Error generating preprocessed source(s) - " | |||
1373 | "no preprocessable inputs."; | |||
1374 | return; | |||
1375 | } | |||
1376 | ||||
1377 | // Don't attempt to generate preprocessed files if multiple -arch options are | |||
1378 | // used, unless they're all duplicates. | |||
1379 | llvm::StringSet<> ArchNames; | |||
1380 | for (const Arg *A : C.getArgs()) { | |||
1381 | if (A->getOption().matches(options::OPT_arch)) { | |||
1382 | StringRef ArchName = A->getValue(); | |||
1383 | ArchNames.insert(ArchName); | |||
1384 | } | |||
1385 | } | |||
1386 | if (ArchNames.size() > 1) { | |||
1387 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1388 | << "Error generating preprocessed source(s) - cannot generate " | |||
1389 | "preprocessed source with multiple -arch options."; | |||
1390 | return; | |||
1391 | } | |||
1392 | ||||
1393 | // Construct the list of abstract actions to perform for this compilation. On | |||
1394 | // Darwin OSes this uses the driver-driver and builds universal actions. | |||
1395 | const ToolChain &TC = C.getDefaultToolChain(); | |||
1396 | if (TC.getTriple().isOSBinFormatMachO()) | |||
1397 | BuildUniversalActions(C, TC, Inputs); | |||
1398 | else | |||
1399 | BuildActions(C, C.getArgs(), Inputs, C.getActions()); | |||
1400 | ||||
1401 | BuildJobs(C); | |||
1402 | ||||
1403 | // If there were errors building the compilation, quit now. | |||
1404 | if (Trap.hasErrorOccurred()) { | |||
1405 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1406 | << "Error generating preprocessed source(s)."; | |||
1407 | return; | |||
1408 | } | |||
1409 | ||||
1410 | // Generate preprocessed output. | |||
1411 | SmallVector<std::pair<int, const Command *>, 4> FailingCommands; | |||
1412 | C.ExecuteJobs(C.getJobs(), FailingCommands); | |||
1413 | ||||
1414 | // If any of the preprocessing commands failed, clean up and exit. | |||
1415 | if (!FailingCommands.empty()) { | |||
1416 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1417 | << "Error generating preprocessed source(s)."; | |||
1418 | return; | |||
1419 | } | |||
1420 | ||||
1421 | const ArgStringList &TempFiles = C.getTempFiles(); | |||
1422 | if (TempFiles.empty()) { | |||
1423 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1424 | << "Error generating preprocessed source(s)."; | |||
1425 | return; | |||
1426 | } | |||
1427 | ||||
1428 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1429 | << "\n********************\n\n" | |||
1430 | "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" | |||
1431 | "Preprocessed source(s) and associated run script(s) are located at:"; | |||
1432 | ||||
1433 | SmallString<128> VFS; | |||
1434 | SmallString<128> ReproCrashFilename; | |||
1435 | for (const char *TempFile : TempFiles) { | |||
1436 | Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile; | |||
1437 | if (Report) | |||
1438 | Report->TemporaryFiles.push_back(TempFile); | |||
1439 | if (ReproCrashFilename.empty()) { | |||
1440 | ReproCrashFilename = TempFile; | |||
1441 | llvm::sys::path::replace_extension(ReproCrashFilename, ".crash"); | |||
1442 | } | |||
1443 | if (StringRef(TempFile).endswith(".cache")) { | |||
1444 | // In some cases (modules) we'll dump extra data to help with reproducing | |||
1445 | // the crash into a directory next to the output. | |||
1446 | VFS = llvm::sys::path::filename(TempFile); | |||
1447 | llvm::sys::path::append(VFS, "vfs", "vfs.yaml"); | |||
1448 | } | |||
1449 | } | |||
1450 | ||||
1451 | // Assume associated files are based off of the first temporary file. | |||
1452 | CrashReportInfo CrashInfo(TempFiles[0], VFS); | |||
1453 | ||||
1454 | llvm::SmallString<128> Script(CrashInfo.Filename); | |||
1455 | llvm::sys::path::replace_extension(Script, "sh"); | |||
1456 | std::error_code EC; | |||
1457 | llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew, | |||
1458 | llvm::sys::fs::FA_Write, | |||
1459 | llvm::sys::fs::OF_Text); | |||
1460 | if (EC) { | |||
1461 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1462 | << "Error generating run script: " << Script << " " << EC.message(); | |||
1463 | } else { | |||
1464 | ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" | |||
1465 | << "# Driver args: "; | |||
1466 | printArgList(ScriptOS, C.getInputArgs()); | |||
1467 | ScriptOS << "# Original command: "; | |||
1468 | Cmd.Print(ScriptOS, "\n", /*Quote=*/true); | |||
1469 | Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); | |||
1470 | if (!AdditionalInformation.empty()) | |||
1471 | ScriptOS << "\n# Additional information: " << AdditionalInformation | |||
1472 | << "\n"; | |||
1473 | if (Report) | |||
1474 | Report->TemporaryFiles.push_back(std::string(Script.str())); | |||
1475 | Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; | |||
1476 | } | |||
1477 | ||||
1478 | // On darwin, provide information about the .crash diagnostic report. | |||
1479 | if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) { | |||
1480 | SmallString<128> CrashDiagDir; | |||
1481 | if (getCrashDiagnosticFile(ReproCrashFilename, CrashDiagDir)) { | |||
1482 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1483 | << ReproCrashFilename.str(); | |||
1484 | } else { // Suggest a directory for the user to look for .crash files. | |||
1485 | llvm::sys::path::append(CrashDiagDir, Name); | |||
1486 | CrashDiagDir += "_<YYYY-MM-DD-HHMMSS>_<hostname>.crash"; | |||
1487 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1488 | << "Crash backtrace is located in"; | |||
1489 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1490 | << CrashDiagDir.str(); | |||
1491 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1492 | << "(choose the .crash file that corresponds to your crash)"; | |||
1493 | } | |||
1494 | } | |||
1495 | ||||
1496 | for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file_EQ)) | |||
1497 | Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue(); | |||
1498 | ||||
1499 | Diag(clang::diag::note_drv_command_failed_diag_msg) | |||
1500 | << "\n\n********************"; | |||
1501 | } | |||
1502 | ||||
1503 | void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) { | |||
1504 | // Since commandLineFitsWithinSystemLimits() may underestimate system's | |||
1505 | // capacity if the tool does not support response files, there is a chance/ | |||
1506 | // that things will just work without a response file, so we silently just | |||
1507 | // skip it. | |||
1508 | if (Cmd.getResponseFileSupport().ResponseKind == | |||
1509 | ResponseFileSupport::RF_None || | |||
1510 | llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(), | |||
1511 | Cmd.getArguments())) | |||
1512 | return; | |||
1513 | ||||
1514 | std::string TmpName = GetTemporaryPath("response", "txt"); | |||
1515 | Cmd.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName))); | |||
1516 | } | |||
1517 | ||||
1518 | int Driver::ExecuteCompilation( | |||
1519 | Compilation &C, | |||
1520 | SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) { | |||
1521 | // Just print if -### was present. | |||
1522 | if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { | |||
1523 | C.getJobs().Print(llvm::errs(), "\n", true); | |||
1524 | return 0; | |||
1525 | } | |||
1526 | ||||
1527 | // If there were errors building the compilation, quit now. | |||
1528 | if (Diags.hasErrorOccurred()) | |||
1529 | return 1; | |||
1530 | ||||
1531 | // Set up response file names for each command, if necessary | |||
1532 | for (auto &Job : C.getJobs()) | |||
1533 | setUpResponseFiles(C, Job); | |||
1534 | ||||
1535 | C.ExecuteJobs(C.getJobs(), FailingCommands); | |||
1536 | ||||
1537 | // If the command succeeded, we are done. | |||
1538 | if (FailingCommands.empty()) | |||
1539 | return 0; | |||
1540 | ||||
1541 | // Otherwise, remove result files and print extra information about abnormal | |||
1542 | // failures. | |||
1543 | int Res = 0; | |||
1544 | for (const auto &CmdPair : FailingCommands) { | |||
1545 | int CommandRes = CmdPair.first; | |||
1546 | const Command *FailingCommand = CmdPair.second; | |||
1547 | ||||
1548 | // Remove result files if we're not saving temps. | |||
1549 | if (!isSaveTempsEnabled()) { | |||
1550 | const JobAction *JA = cast<JobAction>(&FailingCommand->getSource()); | |||
1551 | C.CleanupFileMap(C.getResultFiles(), JA, true); | |||
1552 | ||||
1553 | // Failure result files are valid unless we crashed. | |||
1554 | if (CommandRes < 0) | |||
1555 | C.CleanupFileMap(C.getFailureResultFiles(), JA, true); | |||
1556 | } | |||
1557 | ||||
1558 | #if LLVM_ON_UNIX1 | |||
1559 | // llvm/lib/Support/Unix/Signals.inc will exit with a special return code | |||
1560 | // for SIGPIPE. Do not print diagnostics for this case. | |||
1561 | if (CommandRes == EX_IOERR74) { | |||
1562 | Res = CommandRes; | |||
1563 | continue; | |||
1564 | } | |||
1565 | #endif | |||
1566 | ||||
1567 | // Print extra information about abnormal failures, if possible. | |||
1568 | // | |||
1569 | // This is ad-hoc, but we don't want to be excessively noisy. If the result | |||
1570 | // status was 1, assume the command failed normally. In particular, if it | |||
1571 | // was the compiler then assume it gave a reasonable error code. Failures | |||
1572 | // in other tools are less common, and they generally have worse | |||
1573 | // diagnostics, so always print the diagnostic there. | |||
1574 | const Tool &FailingTool = FailingCommand->getCreator(); | |||
1575 | ||||
1576 | if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) { | |||
1577 | // FIXME: See FIXME above regarding result code interpretation. | |||
1578 | if (CommandRes < 0) | |||
1579 | Diag(clang::diag::err_drv_command_signalled) | |||
1580 | << FailingTool.getShortName(); | |||
1581 | else | |||
1582 | Diag(clang::diag::err_drv_command_failed) | |||
1583 | << FailingTool.getShortName() << CommandRes; | |||
1584 | } | |||
1585 | } | |||
1586 | return Res; | |||
1587 | } | |||
1588 | ||||
1589 | void Driver::PrintHelp(bool ShowHidden) const { | |||
1590 | unsigned IncludedFlagsBitmask; | |||
1591 | unsigned ExcludedFlagsBitmask; | |||
1592 | std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = | |||
1593 | getIncludeExcludeOptionFlagMasks(IsCLMode()); | |||
1594 | ||||
1595 | ExcludedFlagsBitmask |= options::NoDriverOption; | |||
1596 | if (!ShowHidden) | |||
1597 | ExcludedFlagsBitmask |= HelpHidden; | |||
1598 | ||||
1599 | if (IsFlangMode()) | |||
1600 | IncludedFlagsBitmask |= options::FlangOption; | |||
1601 | else | |||
1602 | ExcludedFlagsBitmask |= options::FlangOnlyOption; | |||
1603 | ||||
1604 | std::string Usage = llvm::formatv("{0} [options] file...", Name).str(); | |||
1605 | getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(), | |||
1606 | IncludedFlagsBitmask, ExcludedFlagsBitmask, | |||
1607 | /*ShowAllAliases=*/false); | |||
1608 | } | |||
1609 | ||||
1610 | void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { | |||
1611 | if (IsFlangMode()) { | |||
1612 | OS << getClangToolFullVersion("flang-new") << '\n'; | |||
1613 | } else { | |||
1614 | // FIXME: The following handlers should use a callback mechanism, we don't | |||
1615 | // know what the client would like to do. | |||
1616 | OS << getClangFullVersion() << '\n'; | |||
1617 | } | |||
1618 | const ToolChain &TC = C.getDefaultToolChain(); | |||
1619 | OS << "Target: " << TC.getTripleString() << '\n'; | |||
1620 | ||||
1621 | // Print the threading model. | |||
1622 | if (Arg *A = C.getArgs().getLastArg(options::OPT_mthread_model)) { | |||
1623 | // Don't print if the ToolChain would have barfed on it already | |||
1624 | if (TC.isThreadModelSupported(A->getValue())) | |||
1625 | OS << "Thread model: " << A->getValue(); | |||
1626 | } else | |||
1627 | OS << "Thread model: " << TC.getThreadModel(); | |||
1628 | OS << '\n'; | |||
1629 | ||||
1630 | // Print out the install directory. | |||
1631 | OS << "InstalledDir: " << InstalledDir << '\n'; | |||
1632 | ||||
1633 | // If configuration file was used, print its path. | |||
1634 | if (!ConfigFile.empty()) | |||
1635 | OS << "Configuration file: " << ConfigFile << '\n'; | |||
1636 | } | |||
1637 | ||||
1638 | /// PrintDiagnosticCategories - Implement the --print-diagnostic-categories | |||
1639 | /// option. | |||
1640 | static void PrintDiagnosticCategories(raw_ostream &OS) { | |||
1641 | // Skip the empty category. | |||
1642 | for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max; | |||
1643 | ++i) | |||
1644 | OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n'; | |||
1645 | } | |||
1646 | ||||
1647 | void Driver::HandleAutocompletions(StringRef PassedFlags) const { | |||
1648 | if (PassedFlags == "") | |||
1649 | return; | |||
1650 | // Print out all options that start with a given argument. This is used for | |||
1651 | // shell autocompletion. | |||
1652 | std::vector<std::string> SuggestedCompletions; | |||
1653 | std::vector<std::string> Flags; | |||
1654 | ||||
1655 | unsigned int DisableFlags = | |||
1656 | options::NoDriverOption | options::Unsupported | options::Ignored; | |||
1657 | ||||
1658 | // Make sure that Flang-only options don't pollute the Clang output | |||
1659 | // TODO: Make sure that Clang-only options don't pollute Flang output | |||
1660 | if (!IsFlangMode()) | |||
1661 | DisableFlags |= options::FlangOnlyOption; | |||
1662 | ||||
1663 | // Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag," | |||
1664 | // because the latter indicates that the user put space before pushing tab | |||
1665 | // which should end up in a file completion. | |||
1666 | const bool HasSpace = PassedFlags.endswith(","); | |||
1667 | ||||
1668 | // Parse PassedFlags by "," as all the command-line flags are passed to this | |||
1669 | // function separated by "," | |||
1670 | StringRef TargetFlags = PassedFlags; | |||
1671 | while (TargetFlags != "") { | |||
1672 | StringRef CurFlag; | |||
1673 | std::tie(CurFlag, TargetFlags) = TargetFlags.split(","); | |||
1674 | Flags.push_back(std::string(CurFlag)); | |||
1675 | } | |||
1676 | ||||
1677 | // We want to show cc1-only options only when clang is invoked with -cc1 or | |||
1678 | // -Xclang. | |||
1679 | if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1")) | |||
1680 | DisableFlags &= ~options::NoDriverOption; | |||
1681 | ||||
1682 | const llvm::opt::OptTable &Opts = getOpts(); | |||
1683 | StringRef Cur; | |||
1684 | Cur = Flags.at(Flags.size() - 1); | |||
1685 | StringRef Prev; | |||
1686 | if (Flags.size() >= 2) { | |||
1687 | Prev = Flags.at(Flags.size() - 2); | |||
1688 | SuggestedCompletions = Opts.suggestValueCompletions(Prev, Cur); | |||
1689 | } | |||
1690 | ||||
1691 | if (SuggestedCompletions.empty()) | |||
1692 | SuggestedCompletions = Opts.suggestValueCompletions(Cur, ""); | |||
1693 | ||||
1694 | // If Flags were empty, it means the user typed `clang [tab]` where we should | |||
1695 | // list all possible flags. If there was no value completion and the user | |||
1696 | // pressed tab after a space, we should fall back to a file completion. | |||
1697 | // We're printing a newline to be consistent with what we print at the end of | |||
1698 | // this function. | |||
1699 | if (SuggestedCompletions.empty() && HasSpace && !Flags.empty()) { | |||
1700 | llvm::outs() << '\n'; | |||
1701 | return; | |||
1702 | } | |||
1703 | ||||
1704 | // When flag ends with '=' and there was no value completion, return empty | |||
1705 | // string and fall back to the file autocompletion. | |||
1706 | if (SuggestedCompletions.empty() && !Cur.endswith("=")) { | |||
1707 | // If the flag is in the form of "--autocomplete=-foo", | |||
1708 | // we were requested to print out all option names that start with "-foo". | |||
1709 | // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only". | |||
1710 | SuggestedCompletions = Opts.findByPrefix(Cur, DisableFlags); | |||
1711 | ||||
1712 | // We have to query the -W flags manually as they're not in the OptTable. | |||
1713 | // TODO: Find a good way to add them to OptTable instead and them remove | |||
1714 | // this code. | |||
1715 | for (StringRef S : DiagnosticIDs::getDiagnosticFlags()) | |||
1716 | if (S.startswith(Cur)) | |||
1717 | SuggestedCompletions.push_back(std::string(S)); | |||
1718 | } | |||
1719 | ||||
1720 | // Sort the autocomplete candidates so that shells print them out in a | |||
1721 | // deterministic order. We could sort in any way, but we chose | |||
1722 | // case-insensitive sorting for consistency with the -help option | |||
1723 | // which prints out options in the case-insensitive alphabetical order. | |||
1724 | llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) { | |||
1725 | if (int X = A.compare_lower(B)) | |||
1726 | return X < 0; | |||
1727 | return A.compare(B) > 0; | |||
1728 | }); | |||
1729 | ||||
1730 | llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n'; | |||
1731 | } | |||
1732 | ||||
1733 | bool Driver::HandleImmediateArgs(const Compilation &C) { | |||
1734 | // The order these options are handled in gcc is all over the place, but we | |||
1735 | // don't expect inconsistencies w.r.t. that to matter in practice. | |||
1736 | ||||
1737 | if (C.getArgs().hasArg(options::OPT_dumpmachine)) { | |||
1738 | llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n'; | |||
1739 | return false; | |||
1740 | } | |||
1741 | ||||
1742 | if (C.getArgs().hasArg(options::OPT_dumpversion)) { | |||
1743 | // Since -dumpversion is only implemented for pedantic GCC compatibility, we | |||
1744 | // return an answer which matches our definition of __VERSION__. | |||
1745 | llvm::outs() << CLANG_VERSION_STRING"13.0.0" << "\n"; | |||
1746 | return false; | |||
1747 | } | |||
1748 | ||||
1749 | if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) { | |||
1750 | PrintDiagnosticCategories(llvm::outs()); | |||
1751 | return false; | |||
1752 | } | |||
1753 | ||||
1754 | if (C.getArgs().hasArg(options::OPT_help) || | |||
1755 | C.getArgs().hasArg(options::OPT__help_hidden)) { | |||
1756 | PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden)); | |||
1757 | return false; | |||
1758 | } | |||
1759 | ||||
1760 | if (C.getArgs().hasArg(options::OPT__version)) { | |||
1761 | // Follow gcc behavior and use stdout for --version and stderr for -v. | |||
1762 | PrintVersion(C, llvm::outs()); | |||
1763 | return false; | |||
1764 | } | |||
1765 | ||||
1766 | if (C.getArgs().hasArg(options::OPT_v) || | |||
1767 | C.getArgs().hasArg(options::OPT__HASH_HASH_HASH) || | |||
1768 | C.getArgs().hasArg(options::OPT_print_supported_cpus)) { | |||
1769 | PrintVersion(C, llvm::errs()); | |||
1770 | SuppressMissingInputWarning = true; | |||
1771 | } | |||
1772 | ||||
1773 | if (C.getArgs().hasArg(options::OPT_v)) { | |||
1774 | if (!SystemConfigDir.empty()) | |||
1775 | llvm::errs() << "System configuration file directory: " | |||
1776 | << SystemConfigDir << "\n"; | |||
1777 | if (!UserConfigDir.empty()) | |||
1778 | llvm::errs() << "User configuration file directory: " | |||
1779 | << UserConfigDir << "\n"; | |||
1780 | } | |||
1781 | ||||
1782 | const ToolChain &TC = C.getDefaultToolChain(); | |||
1783 | ||||
1784 | if (C.getArgs().hasArg(options::OPT_v)) | |||
1785 | TC.printVerboseInfo(llvm::errs()); | |||
1786 | ||||
1787 | if (C.getArgs().hasArg(options::OPT_print_resource_dir)) { | |||
1788 | llvm::outs() << ResourceDir << '\n'; | |||
1789 | return false; | |||
1790 | } | |||
1791 | ||||
1792 | if (C.getArgs().hasArg(options::OPT_print_search_dirs)) { | |||
1793 | llvm::outs() << "programs: ="; | |||
1794 | bool separator = false; | |||
1795 | // Print -B and COMPILER_PATH. | |||
1796 | for (const std::string &Path : PrefixDirs) { | |||
1797 | if (separator) | |||
1798 | llvm::outs() << llvm::sys::EnvPathSeparator; | |||
1799 | llvm::outs() << Path; | |||
1800 | separator = true; | |||
1801 | } | |||
1802 | for (const std::string &Path : TC.getProgramPaths()) { | |||
1803 | if (separator) | |||
1804 | llvm::outs() << llvm::sys::EnvPathSeparator; | |||
1805 | llvm::outs() << Path; | |||
1806 | separator = true; | |||
1807 | } | |||
1808 | llvm::outs() << "\n"; | |||
1809 | llvm::outs() << "libraries: =" << ResourceDir; | |||
1810 | ||||
1811 | StringRef sysroot = C.getSysRoot(); | |||
1812 | ||||
1813 | for (const std::string &Path : TC.getFilePaths()) { | |||
1814 | // Always print a separator. ResourceDir was the first item shown. | |||
1815 | llvm::outs() << llvm::sys::EnvPathSeparator; | |||
1816 | // Interpretation of leading '=' is needed only for NetBSD. | |||
1817 | if (Path[0] == '=') | |||
1818 | llvm::outs() << sysroot << Path.substr(1); | |||
1819 | else | |||
1820 | llvm::outs() << Path; | |||
1821 | } | |||
1822 | llvm::outs() << "\n"; | |||
1823 | return false; | |||
1824 | } | |||
1825 | ||||
1826 | if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) { | |||
1827 | std::string CandidateRuntimePath = TC.getRuntimePath(); | |||
1828 | if (getVFS().exists(CandidateRuntimePath)) | |||
1829 | llvm::outs() << CandidateRuntimePath << '\n'; | |||
1830 | else | |||
1831 | llvm::outs() << TC.getCompilerRTPath() << '\n'; | |||
1832 | return false; | |||
1833 | } | |||
1834 | ||||
1835 | // FIXME: The following handlers should use a callback mechanism, we don't | |||
1836 | // know what the client would like to do. | |||
1837 | if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) { | |||
1838 | llvm::outs() << GetFilePath(A->getValue(), TC) << "\n"; | |||
1839 | return false; | |||
1840 | } | |||
1841 | ||||
1842 | if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) { | |||
1843 | StringRef ProgName = A->getValue(); | |||
1844 | ||||
1845 | // Null program name cannot have a path. | |||
1846 | if (! ProgName.empty()) | |||
1847 | llvm::outs() << GetProgramPath(ProgName, TC); | |||
1848 | ||||
1849 | llvm::outs() << "\n"; | |||
1850 | return false; | |||
1851 | } | |||
1852 | ||||
1853 | if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) { | |||
1854 | StringRef PassedFlags = A->getValue(); | |||
1855 | HandleAutocompletions(PassedFlags); | |||
1856 | return false; | |||
1857 | } | |||
1858 | ||||
1859 | if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) { | |||
1860 | ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs()); | |||
1861 | const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs())); | |||
1862 | RegisterEffectiveTriple TripleRAII(TC, Triple); | |||
1863 | switch (RLT) { | |||
1864 | case ToolChain::RLT_CompilerRT: | |||
1865 | llvm::outs() << TC.getCompilerRT(C.getArgs(), "builtins") << "\n"; | |||
1866 | break; | |||
1867 | case ToolChain::RLT_Libgcc: | |||
1868 | llvm::outs() << GetFilePath("libgcc.a", TC) << "\n"; | |||
1869 | break; | |||
1870 | } | |||
1871 | return false; | |||
1872 | } | |||
1873 | ||||
1874 | if (C.getArgs().hasArg(options::OPT_print_multi_lib)) { | |||
1875 | for (const Multilib &Multilib : TC.getMultilibs()) | |||
1876 | llvm::outs() << Multilib << "\n"; | |||
1877 | return false; | |||
1878 | } | |||
1879 | ||||
1880 | if (C.getArgs().hasArg(options::OPT_print_multi_directory)) { | |||
1881 | const Multilib &Multilib = TC.getMultilib(); | |||
1882 | if (Multilib.gccSuffix().empty()) | |||
1883 | llvm::outs() << ".\n"; | |||
1884 | else { | |||
1885 | StringRef Suffix(Multilib.gccSuffix()); | |||
1886 | assert(Suffix.front() == '/')(static_cast <bool> (Suffix.front() == '/') ? void (0) : __assert_fail ("Suffix.front() == '/'", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 1886, __extension__ __PRETTY_FUNCTION__)); | |||
1887 | llvm::outs() << Suffix.substr(1) << "\n"; | |||
1888 | } | |||
1889 | return false; | |||
1890 | } | |||
1891 | ||||
1892 | if (C.getArgs().hasArg(options::OPT_print_target_triple)) { | |||
1893 | llvm::outs() << TC.getTripleString() << "\n"; | |||
1894 | return false; | |||
1895 | } | |||
1896 | ||||
1897 | if (C.getArgs().hasArg(options::OPT_print_effective_triple)) { | |||
1898 | const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs())); | |||
1899 | llvm::outs() << Triple.getTriple() << "\n"; | |||
1900 | return false; | |||
1901 | } | |||
1902 | ||||
1903 | if (C.getArgs().hasArg(options::OPT_print_multiarch)) { | |||
1904 | llvm::outs() << TC.getMultiarchTriple(*this, TC.getTriple(), SysRoot) | |||
1905 | << "\n"; | |||
1906 | return false; | |||
1907 | } | |||
1908 | ||||
1909 | if (C.getArgs().hasArg(options::OPT_print_targets)) { | |||
1910 | llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs()); | |||
1911 | return false; | |||
1912 | } | |||
1913 | ||||
1914 | return true; | |||
1915 | } | |||
1916 | ||||
1917 | enum { | |||
1918 | TopLevelAction = 0, | |||
1919 | HeadSibAction = 1, | |||
1920 | OtherSibAction = 2, | |||
1921 | }; | |||
1922 | ||||
1923 | // Display an action graph human-readably. Action A is the "sink" node | |||
1924 | // and latest-occuring action. Traversal is in pre-order, visiting the | |||
1925 | // inputs to each action before printing the action itself. | |||
1926 | static unsigned PrintActions1(const Compilation &C, Action *A, | |||
1927 | std::map<Action *, unsigned> &Ids, | |||
1928 | Twine Indent = {}, int Kind = TopLevelAction) { | |||
1929 | if (Ids.count(A)) // A was already visited. | |||
1930 | return Ids[A]; | |||
1931 | ||||
1932 | std::string str; | |||
1933 | llvm::raw_string_ostream os(str); | |||
1934 | ||||
1935 | auto getSibIndent = [](int K) -> Twine { | |||
1936 | return (K == HeadSibAction) ? " " : (K == OtherSibAction) ? "| " : ""; | |||
1937 | }; | |||
1938 | ||||
1939 | Twine SibIndent = Indent + getSibIndent(Kind); | |||
1940 | int SibKind = HeadSibAction; | |||
1941 | os << Action::getClassName(A->getKind()) << ", "; | |||
1942 | if (InputAction *IA = dyn_cast<InputAction>(A)) { | |||
1943 | os << "\"" << IA->getInputArg().getValue() << "\""; | |||
1944 | } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { | |||
1945 | os << '"' << BIA->getArchName() << '"' << ", {" | |||
1946 | << PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}"; | |||
1947 | } else if (OffloadAction *OA = dyn_cast<OffloadAction>(A)) { | |||
1948 | bool IsFirst = true; | |||
1949 | OA->doOnEachDependence( | |||
1950 | [&](Action *A, const ToolChain *TC, const char *BoundArch) { | |||
1951 | assert(TC && "Unknown host toolchain")(static_cast <bool> (TC && "Unknown host toolchain" ) ? void (0) : __assert_fail ("TC && \"Unknown host toolchain\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 1951, __extension__ __PRETTY_FUNCTION__)); | |||
1952 | // E.g. for two CUDA device dependences whose bound arch is sm_20 and | |||
1953 | // sm_35 this will generate: | |||
1954 | // "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device" | |||
1955 | // (nvptx64-nvidia-cuda:sm_35) {#ID} | |||
1956 | if (!IsFirst) | |||
1957 | os << ", "; | |||
1958 | os << '"'; | |||
1959 | os << A->getOffloadingKindPrefix(); | |||
1960 | os << " ("; | |||
1961 | os << TC->getTriple().normalize(); | |||
1962 | if (BoundArch) | |||
1963 | os << ":" << BoundArch; | |||
1964 | os << ")"; | |||
1965 | os << '"'; | |||
1966 | os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}"; | |||
1967 | IsFirst = false; | |||
1968 | SibKind = OtherSibAction; | |||
1969 | }); | |||
1970 | } else { | |||
1971 | const ActionList *AL = &A->getInputs(); | |||
1972 | ||||
1973 | if (AL->size()) { | |||
1974 | const char *Prefix = "{"; | |||
1975 | for (Action *PreRequisite : *AL) { | |||
1976 | os << Prefix << PrintActions1(C, PreRequisite, Ids, SibIndent, SibKind); | |||
1977 | Prefix = ", "; | |||
1978 | SibKind = OtherSibAction; | |||
1979 | } | |||
1980 | os << "}"; | |||
1981 | } else | |||
1982 | os << "{}"; | |||
1983 | } | |||
1984 | ||||
1985 | // Append offload info for all options other than the offloading action | |||
1986 | // itself (e.g. (cuda-device, sm_20) or (cuda-host)). | |||
1987 | std::string offload_str; | |||
1988 | llvm::raw_string_ostream offload_os(offload_str); | |||
1989 | if (!isa<OffloadAction>(A)) { | |||
1990 | auto S = A->getOffloadingKindPrefix(); | |||
1991 | if (!S.empty()) { | |||
1992 | offload_os << ", (" << S; | |||
1993 | if (A->getOffloadingArch()) | |||
1994 | offload_os << ", " << A->getOffloadingArch(); | |||
1995 | offload_os << ")"; | |||
1996 | } | |||
1997 | } | |||
1998 | ||||
1999 | auto getSelfIndent = [](int K) -> Twine { | |||
2000 | return (K == HeadSibAction) ? "+- " : (K == OtherSibAction) ? "|- " : ""; | |||
2001 | }; | |||
2002 | ||||
2003 | unsigned Id = Ids.size(); | |||
2004 | Ids[A] = Id; | |||
2005 | llvm::errs() << Indent + getSelfIndent(Kind) << Id << ": " << os.str() << ", " | |||
2006 | << types::getTypeName(A->getType()) << offload_os.str() << "\n"; | |||
2007 | ||||
2008 | return Id; | |||
2009 | } | |||
2010 | ||||
2011 | // Print the action graphs in a compilation C. | |||
2012 | // For example "clang -c file1.c file2.c" is composed of two subgraphs. | |||
2013 | void Driver::PrintActions(const Compilation &C) const { | |||
2014 | std::map<Action *, unsigned> Ids; | |||
2015 | for (Action *A : C.getActions()) | |||
2016 | PrintActions1(C, A, Ids); | |||
2017 | } | |||
2018 | ||||
2019 | /// Check whether the given input tree contains any compilation or | |||
2020 | /// assembly actions. | |||
2021 | static bool ContainsCompileOrAssembleAction(const Action *A) { | |||
2022 | if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) || | |||
2023 | isa<AssembleJobAction>(A)) | |||
2024 | return true; | |||
2025 | ||||
2026 | for (const Action *Input : A->inputs()) | |||
2027 | if (ContainsCompileOrAssembleAction(Input)) | |||
2028 | return true; | |||
2029 | ||||
2030 | return false; | |||
2031 | } | |||
2032 | ||||
2033 | void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, | |||
2034 | const InputList &BAInputs) const { | |||
2035 | DerivedArgList &Args = C.getArgs(); | |||
2036 | ActionList &Actions = C.getActions(); | |||
2037 | llvm::PrettyStackTraceString CrashInfo("Building universal build actions"); | |||
2038 | // Collect the list of architectures. Duplicates are allowed, but should only | |||
2039 | // be handled once (in the order seen). | |||
2040 | llvm::StringSet<> ArchNames; | |||
2041 | SmallVector<const char *, 4> Archs; | |||
2042 | for (Arg *A : Args) { | |||
2043 | if (A->getOption().matches(options::OPT_arch)) { | |||
2044 | // Validate the option here; we don't save the type here because its | |||
2045 | // particular spelling may participate in other driver choices. | |||
2046 | llvm::Triple::ArchType Arch = | |||
2047 | tools::darwin::getArchTypeForMachOArchName(A->getValue()); | |||
2048 | if (Arch == llvm::Triple::UnknownArch) { | |||
2049 | Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); | |||
2050 | continue; | |||
2051 | } | |||
2052 | ||||
2053 | A->claim(); | |||
2054 | if (ArchNames.insert(A->getValue()).second) | |||
2055 | Archs.push_back(A->getValue()); | |||
2056 | } | |||
2057 | } | |||
2058 | ||||
2059 | // When there is no explicit arch for this platform, make sure we still bind | |||
2060 | // the architecture (to the default) so that -Xarch_ is handled correctly. | |||
2061 | if (!Archs.size()) | |||
2062 | Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName())); | |||
2063 | ||||
2064 | ActionList SingleActions; | |||
2065 | BuildActions(C, Args, BAInputs, SingleActions); | |||
2066 | ||||
2067 | // Add in arch bindings for every top level action, as well as lipo and | |||
2068 | // dsymutil steps if needed. | |||
2069 | for (Action* Act : SingleActions) { | |||
2070 | // Make sure we can lipo this kind of output. If not (and it is an actual | |||
2071 | // output) then we disallow, since we can't create an output file with the | |||
2072 | // right name without overwriting it. We could remove this oddity by just | |||
2073 | // changing the output names to include the arch, which would also fix | |||
2074 | // -save-temps. Compatibility wins for now. | |||
2075 | ||||
2076 | if (Archs.size() > 1 && !types::canLipoType(Act->getType())) | |||
2077 | Diag(clang::diag::err_drv_invalid_output_with_multiple_archs) | |||
2078 | << types::getTypeName(Act->getType()); | |||
2079 | ||||
2080 | ActionList Inputs; | |||
2081 | for (unsigned i = 0, e = Archs.size(); i != e; ++i) | |||
2082 | Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i])); | |||
2083 | ||||
2084 | // Lipo if necessary, we do it this way because we need to set the arch flag | |||
2085 | // so that -Xarch_ gets overwritten. | |||
2086 | if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) | |||
2087 | Actions.append(Inputs.begin(), Inputs.end()); | |||
2088 | else | |||
2089 | Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType())); | |||
2090 | ||||
2091 | // Handle debug info queries. | |||
2092 | Arg *A = Args.getLastArg(options::OPT_g_Group); | |||
2093 | bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) && | |||
2094 | !A->getOption().matches(options::OPT_gstabs); | |||
2095 | if ((enablesDebugInfo || willEmitRemarks(Args)) && | |||
2096 | ContainsCompileOrAssembleAction(Actions.back())) { | |||
2097 | ||||
2098 | // Add a 'dsymutil' step if necessary, when debug info is enabled and we | |||
2099 | // have a compile input. We need to run 'dsymutil' ourselves in such cases | |||
2100 | // because the debug info will refer to a temporary object file which | |||
2101 | // will be removed at the end of the compilation process. | |||
2102 | if (Act->getType() == types::TY_Image) { | |||
2103 | ActionList Inputs; | |||
2104 | Inputs.push_back(Actions.back()); | |||
2105 | Actions.pop_back(); | |||
2106 | Actions.push_back( | |||
2107 | C.MakeAction<DsymutilJobAction>(Inputs, types::TY_dSYM)); | |||
2108 | } | |||
2109 | ||||
2110 | // Verify the debug info output. | |||
2111 | if (Args.hasArg(options::OPT_verify_debug_info)) { | |||
2112 | Action* LastAction = Actions.back(); | |||
2113 | Actions.pop_back(); | |||
2114 | Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>( | |||
2115 | LastAction, types::TY_Nothing)); | |||
2116 | } | |||
2117 | } | |||
2118 | } | |||
2119 | } | |||
2120 | ||||
2121 | bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, | |||
2122 | types::ID Ty, bool TypoCorrect) const { | |||
2123 | if (!getCheckInputsExist()) | |||
2124 | return true; | |||
2125 | ||||
2126 | // stdin always exists. | |||
2127 | if (Value == "-") | |||
2128 | return true; | |||
2129 | ||||
2130 | if (getVFS().exists(Value)) | |||
2131 | return true; | |||
2132 | ||||
2133 | if (IsCLMode()) { | |||
2134 | if (!llvm::sys::path::is_absolute(Twine(Value)) && | |||
2135 | llvm::sys::Process::FindInEnvPath("LIB", Value, ';')) | |||
2136 | return true; | |||
2137 | ||||
2138 | if (Args.hasArg(options::OPT__SLASH_link) && Ty == types::TY_Object) { | |||
2139 | // Arguments to the /link flag might cause the linker to search for object | |||
2140 | // and library files in paths we don't know about. Don't error in such | |||
2141 | // cases. | |||
2142 | return true; | |||
2143 | } | |||
2144 | } | |||
2145 | ||||
2146 | if (TypoCorrect) { | |||
2147 | // Check if the filename is a typo for an option flag. OptTable thinks | |||
2148 | // that all args that are not known options and that start with / are | |||
2149 | // filenames, but e.g. `/diagnostic:caret` is more likely a typo for | |||
2150 | // the option `/diagnostics:caret` than a reference to a file in the root | |||
2151 | // directory. | |||
2152 | unsigned IncludedFlagsBitmask; | |||
2153 | unsigned ExcludedFlagsBitmask; | |||
2154 | std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = | |||
2155 | getIncludeExcludeOptionFlagMasks(IsCLMode()); | |||
2156 | std::string Nearest; | |||
2157 | if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask, | |||
2158 | ExcludedFlagsBitmask) <= 1) { | |||
2159 | Diag(clang::diag::err_drv_no_such_file_with_suggestion) | |||
2160 | << Value << Nearest; | |||
2161 | return false; | |||
2162 | } | |||
2163 | } | |||
2164 | ||||
2165 | Diag(clang::diag::err_drv_no_such_file) << Value; | |||
2166 | return false; | |||
2167 | } | |||
2168 | ||||
2169 | // Construct a the list of inputs and their types. | |||
2170 | void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, | |||
2171 | InputList &Inputs) const { | |||
2172 | const llvm::opt::OptTable &Opts = getOpts(); | |||
2173 | // Track the current user specified (-x) input. We also explicitly track the | |||
2174 | // argument used to set the type; we only want to claim the type when we | |||
2175 | // actually use it, so we warn about unused -x arguments. | |||
2176 | types::ID InputType = types::TY_Nothing; | |||
2177 | Arg *InputTypeArg = nullptr; | |||
2178 | ||||
2179 | // The last /TC or /TP option sets the input type to C or C++ globally. | |||
2180 | if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC, | |||
2181 | options::OPT__SLASH_TP)) { | |||
2182 | InputTypeArg = TCTP; | |||
2183 | InputType = TCTP->getOption().matches(options::OPT__SLASH_TC) | |||
2184 | ? types::TY_C | |||
2185 | : types::TY_CXX; | |||
2186 | ||||
2187 | Arg *Previous = nullptr; | |||
2188 | bool ShowNote = false; | |||
2189 | for (Arg *A : | |||
2190 | Args.filtered(options::OPT__SLASH_TC, options::OPT__SLASH_TP)) { | |||
2191 | if (Previous) { | |||
2192 | Diag(clang::diag::warn_drv_overriding_flag_option) | |||
2193 | << Previous->getSpelling() << A->getSpelling(); | |||
2194 | ShowNote = true; | |||
2195 | } | |||
2196 | Previous = A; | |||
2197 | } | |||
2198 | if (ShowNote) | |||
2199 | Diag(clang::diag::note_drv_t_option_is_global); | |||
2200 | ||||
2201 | // No driver mode exposes -x and /TC or /TP; we don't support mixing them. | |||
2202 | assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed")(static_cast <bool> (!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed") ? void (0) : __assert_fail ("!Args.hasArg(options::OPT_x) && \"-x and /TC or /TP is not allowed\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2202, __extension__ __PRETTY_FUNCTION__)); | |||
2203 | } | |||
2204 | ||||
2205 | for (Arg *A : Args) { | |||
2206 | if (A->getOption().getKind() == Option::InputClass) { | |||
2207 | const char *Value = A->getValue(); | |||
2208 | types::ID Ty = types::TY_INVALID; | |||
2209 | ||||
2210 | // Infer the input type if necessary. | |||
2211 | if (InputType == types::TY_Nothing) { | |||
2212 | // If there was an explicit arg for this, claim it. | |||
2213 | if (InputTypeArg) | |||
2214 | InputTypeArg->claim(); | |||
2215 | ||||
2216 | // stdin must be handled specially. | |||
2217 | if (memcmp(Value, "-", 2) == 0) { | |||
2218 | if (IsFlangMode()) { | |||
2219 | Ty = types::TY_Fortran; | |||
2220 | } else { | |||
2221 | // If running with -E, treat as a C input (this changes the | |||
2222 | // builtin macros, for example). This may be overridden by -ObjC | |||
2223 | // below. | |||
2224 | // | |||
2225 | // Otherwise emit an error but still use a valid type to avoid | |||
2226 | // spurious errors (e.g., no inputs). | |||
2227 | if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP()) | |||
2228 | Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl | |||
2229 | : clang::diag::err_drv_unknown_stdin_type); | |||
2230 | Ty = types::TY_C; | |||
2231 | } | |||
2232 | } else { | |||
2233 | // Otherwise lookup by extension. | |||
2234 | // Fallback is C if invoked as C preprocessor, C++ if invoked with | |||
2235 | // clang-cl /E, or Object otherwise. | |||
2236 | // We use a host hook here because Darwin at least has its own | |||
2237 | // idea of what .s is. | |||
2238 | if (const char *Ext = strrchr(Value, '.')) | |||
2239 | Ty = TC.LookupTypeForExtension(Ext + 1); | |||
2240 | ||||
2241 | if (Ty == types::TY_INVALID) { | |||
2242 | if (CCCIsCPP()) | |||
2243 | Ty = types::TY_C; | |||
2244 | else if (IsCLMode() && Args.hasArgNoClaim(options::OPT_E)) | |||
2245 | Ty = types::TY_CXX; | |||
2246 | else | |||
2247 | Ty = types::TY_Object; | |||
2248 | } | |||
2249 | ||||
2250 | // If the driver is invoked as C++ compiler (like clang++ or c++) it | |||
2251 | // should autodetect some input files as C++ for g++ compatibility. | |||
2252 | if (CCCIsCXX()) { | |||
2253 | types::ID OldTy = Ty; | |||
2254 | Ty = types::lookupCXXTypeForCType(Ty); | |||
2255 | ||||
2256 | if (Ty != OldTy) | |||
2257 | Diag(clang::diag::warn_drv_treating_input_as_cxx) | |||
2258 | << getTypeName(OldTy) << getTypeName(Ty); | |||
2259 | } | |||
2260 | ||||
2261 | // If running with -fthinlto-index=, extensions that normally identify | |||
2262 | // native object files actually identify LLVM bitcode files. | |||
2263 | if (Args.hasArgNoClaim(options::OPT_fthinlto_index_EQ) && | |||
2264 | Ty == types::TY_Object) | |||
2265 | Ty = types::TY_LLVM_BC; | |||
2266 | } | |||
2267 | ||||
2268 | // -ObjC and -ObjC++ override the default language, but only for "source | |||
2269 | // files". We just treat everything that isn't a linker input as a | |||
2270 | // source file. | |||
2271 | // | |||
2272 | // FIXME: Clean this up if we move the phase sequence into the type. | |||
2273 | if (Ty != types::TY_Object) { | |||
2274 | if (Args.hasArg(options::OPT_ObjC)) | |||
2275 | Ty = types::TY_ObjC; | |||
2276 | else if (Args.hasArg(options::OPT_ObjCXX)) | |||
2277 | Ty = types::TY_ObjCXX; | |||
2278 | } | |||
2279 | } else { | |||
2280 | assert(InputTypeArg && "InputType set w/o InputTypeArg")(static_cast <bool> (InputTypeArg && "InputType set w/o InputTypeArg" ) ? void (0) : __assert_fail ("InputTypeArg && \"InputType set w/o InputTypeArg\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2280, __extension__ __PRETTY_FUNCTION__)); | |||
2281 | if (!InputTypeArg->getOption().matches(options::OPT_x)) { | |||
2282 | // If emulating cl.exe, make sure that /TC and /TP don't affect input | |||
2283 | // object files. | |||
2284 | const char *Ext = strrchr(Value, '.'); | |||
2285 | if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object) | |||
2286 | Ty = types::TY_Object; | |||
2287 | } | |||
2288 | if (Ty == types::TY_INVALID) { | |||
2289 | Ty = InputType; | |||
2290 | InputTypeArg->claim(); | |||
2291 | } | |||
2292 | } | |||
2293 | ||||
2294 | if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true)) | |||
2295 | Inputs.push_back(std::make_pair(Ty, A)); | |||
2296 | ||||
2297 | } else if (A->getOption().matches(options::OPT__SLASH_Tc)) { | |||
2298 | StringRef Value = A->getValue(); | |||
2299 | if (DiagnoseInputExistence(Args, Value, types::TY_C, | |||
2300 | /*TypoCorrect=*/false)) { | |||
2301 | Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); | |||
2302 | Inputs.push_back(std::make_pair(types::TY_C, InputArg)); | |||
2303 | } | |||
2304 | A->claim(); | |||
2305 | } else if (A->getOption().matches(options::OPT__SLASH_Tp)) { | |||
2306 | StringRef Value = A->getValue(); | |||
2307 | if (DiagnoseInputExistence(Args, Value, types::TY_CXX, | |||
2308 | /*TypoCorrect=*/false)) { | |||
2309 | Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); | |||
2310 | Inputs.push_back(std::make_pair(types::TY_CXX, InputArg)); | |||
2311 | } | |||
2312 | A->claim(); | |||
2313 | } else if (A->getOption().hasFlag(options::LinkerInput)) { | |||
2314 | // Just treat as object type, we could make a special type for this if | |||
2315 | // necessary. | |||
2316 | Inputs.push_back(std::make_pair(types::TY_Object, A)); | |||
2317 | ||||
2318 | } else if (A->getOption().matches(options::OPT_x)) { | |||
2319 | InputTypeArg = A; | |||
2320 | InputType = types::lookupTypeForTypeSpecifier(A->getValue()); | |||
2321 | A->claim(); | |||
2322 | ||||
2323 | // Follow gcc behavior and treat as linker input for invalid -x | |||
2324 | // options. Its not clear why we shouldn't just revert to unknown; but | |||
2325 | // this isn't very important, we might as well be bug compatible. | |||
2326 | if (!InputType) { | |||
2327 | Diag(clang::diag::err_drv_unknown_language) << A->getValue(); | |||
2328 | InputType = types::TY_Object; | |||
2329 | } | |||
2330 | } else if (A->getOption().getID() == options::OPT_U) { | |||
2331 | assert(A->getNumValues() == 1 && "The /U option has one value.")(static_cast <bool> (A->getNumValues() == 1 && "The /U option has one value.") ? void (0) : __assert_fail ( "A->getNumValues() == 1 && \"The /U option has one value.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2331, __extension__ __PRETTY_FUNCTION__)); | |||
2332 | StringRef Val = A->getValue(0); | |||
2333 | if (Val.find_first_of("/\\") != StringRef::npos) { | |||
2334 | // Warn about e.g. "/Users/me/myfile.c". | |||
2335 | Diag(diag::warn_slash_u_filename) << Val; | |||
2336 | Diag(diag::note_use_dashdash); | |||
2337 | } | |||
2338 | } | |||
2339 | } | |||
2340 | if (CCCIsCPP() && Inputs.empty()) { | |||
2341 | // If called as standalone preprocessor, stdin is processed | |||
2342 | // if no other input is present. | |||
2343 | Arg *A = MakeInputArg(Args, Opts, "-"); | |||
2344 | Inputs.push_back(std::make_pair(types::TY_C, A)); | |||
2345 | } | |||
2346 | } | |||
2347 | ||||
2348 | namespace { | |||
2349 | /// Provides a convenient interface for different programming models to generate | |||
2350 | /// the required device actions. | |||
2351 | class OffloadingActionBuilder final { | |||
2352 | /// Flag used to trace errors in the builder. | |||
2353 | bool IsValid = false; | |||
2354 | ||||
2355 | /// The compilation that is using this builder. | |||
2356 | Compilation &C; | |||
2357 | ||||
2358 | /// Map between an input argument and the offload kinds used to process it. | |||
2359 | std::map<const Arg *, unsigned> InputArgToOffloadKindMap; | |||
2360 | ||||
2361 | /// Builder interface. It doesn't build anything or keep any state. | |||
2362 | class DeviceActionBuilder { | |||
2363 | public: | |||
2364 | typedef const llvm::SmallVectorImpl<phases::ID> PhasesTy; | |||
2365 | ||||
2366 | enum ActionBuilderReturnCode { | |||
2367 | // The builder acted successfully on the current action. | |||
2368 | ABRT_Success, | |||
2369 | // The builder didn't have to act on the current action. | |||
2370 | ABRT_Inactive, | |||
2371 | // The builder was successful and requested the host action to not be | |||
2372 | // generated. | |||
2373 | ABRT_Ignore_Host, | |||
2374 | }; | |||
2375 | ||||
2376 | protected: | |||
2377 | /// Compilation associated with this builder. | |||
2378 | Compilation &C; | |||
2379 | ||||
2380 | /// Tool chains associated with this builder. The same programming | |||
2381 | /// model may have associated one or more tool chains. | |||
2382 | SmallVector<const ToolChain *, 2> ToolChains; | |||
2383 | ||||
2384 | /// The derived arguments associated with this builder. | |||
2385 | DerivedArgList &Args; | |||
2386 | ||||
2387 | /// The inputs associated with this builder. | |||
2388 | const Driver::InputList &Inputs; | |||
2389 | ||||
2390 | /// The associated offload kind. | |||
2391 | Action::OffloadKind AssociatedOffloadKind = Action::OFK_None; | |||
2392 | ||||
2393 | public: | |||
2394 | DeviceActionBuilder(Compilation &C, DerivedArgList &Args, | |||
2395 | const Driver::InputList &Inputs, | |||
2396 | Action::OffloadKind AssociatedOffloadKind) | |||
2397 | : C(C), Args(Args), Inputs(Inputs), | |||
2398 | AssociatedOffloadKind(AssociatedOffloadKind) {} | |||
2399 | virtual ~DeviceActionBuilder() {} | |||
2400 | ||||
2401 | /// Fill up the array \a DA with all the device dependences that should be | |||
2402 | /// added to the provided host action \a HostAction. By default it is | |||
2403 | /// inactive. | |||
2404 | virtual ActionBuilderReturnCode | |||
2405 | getDeviceDependences(OffloadAction::DeviceDependences &DA, | |||
2406 | phases::ID CurPhase, phases::ID FinalPhase, | |||
2407 | PhasesTy &Phases) { | |||
2408 | return ABRT_Inactive; | |||
2409 | } | |||
2410 | ||||
2411 | /// Update the state to include the provided host action \a HostAction as a | |||
2412 | /// dependency of the current device action. By default it is inactive. | |||
2413 | virtual ActionBuilderReturnCode addDeviceDepences(Action *HostAction) { | |||
2414 | return ABRT_Inactive; | |||
2415 | } | |||
2416 | ||||
2417 | /// Append top level actions generated by the builder. | |||
2418 | virtual void appendTopLevelActions(ActionList &AL) {} | |||
2419 | ||||
2420 | /// Append linker device actions generated by the builder. | |||
2421 | virtual void appendLinkDeviceActions(ActionList &AL) {} | |||
2422 | ||||
2423 | /// Append linker host action generated by the builder. | |||
2424 | virtual Action* appendLinkHostActions(ActionList &AL) { return nullptr; } | |||
2425 | ||||
2426 | /// Append linker actions generated by the builder. | |||
2427 | virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {} | |||
2428 | ||||
2429 | /// Initialize the builder. Return true if any initialization errors are | |||
2430 | /// found. | |||
2431 | virtual bool initialize() { return false; } | |||
2432 | ||||
2433 | /// Return true if the builder can use bundling/unbundling. | |||
2434 | virtual bool canUseBundlerUnbundler() const { return false; } | |||
2435 | ||||
2436 | /// Return true if this builder is valid. We have a valid builder if we have | |||
2437 | /// associated device tool chains. | |||
2438 | bool isValid() { return !ToolChains.empty(); } | |||
2439 | ||||
2440 | /// Return the associated offload kind. | |||
2441 | Action::OffloadKind getAssociatedOffloadKind() { | |||
2442 | return AssociatedOffloadKind; | |||
2443 | } | |||
2444 | }; | |||
2445 | ||||
2446 | /// Base class for CUDA/HIP action builder. It injects device code in | |||
2447 | /// the host backend action. | |||
2448 | class CudaActionBuilderBase : public DeviceActionBuilder { | |||
2449 | protected: | |||
2450 | /// Flags to signal if the user requested host-only or device-only | |||
2451 | /// compilation. | |||
2452 | bool CompileHostOnly = false; | |||
2453 | bool CompileDeviceOnly = false; | |||
2454 | bool EmitLLVM = false; | |||
2455 | bool EmitAsm = false; | |||
2456 | ||||
2457 | /// ID to identify each device compilation. For CUDA it is simply the | |||
2458 | /// GPU arch string. For HIP it is either the GPU arch string or GPU | |||
2459 | /// arch string plus feature strings delimited by a plus sign, e.g. | |||
2460 | /// gfx906+xnack. | |||
2461 | struct TargetID { | |||
2462 | /// Target ID string which is persistent throughout the compilation. | |||
2463 | const char *ID; | |||
2464 | TargetID(CudaArch Arch) { ID = CudaArchToString(Arch); } | |||
2465 | TargetID(const char *ID) : ID(ID) {} | |||
2466 | operator const char *() { return ID; } | |||
2467 | operator StringRef() { return StringRef(ID); } | |||
2468 | }; | |||
2469 | /// List of GPU architectures to use in this compilation. | |||
2470 | SmallVector<TargetID, 4> GpuArchList; | |||
2471 | ||||
2472 | /// The CUDA actions for the current input. | |||
2473 | ActionList CudaDeviceActions; | |||
2474 | ||||
2475 | /// The CUDA fat binary if it was generated for the current input. | |||
2476 | Action *CudaFatBinary = nullptr; | |||
2477 | ||||
2478 | /// Flag that is set to true if this builder acted on the current input. | |||
2479 | bool IsActive = false; | |||
2480 | ||||
2481 | /// Flag for -fgpu-rdc. | |||
2482 | bool Relocatable = false; | |||
2483 | ||||
2484 | /// Default GPU architecture if there's no one specified. | |||
2485 | CudaArch DefaultCudaArch = CudaArch::UNKNOWN; | |||
2486 | ||||
2487 | /// Method to generate compilation unit ID specified by option | |||
2488 | /// '-fuse-cuid='. | |||
2489 | enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid }; | |||
2490 | UseCUIDKind UseCUID = CUID_Hash; | |||
2491 | ||||
2492 | /// Compilation unit ID specified by option '-cuid='. | |||
2493 | StringRef FixedCUID; | |||
2494 | ||||
2495 | public: | |||
2496 | CudaActionBuilderBase(Compilation &C, DerivedArgList &Args, | |||
2497 | const Driver::InputList &Inputs, | |||
2498 | Action::OffloadKind OFKind) | |||
2499 | : DeviceActionBuilder(C, Args, Inputs, OFKind) {} | |||
2500 | ||||
2501 | ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override { | |||
2502 | // While generating code for CUDA, we only depend on the host input action | |||
2503 | // to trigger the creation of all the CUDA device actions. | |||
2504 | ||||
2505 | // If we are dealing with an input action, replicate it for each GPU | |||
2506 | // architecture. If we are in host-only mode we return 'success' so that | |||
2507 | // the host uses the CUDA offload kind. | |||
2508 | if (auto *IA = dyn_cast<InputAction>(HostAction)) { | |||
2509 | assert(!GpuArchList.empty() &&(static_cast <bool> (!GpuArchList.empty() && "We should have at least one GPU architecture." ) ? void (0) : __assert_fail ("!GpuArchList.empty() && \"We should have at least one GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2510, __extension__ __PRETTY_FUNCTION__)) | |||
2510 | "We should have at least one GPU architecture.")(static_cast <bool> (!GpuArchList.empty() && "We should have at least one GPU architecture." ) ? void (0) : __assert_fail ("!GpuArchList.empty() && \"We should have at least one GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2510, __extension__ __PRETTY_FUNCTION__)); | |||
2511 | ||||
2512 | // If the host input is not CUDA or HIP, we don't need to bother about | |||
2513 | // this input. | |||
2514 | if (!(IA->getType() == types::TY_CUDA || | |||
2515 | IA->getType() == types::TY_HIP || | |||
2516 | IA->getType() == types::TY_PP_HIP)) { | |||
2517 | // The builder will ignore this input. | |||
2518 | IsActive = false; | |||
2519 | return ABRT_Inactive; | |||
2520 | } | |||
2521 | ||||
2522 | // Set the flag to true, so that the builder acts on the current input. | |||
2523 | IsActive = true; | |||
2524 | ||||
2525 | if (CompileHostOnly) | |||
2526 | return ABRT_Success; | |||
2527 | ||||
2528 | // Replicate inputs for each GPU architecture. | |||
2529 | auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE | |||
2530 | : types::TY_CUDA_DEVICE; | |||
2531 | std::string CUID = FixedCUID.str(); | |||
2532 | if (CUID.empty()) { | |||
2533 | if (UseCUID == CUID_Random) | |||
2534 | CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(), | |||
2535 | /*LowerCase=*/true); | |||
2536 | else if (UseCUID == CUID_Hash) { | |||
2537 | llvm::MD5 Hasher; | |||
2538 | llvm::MD5::MD5Result Hash; | |||
2539 | SmallString<256> RealPath; | |||
2540 | llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath, | |||
2541 | /*expand_tilde=*/true); | |||
2542 | Hasher.update(RealPath); | |||
2543 | for (auto *A : Args) { | |||
2544 | if (A->getOption().matches(options::OPT_INPUT)) | |||
2545 | continue; | |||
2546 | Hasher.update(A->getAsString(Args)); | |||
2547 | } | |||
2548 | Hasher.final(Hash); | |||
2549 | CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true); | |||
2550 | } | |||
2551 | } | |||
2552 | IA->setId(CUID); | |||
2553 | ||||
2554 | for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { | |||
2555 | CudaDeviceActions.push_back( | |||
2556 | C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId())); | |||
2557 | } | |||
2558 | ||||
2559 | return ABRT_Success; | |||
2560 | } | |||
2561 | ||||
2562 | // If this is an unbundling action use it as is for each CUDA toolchain. | |||
2563 | if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) { | |||
2564 | ||||
2565 | // If -fgpu-rdc is disabled, should not unbundle since there is no | |||
2566 | // device code to link. | |||
2567 | if (UA->getType() == types::TY_Object && !Relocatable) | |||
2568 | return ABRT_Inactive; | |||
2569 | ||||
2570 | CudaDeviceActions.clear(); | |||
2571 | auto *IA = cast<InputAction>(UA->getInputs().back()); | |||
2572 | std::string FileName = IA->getInputArg().getAsString(Args); | |||
2573 | // Check if the type of the file is the same as the action. Do not | |||
2574 | // unbundle it if it is not. Do not unbundle .so files, for example, | |||
2575 | // which are not object files. | |||
2576 | if (IA->getType() == types::TY_Object && | |||
2577 | (!llvm::sys::path::has_extension(FileName) || | |||
2578 | types::lookupTypeForExtension( | |||
2579 | llvm::sys::path::extension(FileName).drop_front()) != | |||
2580 | types::TY_Object)) | |||
2581 | return ABRT_Inactive; | |||
2582 | ||||
2583 | for (auto Arch : GpuArchList) { | |||
2584 | CudaDeviceActions.push_back(UA); | |||
2585 | UA->registerDependentActionInfo(ToolChains[0], Arch, | |||
2586 | AssociatedOffloadKind); | |||
2587 | } | |||
2588 | return ABRT_Success; | |||
2589 | } | |||
2590 | ||||
2591 | return IsActive ? ABRT_Success : ABRT_Inactive; | |||
2592 | } | |||
2593 | ||||
2594 | void appendTopLevelActions(ActionList &AL) override { | |||
2595 | // Utility to append actions to the top level list. | |||
2596 | auto AddTopLevel = [&](Action *A, TargetID TargetID) { | |||
2597 | OffloadAction::DeviceDependences Dep; | |||
2598 | Dep.add(*A, *ToolChains.front(), TargetID, AssociatedOffloadKind); | |||
2599 | AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType())); | |||
2600 | }; | |||
2601 | ||||
2602 | // If we have a fat binary, add it to the list. | |||
2603 | if (CudaFatBinary) { | |||
2604 | AddTopLevel(CudaFatBinary, CudaArch::UNUSED); | |||
2605 | CudaDeviceActions.clear(); | |||
2606 | CudaFatBinary = nullptr; | |||
2607 | return; | |||
2608 | } | |||
2609 | ||||
2610 | if (CudaDeviceActions.empty()) | |||
2611 | return; | |||
2612 | ||||
2613 | // If we have CUDA actions at this point, that's because we have a have | |||
2614 | // partial compilation, so we should have an action for each GPU | |||
2615 | // architecture. | |||
2616 | assert(CudaDeviceActions.size() == GpuArchList.size() &&(static_cast <bool> (CudaDeviceActions.size() == GpuArchList .size() && "Expecting one action per GPU architecture." ) ? void (0) : __assert_fail ("CudaDeviceActions.size() == GpuArchList.size() && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2617, __extension__ __PRETTY_FUNCTION__)) | |||
2617 | "Expecting one action per GPU architecture.")(static_cast <bool> (CudaDeviceActions.size() == GpuArchList .size() && "Expecting one action per GPU architecture." ) ? void (0) : __assert_fail ("CudaDeviceActions.size() == GpuArchList.size() && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2617, __extension__ __PRETTY_FUNCTION__)); | |||
2618 | assert(ToolChains.size() == 1 &&(static_cast <bool> (ToolChains.size() == 1 && "Expecting to have a sing CUDA toolchain." ) ? void (0) : __assert_fail ("ToolChains.size() == 1 && \"Expecting to have a sing CUDA toolchain.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2619, __extension__ __PRETTY_FUNCTION__)) | |||
2619 | "Expecting to have a sing CUDA toolchain.")(static_cast <bool> (ToolChains.size() == 1 && "Expecting to have a sing CUDA toolchain." ) ? void (0) : __assert_fail ("ToolChains.size() == 1 && \"Expecting to have a sing CUDA toolchain.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2619, __extension__ __PRETTY_FUNCTION__)); | |||
2620 | for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) | |||
2621 | AddTopLevel(CudaDeviceActions[I], GpuArchList[I]); | |||
2622 | ||||
2623 | CudaDeviceActions.clear(); | |||
2624 | } | |||
2625 | ||||
2626 | /// Get canonicalized offload arch option. \returns empty StringRef if the | |||
2627 | /// option is invalid. | |||
2628 | virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0; | |||
2629 | ||||
2630 | virtual llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> | |||
2631 | getConflictOffloadArchCombination(const std::set<StringRef> &GpuArchs) = 0; | |||
2632 | ||||
2633 | bool initialize() override { | |||
2634 | assert(AssociatedOffloadKind == Action::OFK_Cuda ||(static_cast <bool> (AssociatedOffloadKind == Action::OFK_Cuda || AssociatedOffloadKind == Action::OFK_HIP) ? void (0) : __assert_fail ("AssociatedOffloadKind == Action::OFK_Cuda || AssociatedOffloadKind == Action::OFK_HIP" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2635, __extension__ __PRETTY_FUNCTION__)) | |||
2635 | AssociatedOffloadKind == Action::OFK_HIP)(static_cast <bool> (AssociatedOffloadKind == Action::OFK_Cuda || AssociatedOffloadKind == Action::OFK_HIP) ? void (0) : __assert_fail ("AssociatedOffloadKind == Action::OFK_Cuda || AssociatedOffloadKind == Action::OFK_HIP" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2635, __extension__ __PRETTY_FUNCTION__)); | |||
2636 | ||||
2637 | // We don't need to support CUDA. | |||
2638 | if (AssociatedOffloadKind == Action::OFK_Cuda && | |||
2639 | !C.hasOffloadToolChain<Action::OFK_Cuda>()) | |||
2640 | return false; | |||
2641 | ||||
2642 | // We don't need to support HIP. | |||
2643 | if (AssociatedOffloadKind == Action::OFK_HIP && | |||
2644 | !C.hasOffloadToolChain<Action::OFK_HIP>()) | |||
2645 | return false; | |||
2646 | ||||
2647 | Relocatable = Args.hasFlag(options::OPT_fgpu_rdc, | |||
2648 | options::OPT_fno_gpu_rdc, /*Default=*/false); | |||
2649 | ||||
2650 | const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>(); | |||
2651 | assert(HostTC && "No toolchain for host compilation.")(static_cast <bool> (HostTC && "No toolchain for host compilation." ) ? void (0) : __assert_fail ("HostTC && \"No toolchain for host compilation.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2651, __extension__ __PRETTY_FUNCTION__)); | |||
2652 | if (HostTC->getTriple().isNVPTX() || | |||
2653 | HostTC->getTriple().getArch() == llvm::Triple::amdgcn) { | |||
2654 | // We do not support targeting NVPTX/AMDGCN for host compilation. Throw | |||
2655 | // an error and abort pipeline construction early so we don't trip | |||
2656 | // asserts that assume device-side compilation. | |||
2657 | C.getDriver().Diag(diag::err_drv_cuda_host_arch) | |||
2658 | << HostTC->getTriple().getArchName(); | |||
2659 | return true; | |||
2660 | } | |||
2661 | ||||
2662 | ToolChains.push_back( | |||
2663 | AssociatedOffloadKind == Action::OFK_Cuda | |||
2664 | ? C.getSingleOffloadToolChain<Action::OFK_Cuda>() | |||
2665 | : C.getSingleOffloadToolChain<Action::OFK_HIP>()); | |||
2666 | ||||
2667 | Arg *PartialCompilationArg = Args.getLastArg( | |||
2668 | options::OPT_cuda_host_only, options::OPT_cuda_device_only, | |||
2669 | options::OPT_cuda_compile_host_device); | |||
2670 | CompileHostOnly = PartialCompilationArg && | |||
2671 | PartialCompilationArg->getOption().matches( | |||
2672 | options::OPT_cuda_host_only); | |||
2673 | CompileDeviceOnly = PartialCompilationArg && | |||
2674 | PartialCompilationArg->getOption().matches( | |||
2675 | options::OPT_cuda_device_only); | |||
2676 | EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); | |||
2677 | EmitAsm = Args.getLastArg(options::OPT_S); | |||
2678 | FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ); | |||
2679 | if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) { | |||
2680 | StringRef UseCUIDStr = A->getValue(); | |||
2681 | UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr) | |||
2682 | .Case("hash", CUID_Hash) | |||
2683 | .Case("random", CUID_Random) | |||
2684 | .Case("none", CUID_None) | |||
2685 | .Default(CUID_Invalid); | |||
2686 | if (UseCUID == CUID_Invalid) { | |||
2687 | C.getDriver().Diag(diag::err_drv_invalid_value) | |||
2688 | << A->getAsString(Args) << UseCUIDStr; | |||
2689 | C.setContainsError(); | |||
2690 | return true; | |||
2691 | } | |||
2692 | } | |||
2693 | ||||
2694 | // Collect all cuda_gpu_arch parameters, removing duplicates. | |||
2695 | std::set<StringRef> GpuArchs; | |||
2696 | bool Error = false; | |||
2697 | for (Arg *A : Args) { | |||
2698 | if (!(A->getOption().matches(options::OPT_offload_arch_EQ) || | |||
2699 | A->getOption().matches(options::OPT_no_offload_arch_EQ))) | |||
2700 | continue; | |||
2701 | A->claim(); | |||
2702 | ||||
2703 | StringRef ArchStr = A->getValue(); | |||
2704 | if (A->getOption().matches(options::OPT_no_offload_arch_EQ) && | |||
2705 | ArchStr == "all") { | |||
2706 | GpuArchs.clear(); | |||
2707 | continue; | |||
2708 | } | |||
2709 | ArchStr = getCanonicalOffloadArch(ArchStr); | |||
2710 | if (ArchStr.empty()) { | |||
2711 | Error = true; | |||
2712 | } else if (A->getOption().matches(options::OPT_offload_arch_EQ)) | |||
2713 | GpuArchs.insert(ArchStr); | |||
2714 | else if (A->getOption().matches(options::OPT_no_offload_arch_EQ)) | |||
2715 | GpuArchs.erase(ArchStr); | |||
2716 | else | |||
2717 | llvm_unreachable("Unexpected option.")::llvm::llvm_unreachable_internal("Unexpected option.", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2717); | |||
2718 | } | |||
2719 | ||||
2720 | auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs); | |||
2721 | if (ConflictingArchs) { | |||
2722 | C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo) | |||
2723 | << ConflictingArchs.getValue().first | |||
2724 | << ConflictingArchs.getValue().second; | |||
2725 | C.setContainsError(); | |||
2726 | return true; | |||
2727 | } | |||
2728 | ||||
2729 | // Collect list of GPUs remaining in the set. | |||
2730 | for (auto Arch : GpuArchs) | |||
2731 | GpuArchList.push_back(Arch.data()); | |||
2732 | ||||
2733 | // Default to sm_20 which is the lowest common denominator for | |||
2734 | // supported GPUs. sm_20 code should work correctly, if | |||
2735 | // suboptimally, on all newer GPUs. | |||
2736 | if (GpuArchList.empty()) | |||
2737 | GpuArchList.push_back(DefaultCudaArch); | |||
2738 | ||||
2739 | return Error; | |||
2740 | } | |||
2741 | }; | |||
2742 | ||||
2743 | /// \brief CUDA action builder. It injects device code in the host backend | |||
2744 | /// action. | |||
2745 | class CudaActionBuilder final : public CudaActionBuilderBase { | |||
2746 | public: | |||
2747 | CudaActionBuilder(Compilation &C, DerivedArgList &Args, | |||
2748 | const Driver::InputList &Inputs) | |||
2749 | : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) { | |||
2750 | DefaultCudaArch = CudaArch::SM_20; | |||
2751 | } | |||
2752 | ||||
2753 | StringRef getCanonicalOffloadArch(StringRef ArchStr) override { | |||
2754 | CudaArch Arch = StringToCudaArch(ArchStr); | |||
2755 | if (Arch == CudaArch::UNKNOWN) { | |||
2756 | C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr; | |||
2757 | return StringRef(); | |||
2758 | } | |||
2759 | return CudaArchToString(Arch); | |||
2760 | } | |||
2761 | ||||
2762 | llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> | |||
2763 | getConflictOffloadArchCombination( | |||
2764 | const std::set<StringRef> &GpuArchs) override { | |||
2765 | return llvm::None; | |||
2766 | } | |||
2767 | ||||
2768 | ActionBuilderReturnCode | |||
2769 | getDeviceDependences(OffloadAction::DeviceDependences &DA, | |||
2770 | phases::ID CurPhase, phases::ID FinalPhase, | |||
2771 | PhasesTy &Phases) override { | |||
2772 | if (!IsActive) | |||
2773 | return ABRT_Inactive; | |||
2774 | ||||
2775 | // If we don't have more CUDA actions, we don't have any dependences to | |||
2776 | // create for the host. | |||
2777 | if (CudaDeviceActions.empty()) | |||
2778 | return ABRT_Success; | |||
2779 | ||||
2780 | assert(CudaDeviceActions.size() == GpuArchList.size() &&(static_cast <bool> (CudaDeviceActions.size() == GpuArchList .size() && "Expecting one action per GPU architecture." ) ? void (0) : __assert_fail ("CudaDeviceActions.size() == GpuArchList.size() && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2781, __extension__ __PRETTY_FUNCTION__)) | |||
2781 | "Expecting one action per GPU architecture.")(static_cast <bool> (CudaDeviceActions.size() == GpuArchList .size() && "Expecting one action per GPU architecture." ) ? void (0) : __assert_fail ("CudaDeviceActions.size() == GpuArchList.size() && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2781, __extension__ __PRETTY_FUNCTION__)); | |||
2782 | assert(!CompileHostOnly &&(static_cast <bool> (!CompileHostOnly && "Not expecting CUDA actions in host-only compilation." ) ? void (0) : __assert_fail ("!CompileHostOnly && \"Not expecting CUDA actions in host-only compilation.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2783, __extension__ __PRETTY_FUNCTION__)) | |||
2783 | "Not expecting CUDA actions in host-only compilation.")(static_cast <bool> (!CompileHostOnly && "Not expecting CUDA actions in host-only compilation." ) ? void (0) : __assert_fail ("!CompileHostOnly && \"Not expecting CUDA actions in host-only compilation.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2783, __extension__ __PRETTY_FUNCTION__)); | |||
2784 | ||||
2785 | // If we are generating code for the device or we are in a backend phase, | |||
2786 | // we attempt to generate the fat binary. We compile each arch to ptx and | |||
2787 | // assemble to cubin, then feed the cubin *and* the ptx into a device | |||
2788 | // "link" action, which uses fatbinary to combine these cubins into one | |||
2789 | // fatbin. The fatbin is then an input to the host action if not in | |||
2790 | // device-only mode. | |||
2791 | if (CompileDeviceOnly || CurPhase == phases::Backend) { | |||
2792 | ActionList DeviceActions; | |||
2793 | for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { | |||
2794 | // Produce the device action from the current phase up to the assemble | |||
2795 | // phase. | |||
2796 | for (auto Ph : Phases) { | |||
2797 | // Skip the phases that were already dealt with. | |||
2798 | if (Ph < CurPhase) | |||
2799 | continue; | |||
2800 | // We have to be consistent with the host final phase. | |||
2801 | if (Ph > FinalPhase) | |||
2802 | break; | |||
2803 | ||||
2804 | CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction( | |||
2805 | C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda); | |||
2806 | ||||
2807 | if (Ph == phases::Assemble) | |||
2808 | break; | |||
2809 | } | |||
2810 | ||||
2811 | // If we didn't reach the assemble phase, we can't generate the fat | |||
2812 | // binary. We don't need to generate the fat binary if we are not in | |||
2813 | // device-only mode. | |||
2814 | if (!isa<AssembleJobAction>(CudaDeviceActions[I]) || | |||
2815 | CompileDeviceOnly) | |||
2816 | continue; | |||
2817 | ||||
2818 | Action *AssembleAction = CudaDeviceActions[I]; | |||
2819 | assert(AssembleAction->getType() == types::TY_Object)(static_cast <bool> (AssembleAction->getType() == types ::TY_Object) ? void (0) : __assert_fail ("AssembleAction->getType() == types::TY_Object" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2819, __extension__ __PRETTY_FUNCTION__)); | |||
2820 | assert(AssembleAction->getInputs().size() == 1)(static_cast <bool> (AssembleAction->getInputs().size () == 1) ? void (0) : __assert_fail ("AssembleAction->getInputs().size() == 1" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2820, __extension__ __PRETTY_FUNCTION__)); | |||
2821 | ||||
2822 | Action *BackendAction = AssembleAction->getInputs()[0]; | |||
2823 | assert(BackendAction->getType() == types::TY_PP_Asm)(static_cast <bool> (BackendAction->getType() == types ::TY_PP_Asm) ? void (0) : __assert_fail ("BackendAction->getType() == types::TY_PP_Asm" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2823, __extension__ __PRETTY_FUNCTION__)); | |||
2824 | ||||
2825 | for (auto &A : {AssembleAction, BackendAction}) { | |||
2826 | OffloadAction::DeviceDependences DDep; | |||
2827 | DDep.add(*A, *ToolChains.front(), GpuArchList[I], Action::OFK_Cuda); | |||
2828 | DeviceActions.push_back( | |||
2829 | C.MakeAction<OffloadAction>(DDep, A->getType())); | |||
2830 | } | |||
2831 | } | |||
2832 | ||||
2833 | // We generate the fat binary if we have device input actions. | |||
2834 | if (!DeviceActions.empty()) { | |||
2835 | CudaFatBinary = | |||
2836 | C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN); | |||
2837 | ||||
2838 | if (!CompileDeviceOnly) { | |||
2839 | DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr, | |||
2840 | Action::OFK_Cuda); | |||
2841 | // Clear the fat binary, it is already a dependence to an host | |||
2842 | // action. | |||
2843 | CudaFatBinary = nullptr; | |||
2844 | } | |||
2845 | ||||
2846 | // Remove the CUDA actions as they are already connected to an host | |||
2847 | // action or fat binary. | |||
2848 | CudaDeviceActions.clear(); | |||
2849 | } | |||
2850 | ||||
2851 | // We avoid creating host action in device-only mode. | |||
2852 | return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success; | |||
2853 | } else if (CurPhase > phases::Backend) { | |||
2854 | // If we are past the backend phase and still have a device action, we | |||
2855 | // don't have to do anything as this action is already a device | |||
2856 | // top-level action. | |||
2857 | return ABRT_Success; | |||
2858 | } | |||
2859 | ||||
2860 | assert(CurPhase < phases::Backend && "Generating single CUDA "(static_cast <bool> (CurPhase < phases::Backend && "Generating single CUDA " "instructions should only occur " "before the backend phase!" ) ? void (0) : __assert_fail ("CurPhase < phases::Backend && \"Generating single CUDA \" \"instructions should only occur \" \"before the backend phase!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2862, __extension__ __PRETTY_FUNCTION__)) | |||
2861 | "instructions should only occur "(static_cast <bool> (CurPhase < phases::Backend && "Generating single CUDA " "instructions should only occur " "before the backend phase!" ) ? void (0) : __assert_fail ("CurPhase < phases::Backend && \"Generating single CUDA \" \"instructions should only occur \" \"before the backend phase!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2862, __extension__ __PRETTY_FUNCTION__)) | |||
2862 | "before the backend phase!")(static_cast <bool> (CurPhase < phases::Backend && "Generating single CUDA " "instructions should only occur " "before the backend phase!" ) ? void (0) : __assert_fail ("CurPhase < phases::Backend && \"Generating single CUDA \" \"instructions should only occur \" \"before the backend phase!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2862, __extension__ __PRETTY_FUNCTION__)); | |||
2863 | ||||
2864 | // By default, we produce an action for each device arch. | |||
2865 | for (Action *&A : CudaDeviceActions) | |||
2866 | A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A); | |||
2867 | ||||
2868 | return ABRT_Success; | |||
2869 | } | |||
2870 | }; | |||
2871 | /// \brief HIP action builder. It injects device code in the host backend | |||
2872 | /// action. | |||
2873 | class HIPActionBuilder final : public CudaActionBuilderBase { | |||
2874 | /// The linker inputs obtained for each device arch. | |||
2875 | SmallVector<ActionList, 8> DeviceLinkerInputs; | |||
2876 | bool GPUSanitize; | |||
2877 | ||||
2878 | public: | |||
2879 | HIPActionBuilder(Compilation &C, DerivedArgList &Args, | |||
2880 | const Driver::InputList &Inputs) | |||
2881 | : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) { | |||
2882 | DefaultCudaArch = CudaArch::GFX803; | |||
2883 | GPUSanitize = Args.hasFlag(options::OPT_fgpu_sanitize, | |||
2884 | options::OPT_fno_gpu_sanitize, false); | |||
2885 | } | |||
2886 | ||||
2887 | bool canUseBundlerUnbundler() const override { return true; } | |||
2888 | ||||
2889 | StringRef getCanonicalOffloadArch(StringRef IdStr) override { | |||
2890 | llvm::StringMap<bool> Features; | |||
2891 | auto ArchStr = | |||
2892 | parseTargetID(getHIPOffloadTargetTriple(), IdStr, &Features); | |||
2893 | if (!ArchStr) { | |||
2894 | C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr; | |||
2895 | C.setContainsError(); | |||
2896 | return StringRef(); | |||
2897 | } | |||
2898 | auto CanId = getCanonicalTargetID(ArchStr.getValue(), Features); | |||
2899 | return Args.MakeArgStringRef(CanId); | |||
2900 | }; | |||
2901 | ||||
2902 | llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> | |||
2903 | getConflictOffloadArchCombination( | |||
2904 | const std::set<StringRef> &GpuArchs) override { | |||
2905 | return getConflictTargetIDCombination(GpuArchs); | |||
2906 | } | |||
2907 | ||||
2908 | ActionBuilderReturnCode | |||
2909 | getDeviceDependences(OffloadAction::DeviceDependences &DA, | |||
2910 | phases::ID CurPhase, phases::ID FinalPhase, | |||
2911 | PhasesTy &Phases) override { | |||
2912 | // amdgcn does not support linking of object files, therefore we skip | |||
2913 | // backend and assemble phases to output LLVM IR. Except for generating | |||
2914 | // non-relocatable device coee, where we generate fat binary for device | |||
2915 | // code and pass to host in Backend phase. | |||
2916 | if (CudaDeviceActions.empty()) | |||
2917 | return ABRT_Success; | |||
2918 | ||||
2919 | assert(((CurPhase == phases::Link && Relocatable) ||(static_cast <bool> (((CurPhase == phases::Link && Relocatable) || CudaDeviceActions.size() == GpuArchList.size ()) && "Expecting one action per GPU architecture.") ? void (0) : __assert_fail ("((CurPhase == phases::Link && Relocatable) || CudaDeviceActions.size() == GpuArchList.size()) && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2921, __extension__ __PRETTY_FUNCTION__)) | |||
2920 | CudaDeviceActions.size() == GpuArchList.size()) &&(static_cast <bool> (((CurPhase == phases::Link && Relocatable) || CudaDeviceActions.size() == GpuArchList.size ()) && "Expecting one action per GPU architecture.") ? void (0) : __assert_fail ("((CurPhase == phases::Link && Relocatable) || CudaDeviceActions.size() == GpuArchList.size()) && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2921, __extension__ __PRETTY_FUNCTION__)) | |||
2921 | "Expecting one action per GPU architecture.")(static_cast <bool> (((CurPhase == phases::Link && Relocatable) || CudaDeviceActions.size() == GpuArchList.size ()) && "Expecting one action per GPU architecture.") ? void (0) : __assert_fail ("((CurPhase == phases::Link && Relocatable) || CudaDeviceActions.size() == GpuArchList.size()) && \"Expecting one action per GPU architecture.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2921, __extension__ __PRETTY_FUNCTION__)); | |||
2922 | assert(!CompileHostOnly &&(static_cast <bool> (!CompileHostOnly && "Not expecting CUDA actions in host-only compilation." ) ? void (0) : __assert_fail ("!CompileHostOnly && \"Not expecting CUDA actions in host-only compilation.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2923, __extension__ __PRETTY_FUNCTION__)) | |||
2923 | "Not expecting CUDA actions in host-only compilation.")(static_cast <bool> (!CompileHostOnly && "Not expecting CUDA actions in host-only compilation." ) ? void (0) : __assert_fail ("!CompileHostOnly && \"Not expecting CUDA actions in host-only compilation.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 2923, __extension__ __PRETTY_FUNCTION__)); | |||
2924 | ||||
2925 | if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM && | |||
2926 | !EmitAsm) { | |||
2927 | // If we are in backend phase, we attempt to generate the fat binary. | |||
2928 | // We compile each arch to IR and use a link action to generate code | |||
2929 | // object containing ISA. Then we use a special "link" action to create | |||
2930 | // a fat binary containing all the code objects for different GPU's. | |||
2931 | // The fat binary is then an input to the host action. | |||
2932 | for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { | |||
2933 | if (GPUSanitize) { | |||
2934 | // When GPU sanitizer is enabled, since we need to link in the | |||
2935 | // the sanitizer runtime library after the sanitize pass, we have | |||
2936 | // to skip the backend and assemble phases and use lld to link | |||
2937 | // the bitcode. | |||
2938 | ActionList AL; | |||
2939 | AL.push_back(CudaDeviceActions[I]); | |||
2940 | // Create a link action to link device IR with device library | |||
2941 | // and generate ISA. | |||
2942 | CudaDeviceActions[I] = | |||
2943 | C.MakeAction<LinkJobAction>(AL, types::TY_Image); | |||
2944 | } else { | |||
2945 | // When GPU sanitizer is not enabled, we follow the conventional | |||
2946 | // compiler phases, including backend and assemble phases. | |||
2947 | ActionList AL; | |||
2948 | auto BackendAction = C.getDriver().ConstructPhaseAction( | |||
2949 | C, Args, phases::Backend, CudaDeviceActions[I], | |||
2950 | AssociatedOffloadKind); | |||
2951 | auto AssembleAction = C.getDriver().ConstructPhaseAction( | |||
2952 | C, Args, phases::Assemble, BackendAction, | |||
2953 | AssociatedOffloadKind); | |||
2954 | AL.push_back(AssembleAction); | |||
2955 | // Create a link action to link device IR with device library | |||
2956 | // and generate ISA. | |||
2957 | CudaDeviceActions[I] = | |||
2958 | C.MakeAction<LinkJobAction>(AL, types::TY_Image); | |||
2959 | } | |||
2960 | ||||
2961 | // OffloadingActionBuilder propagates device arch until an offload | |||
2962 | // action. Since the next action for creating fatbin does | |||
2963 | // not have device arch, whereas the above link action and its input | |||
2964 | // have device arch, an offload action is needed to stop the null | |||
2965 | // device arch of the next action being propagated to the above link | |||
2966 | // action. | |||
2967 | OffloadAction::DeviceDependences DDep; | |||
2968 | DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I], | |||
2969 | AssociatedOffloadKind); | |||
2970 | CudaDeviceActions[I] = C.MakeAction<OffloadAction>( | |||
2971 | DDep, CudaDeviceActions[I]->getType()); | |||
2972 | } | |||
2973 | // Create HIP fat binary with a special "link" action. | |||
2974 | CudaFatBinary = | |||
2975 | C.MakeAction<LinkJobAction>(CudaDeviceActions, | |||
2976 | types::TY_HIP_FATBIN); | |||
2977 | ||||
2978 | if (!CompileDeviceOnly) { | |||
2979 | DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr, | |||
2980 | AssociatedOffloadKind); | |||
2981 | // Clear the fat binary, it is already a dependence to an host | |||
2982 | // action. | |||
2983 | CudaFatBinary = nullptr; | |||
2984 | } | |||
2985 | ||||
2986 | // Remove the CUDA actions as they are already connected to an host | |||
2987 | // action or fat binary. | |||
2988 | CudaDeviceActions.clear(); | |||
2989 | ||||
2990 | return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success; | |||
2991 | } else if (CurPhase == phases::Link) { | |||
2992 | // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch. | |||
2993 | // This happens to each device action originated from each input file. | |||
2994 | // Later on, device actions in DeviceLinkerInputs are used to create | |||
2995 | // device link actions in appendLinkDependences and the created device | |||
2996 | // link actions are passed to the offload action as device dependence. | |||
2997 | DeviceLinkerInputs.resize(CudaDeviceActions.size()); | |||
2998 | auto LI = DeviceLinkerInputs.begin(); | |||
2999 | for (auto *A : CudaDeviceActions) { | |||
3000 | LI->push_back(A); | |||
3001 | ++LI; | |||
3002 | } | |||
3003 | ||||
3004 | // We will pass the device action as a host dependence, so we don't | |||
3005 | // need to do anything else with them. | |||
3006 | CudaDeviceActions.clear(); | |||
3007 | return ABRT_Success; | |||
3008 | } | |||
3009 | ||||
3010 | // By default, we produce an action for each device arch. | |||
3011 | for (Action *&A : CudaDeviceActions) | |||
3012 | A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A, | |||
3013 | AssociatedOffloadKind); | |||
3014 | ||||
3015 | return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host | |||
3016 | : ABRT_Success; | |||
3017 | } | |||
3018 | ||||
3019 | void appendLinkDeviceActions(ActionList &AL) override { | |||
3020 | if (DeviceLinkerInputs.size() == 0) | |||
3021 | return; | |||
3022 | ||||
3023 | assert(DeviceLinkerInputs.size() == GpuArchList.size() &&(static_cast <bool> (DeviceLinkerInputs.size() == GpuArchList .size() && "Linker inputs and GPU arch list sizes do not match." ) ? void (0) : __assert_fail ("DeviceLinkerInputs.size() == GpuArchList.size() && \"Linker inputs and GPU arch list sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3024, __extension__ __PRETTY_FUNCTION__)) | |||
3024 | "Linker inputs and GPU arch list sizes do not match.")(static_cast <bool> (DeviceLinkerInputs.size() == GpuArchList .size() && "Linker inputs and GPU arch list sizes do not match." ) ? void (0) : __assert_fail ("DeviceLinkerInputs.size() == GpuArchList.size() && \"Linker inputs and GPU arch list sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3024, __extension__ __PRETTY_FUNCTION__)); | |||
3025 | ||||
3026 | // Append a new link action for each device. | |||
3027 | unsigned I = 0; | |||
3028 | for (auto &LI : DeviceLinkerInputs) { | |||
3029 | // Each entry in DeviceLinkerInputs corresponds to a GPU arch. | |||
3030 | auto *DeviceLinkAction = | |||
3031 | C.MakeAction<LinkJobAction>(LI, types::TY_Image); | |||
3032 | // Linking all inputs for the current GPU arch. | |||
3033 | // LI contains all the inputs for the linker. | |||
3034 | OffloadAction::DeviceDependences DeviceLinkDeps; | |||
3035 | DeviceLinkDeps.add(*DeviceLinkAction, *ToolChains[0], | |||
3036 | GpuArchList[I], AssociatedOffloadKind); | |||
3037 | AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps, | |||
3038 | DeviceLinkAction->getType())); | |||
3039 | ++I; | |||
3040 | } | |||
3041 | DeviceLinkerInputs.clear(); | |||
3042 | ||||
3043 | // Create a host object from all the device images by embedding them | |||
3044 | // in a fat binary. | |||
3045 | OffloadAction::DeviceDependences DDeps; | |||
3046 | auto *TopDeviceLinkAction = | |||
3047 | C.MakeAction<LinkJobAction>(AL, types::TY_Object); | |||
3048 | DDeps.add(*TopDeviceLinkAction, *ToolChains[0], | |||
3049 | nullptr, AssociatedOffloadKind); | |||
3050 | ||||
3051 | // Offload the host object to the host linker. | |||
3052 | AL.push_back(C.MakeAction<OffloadAction>(DDeps, TopDeviceLinkAction->getType())); | |||
3053 | } | |||
3054 | ||||
3055 | Action* appendLinkHostActions(ActionList &AL) override { return AL.back(); } | |||
3056 | ||||
3057 | void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {} | |||
3058 | }; | |||
3059 | ||||
3060 | /// OpenMP action builder. The host bitcode is passed to the device frontend | |||
3061 | /// and all the device linked images are passed to the host link phase. | |||
3062 | class OpenMPActionBuilder final : public DeviceActionBuilder { | |||
3063 | /// The OpenMP actions for the current input. | |||
3064 | ActionList OpenMPDeviceActions; | |||
3065 | ||||
3066 | /// The linker inputs obtained for each toolchain. | |||
3067 | SmallVector<ActionList, 8> DeviceLinkerInputs; | |||
3068 | ||||
3069 | public: | |||
3070 | OpenMPActionBuilder(Compilation &C, DerivedArgList &Args, | |||
3071 | const Driver::InputList &Inputs) | |||
3072 | : DeviceActionBuilder(C, Args, Inputs, Action::OFK_OpenMP) {} | |||
3073 | ||||
3074 | ActionBuilderReturnCode | |||
3075 | getDeviceDependences(OffloadAction::DeviceDependences &DA, | |||
3076 | phases::ID CurPhase, phases::ID FinalPhase, | |||
3077 | PhasesTy &Phases) override { | |||
3078 | if (OpenMPDeviceActions.empty()) | |||
3079 | return ABRT_Inactive; | |||
3080 | ||||
3081 | // We should always have an action for each input. | |||
3082 | assert(OpenMPDeviceActions.size() == ToolChains.size() &&(static_cast <bool> (OpenMPDeviceActions.size() == ToolChains .size() && "Number of OpenMP actions and toolchains do not match." ) ? void (0) : __assert_fail ("OpenMPDeviceActions.size() == ToolChains.size() && \"Number of OpenMP actions and toolchains do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3083, __extension__ __PRETTY_FUNCTION__)) | |||
3083 | "Number of OpenMP actions and toolchains do not match.")(static_cast <bool> (OpenMPDeviceActions.size() == ToolChains .size() && "Number of OpenMP actions and toolchains do not match." ) ? void (0) : __assert_fail ("OpenMPDeviceActions.size() == ToolChains.size() && \"Number of OpenMP actions and toolchains do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3083, __extension__ __PRETTY_FUNCTION__)); | |||
3084 | ||||
3085 | // The host only depends on device action in the linking phase, when all | |||
3086 | // the device images have to be embedded in the host image. | |||
3087 | if (CurPhase == phases::Link) { | |||
3088 | assert(ToolChains.size() == DeviceLinkerInputs.size() &&(static_cast <bool> (ToolChains.size() == DeviceLinkerInputs .size() && "Toolchains and linker inputs sizes do not match." ) ? void (0) : __assert_fail ("ToolChains.size() == DeviceLinkerInputs.size() && \"Toolchains and linker inputs sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3089, __extension__ __PRETTY_FUNCTION__)) | |||
3089 | "Toolchains and linker inputs sizes do not match.")(static_cast <bool> (ToolChains.size() == DeviceLinkerInputs .size() && "Toolchains and linker inputs sizes do not match." ) ? void (0) : __assert_fail ("ToolChains.size() == DeviceLinkerInputs.size() && \"Toolchains and linker inputs sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3089, __extension__ __PRETTY_FUNCTION__)); | |||
3090 | auto LI = DeviceLinkerInputs.begin(); | |||
3091 | for (auto *A : OpenMPDeviceActions) { | |||
3092 | LI->push_back(A); | |||
3093 | ++LI; | |||
3094 | } | |||
3095 | ||||
3096 | // We passed the device action as a host dependence, so we don't need to | |||
3097 | // do anything else with them. | |||
3098 | OpenMPDeviceActions.clear(); | |||
3099 | return ABRT_Success; | |||
3100 | } | |||
3101 | ||||
3102 | // By default, we produce an action for each device arch. | |||
3103 | for (Action *&A : OpenMPDeviceActions) | |||
3104 | A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A); | |||
3105 | ||||
3106 | return ABRT_Success; | |||
3107 | } | |||
3108 | ||||
3109 | ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override { | |||
3110 | ||||
3111 | // If this is an input action replicate it for each OpenMP toolchain. | |||
3112 | if (auto *IA = dyn_cast<InputAction>(HostAction)) { | |||
3113 | OpenMPDeviceActions.clear(); | |||
3114 | for (unsigned I = 0; I < ToolChains.size(); ++I) | |||
3115 | OpenMPDeviceActions.push_back( | |||
3116 | C.MakeAction<InputAction>(IA->getInputArg(), IA->getType())); | |||
3117 | return ABRT_Success; | |||
3118 | } | |||
3119 | ||||
3120 | // If this is an unbundling action use it as is for each OpenMP toolchain. | |||
3121 | if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) { | |||
3122 | OpenMPDeviceActions.clear(); | |||
3123 | auto *IA = cast<InputAction>(UA->getInputs().back()); | |||
3124 | std::string FileName = IA->getInputArg().getAsString(Args); | |||
3125 | // Check if the type of the file is the same as the action. Do not | |||
3126 | // unbundle it if it is not. Do not unbundle .so files, for example, | |||
3127 | // which are not object files. | |||
3128 | if (IA->getType() == types::TY_Object && | |||
3129 | (!llvm::sys::path::has_extension(FileName) || | |||
3130 | types::lookupTypeForExtension( | |||
3131 | llvm::sys::path::extension(FileName).drop_front()) != | |||
3132 | types::TY_Object)) | |||
3133 | return ABRT_Inactive; | |||
3134 | for (unsigned I = 0; I < ToolChains.size(); ++I) { | |||
3135 | OpenMPDeviceActions.push_back(UA); | |||
3136 | UA->registerDependentActionInfo( | |||
3137 | ToolChains[I], /*BoundArch=*/StringRef(), Action::OFK_OpenMP); | |||
3138 | } | |||
3139 | return ABRT_Success; | |||
3140 | } | |||
3141 | ||||
3142 | // When generating code for OpenMP we use the host compile phase result as | |||
3143 | // a dependence to the device compile phase so that it can learn what | |||
3144 | // declarations should be emitted. However, this is not the only use for | |||
3145 | // the host action, so we prevent it from being collapsed. | |||
3146 | if (isa<CompileJobAction>(HostAction)) { | |||
3147 | HostAction->setCannotBeCollapsedWithNextDependentAction(); | |||
3148 | assert(ToolChains.size() == OpenMPDeviceActions.size() &&(static_cast <bool> (ToolChains.size() == OpenMPDeviceActions .size() && "Toolchains and device action sizes do not match." ) ? void (0) : __assert_fail ("ToolChains.size() == OpenMPDeviceActions.size() && \"Toolchains and device action sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3149, __extension__ __PRETTY_FUNCTION__)) | |||
3149 | "Toolchains and device action sizes do not match.")(static_cast <bool> (ToolChains.size() == OpenMPDeviceActions .size() && "Toolchains and device action sizes do not match." ) ? void (0) : __assert_fail ("ToolChains.size() == OpenMPDeviceActions.size() && \"Toolchains and device action sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3149, __extension__ __PRETTY_FUNCTION__)); | |||
3150 | OffloadAction::HostDependence HDep( | |||
3151 | *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(), | |||
3152 | /*BoundArch=*/nullptr, Action::OFK_OpenMP); | |||
3153 | auto TC = ToolChains.begin(); | |||
3154 | for (Action *&A : OpenMPDeviceActions) { | |||
3155 | assert(isa<CompileJobAction>(A))(static_cast <bool> (isa<CompileJobAction>(A)) ? void (0) : __assert_fail ("isa<CompileJobAction>(A)", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3155, __extension__ __PRETTY_FUNCTION__)); | |||
3156 | OffloadAction::DeviceDependences DDep; | |||
3157 | DDep.add(*A, **TC, /*BoundArch=*/nullptr, Action::OFK_OpenMP); | |||
3158 | A = C.MakeAction<OffloadAction>(HDep, DDep); | |||
3159 | ++TC; | |||
3160 | } | |||
3161 | } | |||
3162 | return ABRT_Success; | |||
3163 | } | |||
3164 | ||||
3165 | void appendTopLevelActions(ActionList &AL) override { | |||
3166 | if (OpenMPDeviceActions.empty()) | |||
3167 | return; | |||
3168 | ||||
3169 | // We should always have an action for each input. | |||
3170 | assert(OpenMPDeviceActions.size() == ToolChains.size() &&(static_cast <bool> (OpenMPDeviceActions.size() == ToolChains .size() && "Number of OpenMP actions and toolchains do not match." ) ? void (0) : __assert_fail ("OpenMPDeviceActions.size() == ToolChains.size() && \"Number of OpenMP actions and toolchains do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3171, __extension__ __PRETTY_FUNCTION__)) | |||
3171 | "Number of OpenMP actions and toolchains do not match.")(static_cast <bool> (OpenMPDeviceActions.size() == ToolChains .size() && "Number of OpenMP actions and toolchains do not match." ) ? void (0) : __assert_fail ("OpenMPDeviceActions.size() == ToolChains.size() && \"Number of OpenMP actions and toolchains do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3171, __extension__ __PRETTY_FUNCTION__)); | |||
3172 | ||||
3173 | // Append all device actions followed by the proper offload action. | |||
3174 | auto TI = ToolChains.begin(); | |||
3175 | for (auto *A : OpenMPDeviceActions) { | |||
3176 | OffloadAction::DeviceDependences Dep; | |||
3177 | Dep.add(*A, **TI, /*BoundArch=*/nullptr, Action::OFK_OpenMP); | |||
3178 | AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType())); | |||
3179 | ++TI; | |||
3180 | } | |||
3181 | // We no longer need the action stored in this builder. | |||
3182 | OpenMPDeviceActions.clear(); | |||
3183 | } | |||
3184 | ||||
3185 | void appendLinkDeviceActions(ActionList &AL) override { | |||
3186 | assert(ToolChains.size() == DeviceLinkerInputs.size() &&(static_cast <bool> (ToolChains.size() == DeviceLinkerInputs .size() && "Toolchains and linker inputs sizes do not match." ) ? void (0) : __assert_fail ("ToolChains.size() == DeviceLinkerInputs.size() && \"Toolchains and linker inputs sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3187, __extension__ __PRETTY_FUNCTION__)) | |||
3187 | "Toolchains and linker inputs sizes do not match.")(static_cast <bool> (ToolChains.size() == DeviceLinkerInputs .size() && "Toolchains and linker inputs sizes do not match." ) ? void (0) : __assert_fail ("ToolChains.size() == DeviceLinkerInputs.size() && \"Toolchains and linker inputs sizes do not match.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3187, __extension__ __PRETTY_FUNCTION__)); | |||
3188 | ||||
3189 | // Append a new link action for each device. | |||
3190 | auto TC = ToolChains.begin(); | |||
3191 | for (auto &LI : DeviceLinkerInputs) { | |||
3192 | auto *DeviceLinkAction = | |||
3193 | C.MakeAction<LinkJobAction>(LI, types::TY_Image); | |||
3194 | OffloadAction::DeviceDependences DeviceLinkDeps; | |||
3195 | DeviceLinkDeps.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr, | |||
3196 | Action::OFK_OpenMP); | |||
3197 | AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps, | |||
3198 | DeviceLinkAction->getType())); | |||
3199 | ++TC; | |||
3200 | } | |||
3201 | DeviceLinkerInputs.clear(); | |||
3202 | } | |||
3203 | ||||
3204 | Action* appendLinkHostActions(ActionList &AL) override { | |||
3205 | // Create wrapper bitcode from the result of device link actions and compile | |||
3206 | // it to an object which will be added to the host link command. | |||
3207 | auto *BC = C.MakeAction<OffloadWrapperJobAction>(AL, types::TY_LLVM_BC); | |||
3208 | auto *ASM = C.MakeAction<BackendJobAction>(BC, types::TY_PP_Asm); | |||
3209 | return C.MakeAction<AssembleJobAction>(ASM, types::TY_Object); | |||
3210 | } | |||
3211 | ||||
3212 | void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {} | |||
3213 | ||||
3214 | bool initialize() override { | |||
3215 | // Get the OpenMP toolchains. If we don't get any, the action builder will | |||
3216 | // know there is nothing to do related to OpenMP offloading. | |||
3217 | auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>(); | |||
3218 | for (auto TI = OpenMPTCRange.first, TE = OpenMPTCRange.second; TI != TE; | |||
3219 | ++TI) | |||
3220 | ToolChains.push_back(TI->second); | |||
3221 | ||||
3222 | DeviceLinkerInputs.resize(ToolChains.size()); | |||
3223 | return false; | |||
3224 | } | |||
3225 | ||||
3226 | bool canUseBundlerUnbundler() const override { | |||
3227 | // OpenMP should use bundled files whenever possible. | |||
3228 | return true; | |||
3229 | } | |||
3230 | }; | |||
3231 | ||||
3232 | /// | |||
3233 | /// TODO: Add the implementation for other specialized builders here. | |||
3234 | /// | |||
3235 | ||||
3236 | /// Specialized builders being used by this offloading action builder. | |||
3237 | SmallVector<DeviceActionBuilder *, 4> SpecializedBuilders; | |||
3238 | ||||
3239 | /// Flag set to true if all valid builders allow file bundling/unbundling. | |||
3240 | bool CanUseBundler; | |||
3241 | ||||
3242 | public: | |||
3243 | OffloadingActionBuilder(Compilation &C, DerivedArgList &Args, | |||
3244 | const Driver::InputList &Inputs) | |||
3245 | : C(C) { | |||
3246 | // Create a specialized builder for each device toolchain. | |||
3247 | ||||
3248 | IsValid = true; | |||
3249 | ||||
3250 | // Create a specialized builder for CUDA. | |||
3251 | SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs)); | |||
3252 | ||||
3253 | // Create a specialized builder for HIP. | |||
3254 | SpecializedBuilders.push_back(new HIPActionBuilder(C, Args, Inputs)); | |||
3255 | ||||
3256 | // Create a specialized builder for OpenMP. | |||
3257 | SpecializedBuilders.push_back(new OpenMPActionBuilder(C, Args, Inputs)); | |||
3258 | ||||
3259 | // | |||
3260 | // TODO: Build other specialized builders here. | |||
3261 | // | |||
3262 | ||||
3263 | // Initialize all the builders, keeping track of errors. If all valid | |||
3264 | // builders agree that we can use bundling, set the flag to true. | |||
3265 | unsigned ValidBuilders = 0u; | |||
3266 | unsigned ValidBuildersSupportingBundling = 0u; | |||
3267 | for (auto *SB : SpecializedBuilders) { | |||
3268 | IsValid = IsValid && !SB->initialize(); | |||
3269 | ||||
3270 | // Update the counters if the builder is valid. | |||
3271 | if (SB->isValid()) { | |||
3272 | ++ValidBuilders; | |||
3273 | if (SB->canUseBundlerUnbundler()) | |||
3274 | ++ValidBuildersSupportingBundling; | |||
3275 | } | |||
3276 | } | |||
3277 | CanUseBundler = | |||
3278 | ValidBuilders && ValidBuilders == ValidBuildersSupportingBundling; | |||
3279 | } | |||
3280 | ||||
3281 | ~OffloadingActionBuilder() { | |||
3282 | for (auto *SB : SpecializedBuilders) | |||
3283 | delete SB; | |||
3284 | } | |||
3285 | ||||
3286 | /// Generate an action that adds device dependences (if any) to a host action. | |||
3287 | /// If no device dependence actions exist, just return the host action \a | |||
3288 | /// HostAction. If an error is found or if no builder requires the host action | |||
3289 | /// to be generated, return nullptr. | |||
3290 | Action * | |||
3291 | addDeviceDependencesToHostAction(Action *HostAction, const Arg *InputArg, | |||
3292 | phases::ID CurPhase, phases::ID FinalPhase, | |||
3293 | DeviceActionBuilder::PhasesTy &Phases) { | |||
3294 | if (!IsValid) | |||
3295 | return nullptr; | |||
3296 | ||||
3297 | if (SpecializedBuilders.empty()) | |||
3298 | return HostAction; | |||
3299 | ||||
3300 | assert(HostAction && "Invalid host action!")(static_cast <bool> (HostAction && "Invalid host action!" ) ? void (0) : __assert_fail ("HostAction && \"Invalid host action!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3300, __extension__ __PRETTY_FUNCTION__)); | |||
3301 | ||||
3302 | OffloadAction::DeviceDependences DDeps; | |||
3303 | // Check if all the programming models agree we should not emit the host | |||
3304 | // action. Also, keep track of the offloading kinds employed. | |||
3305 | auto &OffloadKind = InputArgToOffloadKindMap[InputArg]; | |||
3306 | unsigned InactiveBuilders = 0u; | |||
3307 | unsigned IgnoringBuilders = 0u; | |||
3308 | for (auto *SB : SpecializedBuilders) { | |||
3309 | if (!SB->isValid()) { | |||
3310 | ++InactiveBuilders; | |||
3311 | continue; | |||
3312 | } | |||
3313 | ||||
3314 | auto RetCode = | |||
3315 | SB->getDeviceDependences(DDeps, CurPhase, FinalPhase, Phases); | |||
3316 | ||||
3317 | // If the builder explicitly says the host action should be ignored, | |||
3318 | // we need to increment the variable that tracks the builders that request | |||
3319 | // the host object to be ignored. | |||
3320 | if (RetCode == DeviceActionBuilder::ABRT_Ignore_Host) | |||
3321 | ++IgnoringBuilders; | |||
3322 | ||||
3323 | // Unless the builder was inactive for this action, we have to record the | |||
3324 | // offload kind because the host will have to use it. | |||
3325 | if (RetCode != DeviceActionBuilder::ABRT_Inactive) | |||
3326 | OffloadKind |= SB->getAssociatedOffloadKind(); | |||
3327 | } | |||
3328 | ||||
3329 | // If all builders agree that the host object should be ignored, just return | |||
3330 | // nullptr. | |||
3331 | if (IgnoringBuilders && | |||
3332 | SpecializedBuilders.size() == (InactiveBuilders + IgnoringBuilders)) | |||
3333 | return nullptr; | |||
3334 | ||||
3335 | if (DDeps.getActions().empty()) | |||
3336 | return HostAction; | |||
3337 | ||||
3338 | // We have dependences we need to bundle together. We use an offload action | |||
3339 | // for that. | |||
3340 | OffloadAction::HostDependence HDep( | |||
3341 | *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(), | |||
3342 | /*BoundArch=*/nullptr, DDeps); | |||
3343 | return C.MakeAction<OffloadAction>(HDep, DDeps); | |||
3344 | } | |||
3345 | ||||
3346 | /// Generate an action that adds a host dependence to a device action. The | |||
3347 | /// results will be kept in this action builder. Return true if an error was | |||
3348 | /// found. | |||
3349 | bool addHostDependenceToDeviceActions(Action *&HostAction, | |||
3350 | const Arg *InputArg) { | |||
3351 | if (!IsValid) | |||
3352 | return true; | |||
3353 | ||||
3354 | // If we are supporting bundling/unbundling and the current action is an | |||
3355 | // input action of non-source file, we replace the host action by the | |||
3356 | // unbundling action. The bundler tool has the logic to detect if an input | |||
3357 | // is a bundle or not and if the input is not a bundle it assumes it is a | |||
3358 | // host file. Therefore it is safe to create an unbundling action even if | |||
3359 | // the input is not a bundle. | |||
3360 | if (CanUseBundler && isa<InputAction>(HostAction) && | |||
3361 | InputArg->getOption().getKind() == llvm::opt::Option::InputClass && | |||
3362 | (!types::isSrcFile(HostAction->getType()) || | |||
3363 | HostAction->getType() == types::TY_PP_HIP)) { | |||
3364 | auto UnbundlingHostAction = | |||
3365 | C.MakeAction<OffloadUnbundlingJobAction>(HostAction); | |||
3366 | UnbundlingHostAction->registerDependentActionInfo( | |||
3367 | C.getSingleOffloadToolChain<Action::OFK_Host>(), | |||
3368 | /*BoundArch=*/StringRef(), Action::OFK_Host); | |||
3369 | HostAction = UnbundlingHostAction; | |||
3370 | } | |||
3371 | ||||
3372 | assert(HostAction && "Invalid host action!")(static_cast <bool> (HostAction && "Invalid host action!" ) ? void (0) : __assert_fail ("HostAction && \"Invalid host action!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3372, __extension__ __PRETTY_FUNCTION__)); | |||
3373 | ||||
3374 | // Register the offload kinds that are used. | |||
3375 | auto &OffloadKind = InputArgToOffloadKindMap[InputArg]; | |||
3376 | for (auto *SB : SpecializedBuilders) { | |||
3377 | if (!SB->isValid()) | |||
3378 | continue; | |||
3379 | ||||
3380 | auto RetCode = SB->addDeviceDepences(HostAction); | |||
3381 | ||||
3382 | // Host dependences for device actions are not compatible with that same | |||
3383 | // action being ignored. | |||
3384 | assert(RetCode != DeviceActionBuilder::ABRT_Ignore_Host &&(static_cast <bool> (RetCode != DeviceActionBuilder::ABRT_Ignore_Host && "Host dependence not expected to be ignored.!") ? void (0) : __assert_fail ("RetCode != DeviceActionBuilder::ABRT_Ignore_Host && \"Host dependence not expected to be ignored.!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3385, __extension__ __PRETTY_FUNCTION__)) | |||
3385 | "Host dependence not expected to be ignored.!")(static_cast <bool> (RetCode != DeviceActionBuilder::ABRT_Ignore_Host && "Host dependence not expected to be ignored.!") ? void (0) : __assert_fail ("RetCode != DeviceActionBuilder::ABRT_Ignore_Host && \"Host dependence not expected to be ignored.!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3385, __extension__ __PRETTY_FUNCTION__)); | |||
3386 | ||||
3387 | // Unless the builder was inactive for this action, we have to record the | |||
3388 | // offload kind because the host will have to use it. | |||
3389 | if (RetCode != DeviceActionBuilder::ABRT_Inactive) | |||
3390 | OffloadKind |= SB->getAssociatedOffloadKind(); | |||
3391 | } | |||
3392 | ||||
3393 | // Do not use unbundler if the Host does not depend on device action. | |||
3394 | if (OffloadKind == Action::OFK_None && CanUseBundler) | |||
3395 | if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) | |||
3396 | HostAction = UA->getInputs().back(); | |||
3397 | ||||
3398 | return false; | |||
3399 | } | |||
3400 | ||||
3401 | /// Add the offloading top level actions to the provided action list. This | |||
3402 | /// function can replace the host action by a bundling action if the | |||
3403 | /// programming models allow it. | |||
3404 | bool appendTopLevelActions(ActionList &AL, Action *HostAction, | |||
3405 | const Arg *InputArg) { | |||
3406 | // Get the device actions to be appended. | |||
3407 | ActionList OffloadAL; | |||
3408 | for (auto *SB : SpecializedBuilders) { | |||
3409 | if (!SB->isValid()) | |||
3410 | continue; | |||
3411 | SB->appendTopLevelActions(OffloadAL); | |||
3412 | } | |||
3413 | ||||
3414 | // If we can use the bundler, replace the host action by the bundling one in | |||
3415 | // the resulting list. Otherwise, just append the device actions. For | |||
3416 | // device only compilation, HostAction is a null pointer, therefore only do | |||
3417 | // this when HostAction is not a null pointer. | |||
3418 | if (CanUseBundler && HostAction && | |||
3419 | HostAction->getType() != types::TY_Nothing && !OffloadAL.empty()) { | |||
3420 | // Add the host action to the list in order to create the bundling action. | |||
3421 | OffloadAL.push_back(HostAction); | |||
3422 | ||||
3423 | // We expect that the host action was just appended to the action list | |||
3424 | // before this method was called. | |||
3425 | assert(HostAction == AL.back() && "Host action not in the list??")(static_cast <bool> (HostAction == AL.back() && "Host action not in the list??") ? void (0) : __assert_fail ( "HostAction == AL.back() && \"Host action not in the list??\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3425, __extension__ __PRETTY_FUNCTION__)); | |||
3426 | HostAction = C.MakeAction<OffloadBundlingJobAction>(OffloadAL); | |||
3427 | AL.back() = HostAction; | |||
3428 | } else | |||
3429 | AL.append(OffloadAL.begin(), OffloadAL.end()); | |||
3430 | ||||
3431 | // Propagate to the current host action (if any) the offload information | |||
3432 | // associated with the current input. | |||
3433 | if (HostAction) | |||
3434 | HostAction->propagateHostOffloadInfo(InputArgToOffloadKindMap[InputArg], | |||
3435 | /*BoundArch=*/nullptr); | |||
3436 | return false; | |||
3437 | } | |||
3438 | ||||
3439 | Action* makeHostLinkAction() { | |||
3440 | // Build a list of device linking actions. | |||
3441 | ActionList DeviceAL; | |||
3442 | for (DeviceActionBuilder *SB : SpecializedBuilders) { | |||
3443 | if (!SB->isValid()) | |||
3444 | continue; | |||
3445 | SB->appendLinkDeviceActions(DeviceAL); | |||
3446 | } | |||
3447 | ||||
3448 | if (DeviceAL.empty()) | |||
3449 | return nullptr; | |||
3450 | ||||
3451 | // Let builders add host linking actions. | |||
3452 | Action* HA; | |||
3453 | for (DeviceActionBuilder *SB : SpecializedBuilders) { | |||
3454 | if (!SB->isValid()) | |||
3455 | continue; | |||
3456 | HA = SB->appendLinkHostActions(DeviceAL); | |||
3457 | } | |||
3458 | return HA; | |||
| ||||
3459 | } | |||
3460 | ||||
3461 | /// Processes the host linker action. This currently consists of replacing it | |||
3462 | /// with an offload action if there are device link objects and propagate to | |||
3463 | /// the host action all the offload kinds used in the current compilation. The | |||
3464 | /// resulting action is returned. | |||
3465 | Action *processHostLinkAction(Action *HostAction) { | |||
3466 | // Add all the dependences from the device linking actions. | |||
3467 | OffloadAction::DeviceDependences DDeps; | |||
3468 | for (auto *SB : SpecializedBuilders) { | |||
3469 | if (!SB->isValid()) | |||
3470 | continue; | |||
3471 | ||||
3472 | SB->appendLinkDependences(DDeps); | |||
3473 | } | |||
3474 | ||||
3475 | // Calculate all the offload kinds used in the current compilation. | |||
3476 | unsigned ActiveOffloadKinds = 0u; | |||
3477 | for (auto &I : InputArgToOffloadKindMap) | |||
3478 | ActiveOffloadKinds |= I.second; | |||
3479 | ||||
3480 | // If we don't have device dependencies, we don't have to create an offload | |||
3481 | // action. | |||
3482 | if (DDeps.getActions().empty()) { | |||
3483 | // Propagate all the active kinds to host action. Given that it is a link | |||
3484 | // action it is assumed to depend on all actions generated so far. | |||
3485 | HostAction->propagateHostOffloadInfo(ActiveOffloadKinds, | |||
3486 | /*BoundArch=*/nullptr); | |||
3487 | return HostAction; | |||
3488 | } | |||
3489 | ||||
3490 | // Create the offload action with all dependences. When an offload action | |||
3491 | // is created the kinds are propagated to the host action, so we don't have | |||
3492 | // to do that explicitly here. | |||
3493 | OffloadAction::HostDependence HDep( | |||
3494 | *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(), | |||
3495 | /*BoundArch*/ nullptr, ActiveOffloadKinds); | |||
3496 | return C.MakeAction<OffloadAction>(HDep, DDeps); | |||
3497 | } | |||
3498 | }; | |||
3499 | } // anonymous namespace. | |||
3500 | ||||
3501 | void Driver::handleArguments(Compilation &C, DerivedArgList &Args, | |||
3502 | const InputList &Inputs, | |||
3503 | ActionList &Actions) const { | |||
3504 | ||||
3505 | // Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames. | |||
3506 | Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc); | |||
3507 | Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu); | |||
3508 | if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) { | |||
3509 | Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl); | |||
3510 | Args.eraseArg(options::OPT__SLASH_Yc); | |||
3511 | Args.eraseArg(options::OPT__SLASH_Yu); | |||
3512 | YcArg = YuArg = nullptr; | |||
3513 | } | |||
3514 | if (YcArg && Inputs.size() > 1) { | |||
3515 | Diag(clang::diag::warn_drv_yc_multiple_inputs_clang_cl); | |||
3516 | Args.eraseArg(options::OPT__SLASH_Yc); | |||
3517 | YcArg = nullptr; | |||
3518 | } | |||
3519 | ||||
3520 | Arg *FinalPhaseArg; | |||
3521 | phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); | |||
3522 | ||||
3523 | if (FinalPhase == phases::Link) { | |||
3524 | if (Args.hasArg(options::OPT_emit_llvm)) | |||
3525 | Diag(clang::diag::err_drv_emit_llvm_link); | |||
3526 | if (IsCLMode() && LTOMode != LTOK_None && | |||
3527 | !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld")) | |||
3528 | Diag(clang::diag::err_drv_lto_without_lld); | |||
3529 | } | |||
3530 | ||||
3531 | if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) { | |||
3532 | // If only preprocessing or /Y- is used, all pch handling is disabled. | |||
3533 | // Rather than check for it everywhere, just remove clang-cl pch-related | |||
3534 | // flags here. | |||
3535 | Args.eraseArg(options::OPT__SLASH_Fp); | |||
3536 | Args.eraseArg(options::OPT__SLASH_Yc); | |||
3537 | Args.eraseArg(options::OPT__SLASH_Yu); | |||
3538 | YcArg = YuArg = nullptr; | |||
3539 | } | |||
3540 | ||||
3541 | unsigned LastPLSize = 0; | |||
3542 | for (auto &I : Inputs) { | |||
3543 | types::ID InputType = I.first; | |||
3544 | const Arg *InputArg = I.second; | |||
3545 | ||||
3546 | auto PL = types::getCompilationPhases(InputType); | |||
3547 | LastPLSize = PL.size(); | |||
3548 | ||||
3549 | // If the first step comes after the final phase we are doing as part of | |||
3550 | // this compilation, warn the user about it. | |||
3551 | phases::ID InitialPhase = PL[0]; | |||
3552 | if (InitialPhase > FinalPhase) { | |||
3553 | if (InputArg->isClaimed()) | |||
3554 | continue; | |||
3555 | ||||
3556 | // Claim here to avoid the more general unused warning. | |||
3557 | InputArg->claim(); | |||
3558 | ||||
3559 | // Suppress all unused style warnings with -Qunused-arguments | |||
3560 | if (Args.hasArg(options::OPT_Qunused_arguments)) | |||
3561 | continue; | |||
3562 | ||||
3563 | // Special case when final phase determined by binary name, rather than | |||
3564 | // by a command-line argument with a corresponding Arg. | |||
3565 | if (CCCIsCPP()) | |||
3566 | Diag(clang::diag::warn_drv_input_file_unused_by_cpp) | |||
3567 | << InputArg->getAsString(Args) << getPhaseName(InitialPhase); | |||
3568 | // Special case '-E' warning on a previously preprocessed file to make | |||
3569 | // more sense. | |||
3570 | else if (InitialPhase == phases::Compile && | |||
3571 | (Args.getLastArg(options::OPT__SLASH_EP, | |||
3572 | options::OPT__SLASH_P) || | |||
3573 | Args.getLastArg(options::OPT_E) || | |||
3574 | Args.getLastArg(options::OPT_M, options::OPT_MM)) && | |||
3575 | getPreprocessedType(InputType) == types::TY_INVALID) | |||
3576 | Diag(clang::diag::warn_drv_preprocessed_input_file_unused) | |||
3577 | << InputArg->getAsString(Args) << !!FinalPhaseArg | |||
3578 | << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""); | |||
3579 | else | |||
3580 | Diag(clang::diag::warn_drv_input_file_unused) | |||
3581 | << InputArg->getAsString(Args) << getPhaseName(InitialPhase) | |||
3582 | << !!FinalPhaseArg | |||
3583 | << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""); | |||
3584 | continue; | |||
3585 | } | |||
3586 | ||||
3587 | if (YcArg) { | |||
3588 | // Add a separate precompile phase for the compile phase. | |||
3589 | if (FinalPhase >= phases::Compile) { | |||
3590 | const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType); | |||
3591 | // Build the pipeline for the pch file. | |||
3592 | Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType); | |||
3593 | for (phases::ID Phase : types::getCompilationPhases(HeaderType)) | |||
3594 | ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch); | |||
3595 | assert(ClangClPch)(static_cast <bool> (ClangClPch) ? void (0) : __assert_fail ("ClangClPch", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3595, __extension__ __PRETTY_FUNCTION__)); | |||
3596 | Actions.push_back(ClangClPch); | |||
3597 | // The driver currently exits after the first failed command. This | |||
3598 | // relies on that behavior, to make sure if the pch generation fails, | |||
3599 | // the main compilation won't run. | |||
3600 | // FIXME: If the main compilation fails, the PCH generation should | |||
3601 | // probably not be considered successful either. | |||
3602 | } | |||
3603 | } | |||
3604 | } | |||
3605 | ||||
3606 | // If we are linking, claim any options which are obviously only used for | |||
3607 | // compilation. | |||
3608 | // FIXME: Understand why the last Phase List length is used here. | |||
3609 | if (FinalPhase == phases::Link && LastPLSize == 1) { | |||
3610 | Args.ClaimAllArgs(options::OPT_CompileOnly_Group); | |||
3611 | Args.ClaimAllArgs(options::OPT_cl_compile_Group); | |||
3612 | } | |||
3613 | } | |||
3614 | ||||
3615 | void Driver::BuildActions(Compilation &C, DerivedArgList &Args, | |||
3616 | const InputList &Inputs, ActionList &Actions) const { | |||
3617 | llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); | |||
3618 | ||||
3619 | if (!SuppressMissingInputWarning && Inputs.empty()) { | |||
| ||||
3620 | Diag(clang::diag::err_drv_no_input_files); | |||
3621 | return; | |||
3622 | } | |||
3623 | ||||
3624 | // Reject -Z* at the top level, these options should never have been exposed | |||
3625 | // by gcc. | |||
3626 | if (Arg *A = Args.getLastArg(options::OPT_Z_Joined)) | |||
3627 | Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args); | |||
3628 | ||||
3629 | // Diagnose misuse of /Fo. | |||
3630 | if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) { | |||
3631 | StringRef V = A->getValue(); | |||
3632 | if (Inputs.size() > 1 && !V.empty() && | |||
3633 | !llvm::sys::path::is_separator(V.back())) { | |||
3634 | // Check whether /Fo tries to name an output file for multiple inputs. | |||
3635 | Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) | |||
3636 | << A->getSpelling() << V; | |||
3637 | Args.eraseArg(options::OPT__SLASH_Fo); | |||
3638 | } | |||
3639 | } | |||
3640 | ||||
3641 | // Diagnose misuse of /Fa. | |||
3642 | if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) { | |||
3643 | StringRef V = A->getValue(); | |||
3644 | if (Inputs.size() > 1 && !V.empty() && | |||
3645 | !llvm::sys::path::is_separator(V.back())) { | |||
3646 | // Check whether /Fa tries to name an asm file for multiple inputs. | |||
3647 | Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) | |||
3648 | << A->getSpelling() << V; | |||
3649 | Args.eraseArg(options::OPT__SLASH_Fa); | |||
3650 | } | |||
3651 | } | |||
3652 | ||||
3653 | // Diagnose misuse of /o. | |||
3654 | if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) { | |||
3655 | if (A->getValue()[0] == '\0') { | |||
3656 | // It has to have a value. | |||
3657 | Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; | |||
3658 | Args.eraseArg(options::OPT__SLASH_o); | |||
3659 | } | |||
3660 | } | |||
3661 | ||||
3662 | handleArguments(C, Args, Inputs, Actions); | |||
3663 | ||||
3664 | // Builder to be used to build offloading actions. | |||
3665 | OffloadingActionBuilder OffloadBuilder(C, Args, Inputs); | |||
3666 | ||||
3667 | // Construct the actions to perform. | |||
3668 | HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; | |||
3669 | ActionList LinkerInputs; | |||
3670 | ActionList MergerInputs; | |||
3671 | ||||
3672 | for (auto &I : Inputs) { | |||
3673 | types::ID InputType = I.first; | |||
3674 | const Arg *InputArg = I.second; | |||
3675 | ||||
3676 | auto PL = types::getCompilationPhases(*this, Args, InputType); | |||
3677 | if (PL.empty()) | |||
3678 | continue; | |||
3679 | ||||
3680 | auto FullPL = types::getCompilationPhases(InputType); | |||
3681 | ||||
3682 | // Build the pipeline for this file. | |||
3683 | Action *Current = C.MakeAction<InputAction>(*InputArg, InputType); | |||
3684 | ||||
3685 | // Use the current host action in any of the offloading actions, if | |||
3686 | // required. | |||
3687 | if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg)) | |||
3688 | break; | |||
3689 | ||||
3690 | for (phases::ID Phase : PL) { | |||
3691 | ||||
3692 | // Add any offload action the host action depends on. | |||
3693 | Current = OffloadBuilder.addDeviceDependencesToHostAction( | |||
3694 | Current, InputArg, Phase, PL.back(), FullPL); | |||
3695 | if (!Current) | |||
3696 | break; | |||
3697 | ||||
3698 | // Queue linker inputs. | |||
3699 | if (Phase == phases::Link) { | |||
3700 | assert(Phase == PL.back() && "linking must be final compilation step.")(static_cast <bool> (Phase == PL.back() && "linking must be final compilation step." ) ? void (0) : __assert_fail ("Phase == PL.back() && \"linking must be final compilation step.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3700, __extension__ __PRETTY_FUNCTION__)); | |||
3701 | LinkerInputs.push_back(Current); | |||
3702 | Current = nullptr; | |||
3703 | break; | |||
3704 | } | |||
3705 | ||||
3706 | // TODO: Consider removing this because the merged may not end up being | |||
3707 | // the final Phase in the pipeline. Perhaps the merged could just merge | |||
3708 | // and then pass an artifact of some sort to the Link Phase. | |||
3709 | // Queue merger inputs. | |||
3710 | if (Phase == phases::IfsMerge) { | |||
3711 | assert(Phase == PL.back() && "merging must be final compilation step.")(static_cast <bool> (Phase == PL.back() && "merging must be final compilation step." ) ? void (0) : __assert_fail ("Phase == PL.back() && \"merging must be final compilation step.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3711, __extension__ __PRETTY_FUNCTION__)); | |||
3712 | MergerInputs.push_back(Current); | |||
3713 | Current = nullptr; | |||
3714 | break; | |||
3715 | } | |||
3716 | ||||
3717 | // Each precompiled header file after a module file action is a module | |||
3718 | // header of that same module file, rather than being compiled to a | |||
3719 | // separate PCH. | |||
3720 | if (Phase == phases::Precompile && HeaderModuleAction && | |||
3721 | getPrecompiledType(InputType) == types::TY_PCH) { | |||
3722 | HeaderModuleAction->addModuleHeaderInput(Current); | |||
3723 | Current = nullptr; | |||
3724 | break; | |||
3725 | } | |||
3726 | ||||
3727 | // FIXME: Should we include any prior module file outputs as inputs of | |||
3728 | // later actions in the same command line? | |||
3729 | ||||
3730 | // Otherwise construct the appropriate action. | |||
3731 | Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current); | |||
3732 | ||||
3733 | // We didn't create a new action, so we will just move to the next phase. | |||
3734 | if (NewCurrent == Current) | |||
3735 | continue; | |||
3736 | ||||
3737 | if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent)) | |||
3738 | HeaderModuleAction = HMA; | |||
3739 | ||||
3740 | Current = NewCurrent; | |||
3741 | ||||
3742 | // Use the current host action in any of the offloading actions, if | |||
3743 | // required. | |||
3744 | if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg)) | |||
3745 | break; | |||
3746 | ||||
3747 | if (Current->getType() == types::TY_Nothing) | |||
3748 | break; | |||
3749 | } | |||
3750 | ||||
3751 | // If we ended with something, add to the output list. | |||
3752 | if (Current) | |||
3753 | Actions.push_back(Current); | |||
3754 | ||||
3755 | // Add any top level actions generated for offloading. | |||
3756 | OffloadBuilder.appendTopLevelActions(Actions, Current, InputArg); | |||
3757 | } | |||
3758 | ||||
3759 | // Add a link action if necessary. | |||
3760 | if (!LinkerInputs.empty()) { | |||
3761 | if (Action *Wrapper = OffloadBuilder.makeHostLinkAction()) | |||
3762 | LinkerInputs.push_back(Wrapper); | |||
3763 | Action *LA; | |||
3764 | // Check if this Linker Job should emit a static library. | |||
3765 | if (ShouldEmitStaticLibrary(Args)) { | |||
3766 | LA = C.MakeAction<StaticLibJobAction>(LinkerInputs, types::TY_Image); | |||
3767 | } else { | |||
3768 | LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image); | |||
3769 | } | |||
3770 | LA = OffloadBuilder.processHostLinkAction(LA); | |||
3771 | Actions.push_back(LA); | |||
3772 | } | |||
3773 | ||||
3774 | // Add an interface stubs merge action if necessary. | |||
3775 | if (!MergerInputs.empty()) | |||
3776 | Actions.push_back( | |||
3777 | C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image)); | |||
3778 | ||||
3779 | if (Args.hasArg(options::OPT_emit_interface_stubs)) { | |||
3780 | auto PhaseList = types::getCompilationPhases( | |||
3781 | types::TY_IFS_CPP, | |||
3782 | Args.hasArg(options::OPT_c) ? phases::Compile : phases::LastPhase); | |||
3783 | ||||
3784 | ActionList MergerInputs; | |||
3785 | ||||
3786 | for (auto &I : Inputs) { | |||
3787 | types::ID InputType = I.first; | |||
3788 | const Arg *InputArg = I.second; | |||
3789 | ||||
3790 | // Currently clang and the llvm assembler do not support generating symbol | |||
3791 | // stubs from assembly, so we skip the input on asm files. For ifs files | |||
3792 | // we rely on the normal pipeline setup in the pipeline setup code above. | |||
3793 | if (InputType == types::TY_IFS || InputType == types::TY_PP_Asm || | |||
3794 | InputType == types::TY_Asm) | |||
3795 | continue; | |||
3796 | ||||
3797 | Action *Current = C.MakeAction<InputAction>(*InputArg, InputType); | |||
3798 | ||||
3799 | for (auto Phase : PhaseList) { | |||
3800 | switch (Phase) { | |||
3801 | default: | |||
3802 | llvm_unreachable(::llvm::llvm_unreachable_internal("IFS Pipeline can only consist of Compile followed by IfsMerge." , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3803) | |||
3803 | "IFS Pipeline can only consist of Compile followed by IfsMerge.")::llvm::llvm_unreachable_internal("IFS Pipeline can only consist of Compile followed by IfsMerge." , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3803); | |||
3804 | case phases::Compile: { | |||
3805 | // Only IfsMerge (llvm-ifs) can handle .o files by looking for ifs | |||
3806 | // files where the .o file is located. The compile action can not | |||
3807 | // handle this. | |||
3808 | if (InputType == types::TY_Object) | |||
3809 | break; | |||
3810 | ||||
3811 | Current = C.MakeAction<CompileJobAction>(Current, types::TY_IFS_CPP); | |||
3812 | break; | |||
3813 | } | |||
3814 | case phases::IfsMerge: { | |||
3815 | assert(Phase == PhaseList.back() &&(static_cast <bool> (Phase == PhaseList.back() && "merging must be final compilation step.") ? void (0) : __assert_fail ("Phase == PhaseList.back() && \"merging must be final compilation step.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3816, __extension__ __PRETTY_FUNCTION__)) | |||
3816 | "merging must be final compilation step.")(static_cast <bool> (Phase == PhaseList.back() && "merging must be final compilation step.") ? void (0) : __assert_fail ("Phase == PhaseList.back() && \"merging must be final compilation step.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3816, __extension__ __PRETTY_FUNCTION__)); | |||
3817 | MergerInputs.push_back(Current); | |||
3818 | Current = nullptr; | |||
3819 | break; | |||
3820 | } | |||
3821 | } | |||
3822 | } | |||
3823 | ||||
3824 | // If we ended with something, add to the output list. | |||
3825 | if (Current) | |||
3826 | Actions.push_back(Current); | |||
3827 | } | |||
3828 | ||||
3829 | // Add an interface stubs merge action if necessary. | |||
3830 | if (!MergerInputs.empty()) | |||
3831 | Actions.push_back( | |||
3832 | C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image)); | |||
3833 | } | |||
3834 | ||||
3835 | // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom | |||
3836 | // Compile phase that prints out supported cpu models and quits. | |||
3837 | if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) { | |||
3838 | // Use the -mcpu=? flag as the dummy input to cc1. | |||
3839 | Actions.clear(); | |||
3840 | Action *InputAc = C.MakeAction<InputAction>(*A, types::TY_C); | |||
3841 | Actions.push_back( | |||
3842 | C.MakeAction<PrecompileJobAction>(InputAc, types::TY_Nothing)); | |||
3843 | for (auto &I : Inputs) | |||
3844 | I.second->claim(); | |||
3845 | } | |||
3846 | ||||
3847 | // Claim ignored clang-cl options. | |||
3848 | Args.ClaimAllArgs(options::OPT_cl_ignored_Group); | |||
3849 | ||||
3850 | // Claim --cuda-host-only and --cuda-compile-host-device, which may be passed | |||
3851 | // to non-CUDA compilations and should not trigger warnings there. | |||
3852 | Args.ClaimAllArgs(options::OPT_cuda_host_only); | |||
3853 | Args.ClaimAllArgs(options::OPT_cuda_compile_host_device); | |||
3854 | } | |||
3855 | ||||
3856 | Action *Driver::ConstructPhaseAction( | |||
3857 | Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input, | |||
3858 | Action::OffloadKind TargetDeviceOffloadKind) const { | |||
3859 | llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); | |||
3860 | ||||
3861 | // Some types skip the assembler phase (e.g., llvm-bc), but we can't | |||
3862 | // encode this in the steps because the intermediate type depends on | |||
3863 | // arguments. Just special case here. | |||
3864 | if (Phase == phases::Assemble && Input->getType() != types::TY_PP_Asm) | |||
3865 | return Input; | |||
3866 | ||||
3867 | // Build the appropriate action. | |||
3868 | switch (Phase) { | |||
3869 | case phases::Link: | |||
3870 | llvm_unreachable("link action invalid here.")::llvm::llvm_unreachable_internal("link action invalid here." , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3870); | |||
3871 | case phases::IfsMerge: | |||
3872 | llvm_unreachable("ifsmerge action invalid here.")::llvm::llvm_unreachable_internal("ifsmerge action invalid here." , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3872); | |||
3873 | case phases::Preprocess: { | |||
3874 | types::ID OutputTy; | |||
3875 | // -M and -MM specify the dependency file name by altering the output type, | |||
3876 | // -if -MD and -MMD are not specified. | |||
3877 | if (Args.hasArg(options::OPT_M, options::OPT_MM) && | |||
3878 | !Args.hasArg(options::OPT_MD, options::OPT_MMD)) { | |||
3879 | OutputTy = types::TY_Dependencies; | |||
3880 | } else { | |||
3881 | OutputTy = Input->getType(); | |||
3882 | if (!Args.hasFlag(options::OPT_frewrite_includes, | |||
3883 | options::OPT_fno_rewrite_includes, false) && | |||
3884 | !Args.hasFlag(options::OPT_frewrite_imports, | |||
3885 | options::OPT_fno_rewrite_imports, false) && | |||
3886 | !CCGenDiagnostics) | |||
3887 | OutputTy = types::getPreprocessedType(OutputTy); | |||
3888 | assert(OutputTy != types::TY_INVALID &&(static_cast <bool> (OutputTy != types::TY_INVALID && "Cannot preprocess this input type!") ? void (0) : __assert_fail ("OutputTy != types::TY_INVALID && \"Cannot preprocess this input type!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3889, __extension__ __PRETTY_FUNCTION__)) | |||
3889 | "Cannot preprocess this input type!")(static_cast <bool> (OutputTy != types::TY_INVALID && "Cannot preprocess this input type!") ? void (0) : __assert_fail ("OutputTy != types::TY_INVALID && \"Cannot preprocess this input type!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3889, __extension__ __PRETTY_FUNCTION__)); | |||
3890 | } | |||
3891 | return C.MakeAction<PreprocessJobAction>(Input, OutputTy); | |||
3892 | } | |||
3893 | case phases::Precompile: { | |||
3894 | types::ID OutputTy = getPrecompiledType(Input->getType()); | |||
3895 | assert(OutputTy != types::TY_INVALID &&(static_cast <bool> (OutputTy != types::TY_INVALID && "Cannot precompile this input type!") ? void (0) : __assert_fail ("OutputTy != types::TY_INVALID && \"Cannot precompile this input type!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3896, __extension__ __PRETTY_FUNCTION__)) | |||
3896 | "Cannot precompile this input type!")(static_cast <bool> (OutputTy != types::TY_INVALID && "Cannot precompile this input type!") ? void (0) : __assert_fail ("OutputTy != types::TY_INVALID && \"Cannot precompile this input type!\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3896, __extension__ __PRETTY_FUNCTION__)); | |||
3897 | ||||
3898 | // If we're given a module name, precompile header file inputs as a | |||
3899 | // module, not as a precompiled header. | |||
3900 | const char *ModName = nullptr; | |||
3901 | if (OutputTy == types::TY_PCH) { | |||
3902 | if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ)) | |||
3903 | ModName = A->getValue(); | |||
3904 | if (ModName) | |||
3905 | OutputTy = types::TY_ModuleFile; | |||
3906 | } | |||
3907 | ||||
3908 | if (Args.hasArg(options::OPT_fsyntax_only)) { | |||
3909 | // Syntax checks should not emit a PCH file | |||
3910 | OutputTy = types::TY_Nothing; | |||
3911 | } | |||
3912 | ||||
3913 | if (ModName) | |||
3914 | return C.MakeAction<HeaderModulePrecompileJobAction>(Input, OutputTy, | |||
3915 | ModName); | |||
3916 | return C.MakeAction<PrecompileJobAction>(Input, OutputTy); | |||
3917 | } | |||
3918 | case phases::Compile: { | |||
3919 | if (Args.hasArg(options::OPT_fsyntax_only)) | |||
3920 | return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing); | |||
3921 | if (Args.hasArg(options::OPT_rewrite_objc)) | |||
3922 | return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC); | |||
3923 | if (Args.hasArg(options::OPT_rewrite_legacy_objc)) | |||
3924 | return C.MakeAction<CompileJobAction>(Input, | |||
3925 | types::TY_RewrittenLegacyObjC); | |||
3926 | if (Args.hasArg(options::OPT__analyze)) | |||
3927 | return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist); | |||
3928 | if (Args.hasArg(options::OPT__migrate)) | |||
3929 | return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap); | |||
3930 | if (Args.hasArg(options::OPT_emit_ast)) | |||
3931 | return C.MakeAction<CompileJobAction>(Input, types::TY_AST); | |||
3932 | if (Args.hasArg(options::OPT_module_file_info)) | |||
3933 | return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile); | |||
3934 | if (Args.hasArg(options::OPT_verify_pch)) | |||
3935 | return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing); | |||
3936 | return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC); | |||
3937 | } | |||
3938 | case phases::Backend: { | |||
3939 | if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) { | |||
3940 | types::ID Output = | |||
3941 | Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; | |||
3942 | return C.MakeAction<BackendJobAction>(Input, Output); | |||
3943 | } | |||
3944 | if (Args.hasArg(options::OPT_emit_llvm) || | |||
3945 | (TargetDeviceOffloadKind == Action::OFK_HIP && | |||
3946 | Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, | |||
3947 | false))) { | |||
3948 | types::ID Output = | |||
3949 | Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC; | |||
3950 | return C.MakeAction<BackendJobAction>(Input, Output); | |||
3951 | } | |||
3952 | return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm); | |||
3953 | } | |||
3954 | case phases::Assemble: | |||
3955 | return C.MakeAction<AssembleJobAction>(std::move(Input), types::TY_Object); | |||
3956 | } | |||
3957 | ||||
3958 | llvm_unreachable("invalid phase in ConstructPhaseAction")::llvm::llvm_unreachable_internal("invalid phase in ConstructPhaseAction" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 3958); | |||
3959 | } | |||
3960 | ||||
3961 | void Driver::BuildJobs(Compilation &C) const { | |||
3962 | llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); | |||
3963 | ||||
3964 | Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); | |||
3965 | ||||
3966 | // It is an error to provide a -o option if we are making multiple output | |||
3967 | // files. There are exceptions: | |||
3968 | // | |||
3969 | // IfsMergeJob: when generating interface stubs enabled we want to be able to | |||
3970 | // generate the stub file at the same time that we generate the real | |||
3971 | // library/a.out. So when a .o, .so, etc are the output, with clang interface | |||
3972 | // stubs there will also be a .ifs and .ifso at the same location. | |||
3973 | // | |||
3974 | // CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled | |||
3975 | // and -c is passed, we still want to be able to generate a .ifs file while | |||
3976 | // we are also generating .o files. So we allow more than one output file in | |||
3977 | // this case as well. | |||
3978 | // | |||
3979 | if (FinalOutput) { | |||
3980 | unsigned NumOutputs = 0; | |||
3981 | unsigned NumIfsOutputs = 0; | |||
3982 | for (const Action *A : C.getActions()) | |||
3983 | if (A->getType() != types::TY_Nothing && | |||
3984 | !(A->getKind() == Action::IfsMergeJobClass || | |||
3985 | (A->getType() == clang::driver::types::TY_IFS_CPP && | |||
3986 | A->getKind() == clang::driver::Action::CompileJobClass && | |||
3987 | 0 == NumIfsOutputs++) || | |||
3988 | (A->getKind() == Action::BindArchClass && A->getInputs().size() && | |||
3989 | A->getInputs().front()->getKind() == Action::IfsMergeJobClass))) | |||
3990 | ++NumOutputs; | |||
3991 | ||||
3992 | if (NumOutputs > 1) { | |||
3993 | Diag(clang::diag::err_drv_output_argument_with_multiple_files); | |||
3994 | FinalOutput = nullptr; | |||
3995 | } | |||
3996 | } | |||
3997 | ||||
3998 | const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple(); | |||
3999 | if (RawTriple.isOSAIX()) { | |||
4000 | if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) | |||
4001 | Diag(diag::err_drv_unsupported_opt_for_target) | |||
4002 | << A->getSpelling() << RawTriple.str(); | |||
4003 | if (LTOMode == LTOK_Thin) | |||
4004 | Diag(diag::err_drv_clang_unsupported) << "thinLTO on AIX"; | |||
4005 | } | |||
4006 | ||||
4007 | // Collect the list of architectures. | |||
4008 | llvm::StringSet<> ArchNames; | |||
4009 | if (RawTriple.isOSBinFormatMachO()) | |||
4010 | for (const Arg *A : C.getArgs()) | |||
4011 | if (A->getOption().matches(options::OPT_arch)) | |||
4012 | ArchNames.insert(A->getValue()); | |||
4013 | ||||
4014 | // Set of (Action, canonical ToolChain triple) pairs we've built jobs for. | |||
4015 | std::map<std::pair<const Action *, std::string>, InputInfo> CachedResults; | |||
4016 | for (Action *A : C.getActions()) { | |||
4017 | // If we are linking an image for multiple archs then the linker wants | |||
4018 | // -arch_multiple and -final_output <final image name>. Unfortunately, this | |||
4019 | // doesn't fit in cleanly because we have to pass this information down. | |||
4020 | // | |||
4021 | // FIXME: This is a hack; find a cleaner way to integrate this into the | |||
4022 | // process. | |||
4023 | const char *LinkingOutput = nullptr; | |||
4024 | if (isa<LipoJobAction>(A)) { | |||
4025 | if (FinalOutput) | |||
4026 | LinkingOutput = FinalOutput->getValue(); | |||
4027 | else | |||
4028 | LinkingOutput = getDefaultImageName(); | |||
4029 | } | |||
4030 | ||||
4031 | BuildJobsForAction(C, A, &C.getDefaultToolChain(), | |||
4032 | /*BoundArch*/ StringRef(), | |||
4033 | /*AtTopLevel*/ true, | |||
4034 | /*MultipleArchs*/ ArchNames.size() > 1, | |||
4035 | /*LinkingOutput*/ LinkingOutput, CachedResults, | |||
4036 | /*TargetDeviceOffloadKind*/ Action::OFK_None); | |||
4037 | } | |||
4038 | ||||
4039 | // If we have more than one job, then disable integrated-cc1 for now. Do this | |||
4040 | // also when we need to report process execution statistics. | |||
4041 | if (C.getJobs().size() > 1 || CCPrintProcessStats) | |||
4042 | for (auto &J : C.getJobs()) | |||
4043 | J.InProcess = false; | |||
4044 | ||||
4045 | if (CCPrintProcessStats) { | |||
4046 | C.setPostCallback([=](const Command &Cmd, int Res) { | |||
4047 | Optional<llvm::sys::ProcessStatistics> ProcStat = | |||
4048 | Cmd.getProcessStatistics(); | |||
4049 | if (!ProcStat) | |||
4050 | return; | |||
4051 | ||||
4052 | const char *LinkingOutput = nullptr; | |||
4053 | if (FinalOutput) | |||
4054 | LinkingOutput = FinalOutput->getValue(); | |||
4055 | else if (!Cmd.getOutputFilenames().empty()) | |||
4056 | LinkingOutput = Cmd.getOutputFilenames().front().c_str(); | |||
4057 | else | |||
4058 | LinkingOutput = getDefaultImageName(); | |||
4059 | ||||
4060 | if (CCPrintStatReportFilename.empty()) { | |||
4061 | using namespace llvm; | |||
4062 | // Human readable output. | |||
4063 | outs() << sys::path::filename(Cmd.getExecutable()) << ": " | |||
4064 | << "output=" << LinkingOutput; | |||
4065 | outs() << ", total=" | |||
4066 | << format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms" | |||
4067 | << ", user=" | |||
4068 | << format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms" | |||
4069 | << ", mem=" << ProcStat->PeakMemory << " Kb\n"; | |||
4070 | } else { | |||
4071 | // CSV format. | |||
4072 | std::string Buffer; | |||
4073 | llvm::raw_string_ostream Out(Buffer); | |||
4074 | llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()), | |||
4075 | /*Quote*/ true); | |||
4076 | Out << ','; | |||
4077 | llvm::sys::printArg(Out, LinkingOutput, true); | |||
4078 | Out << ',' << ProcStat->TotalTime.count() << ',' | |||
4079 | << ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory | |||
4080 | << '\n'; | |||
4081 | Out.flush(); | |||
4082 | std::error_code EC; | |||
4083 | llvm::raw_fd_ostream OS(CCPrintStatReportFilename.c_str(), EC, | |||
4084 | llvm::sys::fs::OF_Append | | |||
4085 | llvm::sys::fs::OF_Text); | |||
4086 | if (EC) | |||
4087 | return; | |||
4088 | auto L = OS.lock(); | |||
4089 | if (!L) { | |||
4090 | llvm::errs() << "ERROR: Cannot lock file " | |||
4091 | << CCPrintStatReportFilename << ": " | |||
4092 | << toString(L.takeError()) << "\n"; | |||
4093 | return; | |||
4094 | } | |||
4095 | OS << Buffer; | |||
4096 | OS.flush(); | |||
4097 | } | |||
4098 | }); | |||
4099 | } | |||
4100 | ||||
4101 | // If the user passed -Qunused-arguments or there were errors, don't warn | |||
4102 | // about any unused arguments. | |||
4103 | if (Diags.hasErrorOccurred() || | |||
4104 | C.getArgs().hasArg(options::OPT_Qunused_arguments)) | |||
4105 | return; | |||
4106 | ||||
4107 | // Claim -### here. | |||
4108 | (void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); | |||
4109 | ||||
4110 | // Claim --driver-mode, --rsp-quoting, it was handled earlier. | |||
4111 | (void)C.getArgs().hasArg(options::OPT_driver_mode); | |||
4112 | (void)C.getArgs().hasArg(options::OPT_rsp_quoting); | |||
4113 | ||||
4114 | for (Arg *A : C.getArgs()) { | |||
4115 | // FIXME: It would be nice to be able to send the argument to the | |||
4116 | // DiagnosticsEngine, so that extra values, position, and so on could be | |||
4117 | // printed. | |||
4118 | if (!A->isClaimed()) { | |||
4119 | if (A->getOption().hasFlag(options::NoArgumentUnused)) | |||
4120 | continue; | |||
4121 | ||||
4122 | // Suppress the warning automatically if this is just a flag, and it is an | |||
4123 | // instance of an argument we already claimed. | |||
4124 | const Option &Opt = A->getOption(); | |||
4125 | if (Opt.getKind() == Option::FlagClass) { | |||
4126 | bool DuplicateClaimed = false; | |||
4127 | ||||
4128 | for (const Arg *AA : C.getArgs().filtered(&Opt)) { | |||
4129 | if (AA->isClaimed()) { | |||
4130 | DuplicateClaimed = true; | |||
4131 | break; | |||
4132 | } | |||
4133 | } | |||
4134 | ||||
4135 | if (DuplicateClaimed) | |||
4136 | continue; | |||
4137 | } | |||
4138 | ||||
4139 | // In clang-cl, don't mention unknown arguments here since they have | |||
4140 | // already been warned about. | |||
4141 | if (!IsCLMode() || !A->getOption().matches(options::OPT_UNKNOWN)) | |||
4142 | Diag(clang::diag::warn_drv_unused_argument) | |||
4143 | << A->getAsString(C.getArgs()); | |||
4144 | } | |||
4145 | } | |||
4146 | } | |||
4147 | ||||
4148 | namespace { | |||
4149 | /// Utility class to control the collapse of dependent actions and select the | |||
4150 | /// tools accordingly. | |||
4151 | class ToolSelector final { | |||
4152 | /// The tool chain this selector refers to. | |||
4153 | const ToolChain &TC; | |||
4154 | ||||
4155 | /// The compilation this selector refers to. | |||
4156 | const Compilation &C; | |||
4157 | ||||
4158 | /// The base action this selector refers to. | |||
4159 | const JobAction *BaseAction; | |||
4160 | ||||
4161 | /// Set to true if the current toolchain refers to host actions. | |||
4162 | bool IsHostSelector; | |||
4163 | ||||
4164 | /// Set to true if save-temps and embed-bitcode functionalities are active. | |||
4165 | bool SaveTemps; | |||
4166 | bool EmbedBitcode; | |||
4167 | ||||
4168 | /// Get previous dependent action or null if that does not exist. If | |||
4169 | /// \a CanBeCollapsed is false, that action must be legal to collapse or | |||
4170 | /// null will be returned. | |||
4171 | const JobAction *getPrevDependentAction(const ActionList &Inputs, | |||
4172 | ActionList &SavedOffloadAction, | |||
4173 | bool CanBeCollapsed = true) { | |||
4174 | // An option can be collapsed only if it has a single input. | |||
4175 | if (Inputs.size() != 1) | |||
4176 | return nullptr; | |||
4177 | ||||
4178 | Action *CurAction = *Inputs.begin(); | |||
4179 | if (CanBeCollapsed && | |||
4180 | !CurAction->isCollapsingWithNextDependentActionLegal()) | |||
4181 | return nullptr; | |||
4182 | ||||
4183 | // If the input action is an offload action. Look through it and save any | |||
4184 | // offload action that can be dropped in the event of a collapse. | |||
4185 | if (auto *OA = dyn_cast<OffloadAction>(CurAction)) { | |||
4186 | // If the dependent action is a device action, we will attempt to collapse | |||
4187 | // only with other device actions. Otherwise, we would do the same but | |||
4188 | // with host actions only. | |||
4189 | if (!IsHostSelector) { | |||
4190 | if (OA->hasSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)) { | |||
4191 | CurAction = | |||
4192 | OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true); | |||
4193 | if (CanBeCollapsed && | |||
4194 | !CurAction->isCollapsingWithNextDependentActionLegal()) | |||
4195 | return nullptr; | |||
4196 | SavedOffloadAction.push_back(OA); | |||
4197 | return dyn_cast<JobAction>(CurAction); | |||
4198 | } | |||
4199 | } else if (OA->hasHostDependence()) { | |||
4200 | CurAction = OA->getHostDependence(); | |||
4201 | if (CanBeCollapsed && | |||
4202 | !CurAction->isCollapsingWithNextDependentActionLegal()) | |||
4203 | return nullptr; | |||
4204 | SavedOffloadAction.push_back(OA); | |||
4205 | return dyn_cast<JobAction>(CurAction); | |||
4206 | } | |||
4207 | return nullptr; | |||
4208 | } | |||
4209 | ||||
4210 | return dyn_cast<JobAction>(CurAction); | |||
4211 | } | |||
4212 | ||||
4213 | /// Return true if an assemble action can be collapsed. | |||
4214 | bool canCollapseAssembleAction() const { | |||
4215 | return TC.useIntegratedAs() && !SaveTemps && | |||
4216 | !C.getArgs().hasArg(options::OPT_via_file_asm) && | |||
4217 | !C.getArgs().hasArg(options::OPT__SLASH_FA) && | |||
4218 | !C.getArgs().hasArg(options::OPT__SLASH_Fa); | |||
4219 | } | |||
4220 | ||||
4221 | /// Return true if a preprocessor action can be collapsed. | |||
4222 | bool canCollapsePreprocessorAction() const { | |||
4223 | return !C.getArgs().hasArg(options::OPT_no_integrated_cpp) && | |||
4224 | !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps && | |||
4225 | !C.getArgs().hasArg(options::OPT_rewrite_objc); | |||
4226 | } | |||
4227 | ||||
4228 | /// Struct that relates an action with the offload actions that would be | |||
4229 | /// collapsed with it. | |||
4230 | struct JobActionInfo final { | |||
4231 | /// The action this info refers to. | |||
4232 | const JobAction *JA = nullptr; | |||
4233 | /// The offload actions we need to take care off if this action is | |||
4234 | /// collapsed. | |||
4235 | ActionList SavedOffloadAction; | |||
4236 | }; | |||
4237 | ||||
4238 | /// Append collapsed offload actions from the give nnumber of elements in the | |||
4239 | /// action info array. | |||
4240 | static void AppendCollapsedOffloadAction(ActionList &CollapsedOffloadAction, | |||
4241 | ArrayRef<JobActionInfo> &ActionInfo, | |||
4242 | unsigned ElementNum) { | |||
4243 | assert(ElementNum <= ActionInfo.size() && "Invalid number of elements.")(static_cast <bool> (ElementNum <= ActionInfo.size() && "Invalid number of elements.") ? void (0) : __assert_fail ("ElementNum <= ActionInfo.size() && \"Invalid number of elements.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4243, __extension__ __PRETTY_FUNCTION__)); | |||
4244 | for (unsigned I = 0; I < ElementNum; ++I) | |||
4245 | CollapsedOffloadAction.append(ActionInfo[I].SavedOffloadAction.begin(), | |||
4246 | ActionInfo[I].SavedOffloadAction.end()); | |||
4247 | } | |||
4248 | ||||
4249 | /// Functions that attempt to perform the combining. They detect if that is | |||
4250 | /// legal, and if so they update the inputs \a Inputs and the offload action | |||
4251 | /// that were collapsed in \a CollapsedOffloadAction. A tool that deals with | |||
4252 | /// the combined action is returned. If the combining is not legal or if the | |||
4253 | /// tool does not exist, null is returned. | |||
4254 | /// Currently three kinds of collapsing are supported: | |||
4255 | /// - Assemble + Backend + Compile; | |||
4256 | /// - Assemble + Backend ; | |||
4257 | /// - Backend + Compile. | |||
4258 | const Tool * | |||
4259 | combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo, | |||
4260 | ActionList &Inputs, | |||
4261 | ActionList &CollapsedOffloadAction) { | |||
4262 | if (ActionInfo.size() < 3 || !canCollapseAssembleAction()) | |||
4263 | return nullptr; | |||
4264 | auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA); | |||
4265 | auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA); | |||
4266 | auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[2].JA); | |||
4267 | if (!AJ || !BJ || !CJ) | |||
4268 | return nullptr; | |||
4269 | ||||
4270 | // Get compiler tool. | |||
4271 | const Tool *T = TC.SelectTool(*CJ); | |||
4272 | if (!T) | |||
4273 | return nullptr; | |||
4274 | ||||
4275 | // When using -fembed-bitcode, it is required to have the same tool (clang) | |||
4276 | // for both CompilerJA and BackendJA. Otherwise, combine two stages. | |||
4277 | if (EmbedBitcode) { | |||
4278 | const Tool *BT = TC.SelectTool(*BJ); | |||
4279 | if (BT == T) | |||
4280 | return nullptr; | |||
4281 | } | |||
4282 | ||||
4283 | if (!T->hasIntegratedAssembler()) | |||
4284 | return nullptr; | |||
4285 | ||||
4286 | Inputs = CJ->getInputs(); | |||
4287 | AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo, | |||
4288 | /*NumElements=*/3); | |||
4289 | return T; | |||
4290 | } | |||
4291 | const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo, | |||
4292 | ActionList &Inputs, | |||
4293 | ActionList &CollapsedOffloadAction) { | |||
4294 | if (ActionInfo.size() < 2 || !canCollapseAssembleAction()) | |||
4295 | return nullptr; | |||
4296 | auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA); | |||
4297 | auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA); | |||
4298 | if (!AJ || !BJ) | |||
4299 | return nullptr; | |||
4300 | ||||
4301 | // Get backend tool. | |||
4302 | const Tool *T = TC.SelectTool(*BJ); | |||
4303 | if (!T) | |||
4304 | return nullptr; | |||
4305 | ||||
4306 | if (!T->hasIntegratedAssembler()) | |||
4307 | return nullptr; | |||
4308 | ||||
4309 | Inputs = BJ->getInputs(); | |||
4310 | AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo, | |||
4311 | /*NumElements=*/2); | |||
4312 | return T; | |||
4313 | } | |||
4314 | const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo, | |||
4315 | ActionList &Inputs, | |||
4316 | ActionList &CollapsedOffloadAction) { | |||
4317 | if (ActionInfo.size() < 2) | |||
4318 | return nullptr; | |||
4319 | auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[0].JA); | |||
4320 | auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[1].JA); | |||
4321 | if (!BJ || !CJ) | |||
4322 | return nullptr; | |||
4323 | ||||
4324 | // Check if the initial input (to the compile job or its predessor if one | |||
4325 | // exists) is LLVM bitcode. In that case, no preprocessor step is required | |||
4326 | // and we can still collapse the compile and backend jobs when we have | |||
4327 | // -save-temps. I.e. there is no need for a separate compile job just to | |||
4328 | // emit unoptimized bitcode. | |||
4329 | bool InputIsBitcode = true; | |||
4330 | for (size_t i = 1; i < ActionInfo.size(); i++) | |||
4331 | if (ActionInfo[i].JA->getType() != types::TY_LLVM_BC && | |||
4332 | ActionInfo[i].JA->getType() != types::TY_LTO_BC) { | |||
4333 | InputIsBitcode = false; | |||
4334 | break; | |||
4335 | } | |||
4336 | if (!InputIsBitcode && !canCollapsePreprocessorAction()) | |||
4337 | return nullptr; | |||
4338 | ||||
4339 | // Get compiler tool. | |||
4340 | const Tool *T = TC.SelectTool(*CJ); | |||
4341 | if (!T) | |||
4342 | return nullptr; | |||
4343 | ||||
4344 | if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode)) | |||
4345 | return nullptr; | |||
4346 | ||||
4347 | Inputs = CJ->getInputs(); | |||
4348 | AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo, | |||
4349 | /*NumElements=*/2); | |||
4350 | return T; | |||
4351 | } | |||
4352 | ||||
4353 | /// Updates the inputs if the obtained tool supports combining with | |||
4354 | /// preprocessor action, and the current input is indeed a preprocessor | |||
4355 | /// action. If combining results in the collapse of offloading actions, those | |||
4356 | /// are appended to \a CollapsedOffloadAction. | |||
4357 | void combineWithPreprocessor(const Tool *T, ActionList &Inputs, | |||
4358 | ActionList &CollapsedOffloadAction) { | |||
4359 | if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP()) | |||
4360 | return; | |||
4361 | ||||
4362 | // Attempt to get a preprocessor action dependence. | |||
4363 | ActionList PreprocessJobOffloadActions; | |||
4364 | ActionList NewInputs; | |||
4365 | for (Action *A : Inputs) { | |||
4366 | auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions); | |||
4367 | if (!PJ || !isa<PreprocessJobAction>(PJ)) { | |||
4368 | NewInputs.push_back(A); | |||
4369 | continue; | |||
4370 | } | |||
4371 | ||||
4372 | // This is legal to combine. Append any offload action we found and add the | |||
4373 | // current input to preprocessor inputs. | |||
4374 | CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(), | |||
4375 | PreprocessJobOffloadActions.end()); | |||
4376 | NewInputs.append(PJ->input_begin(), PJ->input_end()); | |||
4377 | } | |||
4378 | Inputs = NewInputs; | |||
4379 | } | |||
4380 | ||||
4381 | public: | |||
4382 | ToolSelector(const JobAction *BaseAction, const ToolChain &TC, | |||
4383 | const Compilation &C, bool SaveTemps, bool EmbedBitcode) | |||
4384 | : TC(TC), C(C), BaseAction(BaseAction), SaveTemps(SaveTemps), | |||
4385 | EmbedBitcode(EmbedBitcode) { | |||
4386 | assert(BaseAction && "Invalid base action.")(static_cast <bool> (BaseAction && "Invalid base action." ) ? void (0) : __assert_fail ("BaseAction && \"Invalid base action.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4386, __extension__ __PRETTY_FUNCTION__)); | |||
4387 | IsHostSelector = BaseAction->getOffloadingDeviceKind() == Action::OFK_None; | |||
4388 | } | |||
4389 | ||||
4390 | /// Check if a chain of actions can be combined and return the tool that can | |||
4391 | /// handle the combination of actions. The pointer to the current inputs \a | |||
4392 | /// Inputs and the list of offload actions \a CollapsedOffloadActions | |||
4393 | /// connected to collapsed actions are updated accordingly. The latter enables | |||
4394 | /// the caller of the selector to process them afterwards instead of just | |||
4395 | /// dropping them. If no suitable tool is found, null will be returned. | |||
4396 | const Tool *getTool(ActionList &Inputs, | |||
4397 | ActionList &CollapsedOffloadAction) { | |||
4398 | // | |||
4399 | // Get the largest chain of actions that we could combine. | |||
4400 | // | |||
4401 | ||||
4402 | SmallVector<JobActionInfo, 5> ActionChain(1); | |||
4403 | ActionChain.back().JA = BaseAction; | |||
4404 | while (ActionChain.back().JA) { | |||
4405 | const Action *CurAction = ActionChain.back().JA; | |||
4406 | ||||
4407 | // Grow the chain by one element. | |||
4408 | ActionChain.resize(ActionChain.size() + 1); | |||
4409 | JobActionInfo &AI = ActionChain.back(); | |||
4410 | ||||
4411 | // Attempt to fill it with the | |||
4412 | AI.JA = | |||
4413 | getPrevDependentAction(CurAction->getInputs(), AI.SavedOffloadAction); | |||
4414 | } | |||
4415 | ||||
4416 | // Pop the last action info as it could not be filled. | |||
4417 | ActionChain.pop_back(); | |||
4418 | ||||
4419 | // | |||
4420 | // Attempt to combine actions. If all combining attempts failed, just return | |||
4421 | // the tool of the provided action. At the end we attempt to combine the | |||
4422 | // action with any preprocessor action it may depend on. | |||
4423 | // | |||
4424 | ||||
4425 | const Tool *T = combineAssembleBackendCompile(ActionChain, Inputs, | |||
4426 | CollapsedOffloadAction); | |||
4427 | if (!T) | |||
4428 | T = combineAssembleBackend(ActionChain, Inputs, CollapsedOffloadAction); | |||
4429 | if (!T) | |||
4430 | T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction); | |||
4431 | if (!T) { | |||
4432 | Inputs = BaseAction->getInputs(); | |||
4433 | T = TC.SelectTool(*BaseAction); | |||
4434 | } | |||
4435 | ||||
4436 | combineWithPreprocessor(T, Inputs, CollapsedOffloadAction); | |||
4437 | return T; | |||
4438 | } | |||
4439 | }; | |||
4440 | } | |||
4441 | ||||
4442 | /// Return a string that uniquely identifies the result of a job. The bound arch | |||
4443 | /// is not necessarily represented in the toolchain's triple -- for example, | |||
4444 | /// armv7 and armv7s both map to the same triple -- so we need both in our map. | |||
4445 | /// Also, we need to add the offloading device kind, as the same tool chain can | |||
4446 | /// be used for host and device for some programming models, e.g. OpenMP. | |||
4447 | static std::string GetTriplePlusArchString(const ToolChain *TC, | |||
4448 | StringRef BoundArch, | |||
4449 | Action::OffloadKind OffloadKind) { | |||
4450 | std::string TriplePlusArch = TC->getTriple().normalize(); | |||
4451 | if (!BoundArch.empty()) { | |||
4452 | TriplePlusArch += "-"; | |||
4453 | TriplePlusArch += BoundArch; | |||
4454 | } | |||
4455 | TriplePlusArch += "-"; | |||
4456 | TriplePlusArch += Action::GetOffloadKindName(OffloadKind); | |||
4457 | return TriplePlusArch; | |||
4458 | } | |||
4459 | ||||
4460 | InputInfo Driver::BuildJobsForAction( | |||
4461 | Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch, | |||
4462 | bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput, | |||
4463 | std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults, | |||
4464 | Action::OffloadKind TargetDeviceOffloadKind) const { | |||
4465 | std::pair<const Action *, std::string> ActionTC = { | |||
4466 | A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)}; | |||
4467 | auto CachedResult = CachedResults.find(ActionTC); | |||
4468 | if (CachedResult != CachedResults.end()) { | |||
4469 | return CachedResult->second; | |||
4470 | } | |||
4471 | InputInfo Result = BuildJobsForActionNoCache( | |||
4472 | C, A, TC, BoundArch, AtTopLevel, MultipleArchs, LinkingOutput, | |||
4473 | CachedResults, TargetDeviceOffloadKind); | |||
4474 | CachedResults[ActionTC] = Result; | |||
4475 | return Result; | |||
4476 | } | |||
4477 | ||||
4478 | InputInfo Driver::BuildJobsForActionNoCache( | |||
4479 | Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch, | |||
4480 | bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput, | |||
4481 | std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults, | |||
4482 | Action::OffloadKind TargetDeviceOffloadKind) const { | |||
4483 | llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); | |||
4484 | ||||
4485 | InputInfoList OffloadDependencesInputInfo; | |||
4486 | bool BuildingForOffloadDevice = TargetDeviceOffloadKind != Action::OFK_None; | |||
4487 | if (const OffloadAction *OA = dyn_cast<OffloadAction>(A)) { | |||
4488 | // The 'Darwin' toolchain is initialized only when its arguments are | |||
4489 | // computed. Get the default arguments for OFK_None to ensure that | |||
4490 | // initialization is performed before processing the offload action. | |||
4491 | // FIXME: Remove when darwin's toolchain is initialized during construction. | |||
4492 | C.getArgsForToolChain(TC, BoundArch, Action::OFK_None); | |||
4493 | ||||
4494 | // The offload action is expected to be used in four different situations. | |||
4495 | // | |||
4496 | // a) Set a toolchain/architecture/kind for a host action: | |||
4497 | // Host Action 1 -> OffloadAction -> Host Action 2 | |||
4498 | // | |||
4499 | // b) Set a toolchain/architecture/kind for a device action; | |||
4500 | // Device Action 1 -> OffloadAction -> Device Action 2 | |||
4501 | // | |||
4502 | // c) Specify a device dependence to a host action; | |||
4503 | // Device Action 1 _ | |||
4504 | // \ | |||
4505 | // Host Action 1 ---> OffloadAction -> Host Action 2 | |||
4506 | // | |||
4507 | // d) Specify a host dependence to a device action. | |||
4508 | // Host Action 1 _ | |||
4509 | // \ | |||
4510 | // Device Action 1 ---> OffloadAction -> Device Action 2 | |||
4511 | // | |||
4512 | // For a) and b), we just return the job generated for the dependence. For | |||
4513 | // c) and d) we override the current action with the host/device dependence | |||
4514 | // if the current toolchain is host/device and set the offload dependences | |||
4515 | // info with the jobs obtained from the device/host dependence(s). | |||
4516 | ||||
4517 | // If there is a single device option, just generate the job for it. | |||
4518 | if (OA->hasSingleDeviceDependence()) { | |||
4519 | InputInfo DevA; | |||
4520 | OA->doOnEachDeviceDependence([&](Action *DepA, const ToolChain *DepTC, | |||
4521 | const char *DepBoundArch) { | |||
4522 | DevA = | |||
4523 | BuildJobsForAction(C, DepA, DepTC, DepBoundArch, AtTopLevel, | |||
4524 | /*MultipleArchs*/ !!DepBoundArch, LinkingOutput, | |||
4525 | CachedResults, DepA->getOffloadingDeviceKind()); | |||
4526 | }); | |||
4527 | return DevA; | |||
4528 | } | |||
4529 | ||||
4530 | // If 'Action 2' is host, we generate jobs for the device dependences and | |||
4531 | // override the current action with the host dependence. Otherwise, we | |||
4532 | // generate the host dependences and override the action with the device | |||
4533 | // dependence. The dependences can't therefore be a top-level action. | |||
4534 | OA->doOnEachDependence( | |||
4535 | /*IsHostDependence=*/BuildingForOffloadDevice, | |||
4536 | [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) { | |||
4537 | OffloadDependencesInputInfo.push_back(BuildJobsForAction( | |||
4538 | C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false, | |||
4539 | /*MultipleArchs*/ !!DepBoundArch, LinkingOutput, CachedResults, | |||
4540 | DepA->getOffloadingDeviceKind())); | |||
4541 | }); | |||
4542 | ||||
4543 | A = BuildingForOffloadDevice | |||
4544 | ? OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true) | |||
4545 | : OA->getHostDependence(); | |||
4546 | } | |||
4547 | ||||
4548 | if (const InputAction *IA = dyn_cast<InputAction>(A)) { | |||
4549 | // FIXME: It would be nice to not claim this here; maybe the old scheme of | |||
4550 | // just using Args was better? | |||
4551 | const Arg &Input = IA->getInputArg(); | |||
4552 | Input.claim(); | |||
4553 | if (Input.getOption().matches(options::OPT_INPUT)) { | |||
4554 | const char *Name = Input.getValue(); | |||
4555 | return InputInfo(A, Name, /* _BaseInput = */ Name); | |||
4556 | } | |||
4557 | return InputInfo(A, &Input, /* _BaseInput = */ ""); | |||
4558 | } | |||
4559 | ||||
4560 | if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { | |||
4561 | const ToolChain *TC; | |||
4562 | StringRef ArchName = BAA->getArchName(); | |||
4563 | ||||
4564 | if (!ArchName.empty()) | |||
4565 | TC = &getToolChain(C.getArgs(), | |||
4566 | computeTargetTriple(*this, TargetTriple, | |||
4567 | C.getArgs(), ArchName)); | |||
4568 | else | |||
4569 | TC = &C.getDefaultToolChain(); | |||
4570 | ||||
4571 | return BuildJobsForAction(C, *BAA->input_begin(), TC, ArchName, AtTopLevel, | |||
4572 | MultipleArchs, LinkingOutput, CachedResults, | |||
4573 | TargetDeviceOffloadKind); | |||
4574 | } | |||
4575 | ||||
4576 | ||||
4577 | ActionList Inputs = A->getInputs(); | |||
4578 | ||||
4579 | const JobAction *JA = cast<JobAction>(A); | |||
4580 | ActionList CollapsedOffloadActions; | |||
4581 | ||||
4582 | ToolSelector TS(JA, *TC, C, isSaveTempsEnabled(), | |||
4583 | embedBitcodeInObject() && !isUsingLTO()); | |||
4584 | const Tool *T = TS.getTool(Inputs, CollapsedOffloadActions); | |||
4585 | ||||
4586 | if (!T) | |||
4587 | return InputInfo(); | |||
4588 | ||||
4589 | if (BuildingForOffloadDevice && | |||
4590 | A->getOffloadingDeviceKind() == Action::OFK_OpenMP) { | |||
4591 | if (TC->getTriple().isAMDGCN()) { | |||
4592 | // AMDGCN treats backend and assemble actions as no-op because | |||
4593 | // linker does not support object files. | |||
4594 | if (const BackendJobAction *BA = dyn_cast<BackendJobAction>(A)) { | |||
4595 | return BuildJobsForAction(C, *BA->input_begin(), TC, BoundArch, | |||
4596 | AtTopLevel, MultipleArchs, LinkingOutput, | |||
4597 | CachedResults, TargetDeviceOffloadKind); | |||
4598 | } | |||
4599 | ||||
4600 | if (const AssembleJobAction *AA = dyn_cast<AssembleJobAction>(A)) { | |||
4601 | return BuildJobsForAction(C, *AA->input_begin(), TC, BoundArch, | |||
4602 | AtTopLevel, MultipleArchs, LinkingOutput, | |||
4603 | CachedResults, TargetDeviceOffloadKind); | |||
4604 | } | |||
4605 | } | |||
4606 | } | |||
4607 | ||||
4608 | // If we've collapsed action list that contained OffloadAction we | |||
4609 | // need to build jobs for host/device-side inputs it may have held. | |||
4610 | for (const auto *OA : CollapsedOffloadActions) | |||
4611 | cast<OffloadAction>(OA)->doOnEachDependence( | |||
4612 | /*IsHostDependence=*/BuildingForOffloadDevice, | |||
4613 | [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) { | |||
4614 | OffloadDependencesInputInfo.push_back(BuildJobsForAction( | |||
4615 | C, DepA, DepTC, DepBoundArch, /* AtTopLevel */ false, | |||
4616 | /*MultipleArchs=*/!!DepBoundArch, LinkingOutput, CachedResults, | |||
4617 | DepA->getOffloadingDeviceKind())); | |||
4618 | }); | |||
4619 | ||||
4620 | // Only use pipes when there is exactly one input. | |||
4621 | InputInfoList InputInfos; | |||
4622 | for (const Action *Input : Inputs) { | |||
4623 | // Treat dsymutil and verify sub-jobs as being at the top-level too, they | |||
4624 | // shouldn't get temporary output names. | |||
4625 | // FIXME: Clean this up. | |||
4626 | bool SubJobAtTopLevel = | |||
4627 | AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A)); | |||
4628 | InputInfos.push_back(BuildJobsForAction( | |||
4629 | C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput, | |||
4630 | CachedResults, A->getOffloadingDeviceKind())); | |||
4631 | } | |||
4632 | ||||
4633 | // Always use the first input as the base input. | |||
4634 | const char *BaseInput = InputInfos[0].getBaseInput(); | |||
4635 | ||||
4636 | // ... except dsymutil actions, which use their actual input as the base | |||
4637 | // input. | |||
4638 | if (JA->getType() == types::TY_dSYM) | |||
4639 | BaseInput = InputInfos[0].getFilename(); | |||
4640 | ||||
4641 | // ... and in header module compilations, which use the module name. | |||
4642 | if (auto *ModuleJA = dyn_cast<HeaderModulePrecompileJobAction>(JA)) | |||
4643 | BaseInput = ModuleJA->getModuleName(); | |||
4644 | ||||
4645 | // Append outputs of offload device jobs to the input list | |||
4646 | if (!OffloadDependencesInputInfo.empty()) | |||
4647 | InputInfos.append(OffloadDependencesInputInfo.begin(), | |||
4648 | OffloadDependencesInputInfo.end()); | |||
4649 | ||||
4650 | // Set the effective triple of the toolchain for the duration of this job. | |||
4651 | llvm::Triple EffectiveTriple; | |||
4652 | const ToolChain &ToolTC = T->getToolChain(); | |||
4653 | const ArgList &Args = | |||
4654 | C.getArgsForToolChain(TC, BoundArch, A->getOffloadingDeviceKind()); | |||
4655 | if (InputInfos.size() != 1) { | |||
4656 | EffectiveTriple = llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args)); | |||
4657 | } else { | |||
4658 | // Pass along the input type if it can be unambiguously determined. | |||
4659 | EffectiveTriple = llvm::Triple( | |||
4660 | ToolTC.ComputeEffectiveClangTriple(Args, InputInfos[0].getType())); | |||
4661 | } | |||
4662 | RegisterEffectiveTriple TripleRAII(ToolTC, EffectiveTriple); | |||
4663 | ||||
4664 | // Determine the place to write output to, if any. | |||
4665 | InputInfo Result; | |||
4666 | InputInfoList UnbundlingResults; | |||
4667 | if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(JA)) { | |||
4668 | // If we have an unbundling job, we need to create results for all the | |||
4669 | // outputs. We also update the results cache so that other actions using | |||
4670 | // this unbundling action can get the right results. | |||
4671 | for (auto &UI : UA->getDependentActionsInfo()) { | |||
4672 | assert(UI.DependentOffloadKind != Action::OFK_None &&(static_cast <bool> (UI.DependentOffloadKind != Action:: OFK_None && "Unbundling with no offloading??") ? void (0) : __assert_fail ("UI.DependentOffloadKind != Action::OFK_None && \"Unbundling with no offloading??\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4673, __extension__ __PRETTY_FUNCTION__)) | |||
4673 | "Unbundling with no offloading??")(static_cast <bool> (UI.DependentOffloadKind != Action:: OFK_None && "Unbundling with no offloading??") ? void (0) : __assert_fail ("UI.DependentOffloadKind != Action::OFK_None && \"Unbundling with no offloading??\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4673, __extension__ __PRETTY_FUNCTION__)); | |||
4674 | ||||
4675 | // Unbundling actions are never at the top level. When we generate the | |||
4676 | // offloading prefix, we also do that for the host file because the | |||
4677 | // unbundling action does not change the type of the output which can | |||
4678 | // cause a overwrite. | |||
4679 | std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix( | |||
4680 | UI.DependentOffloadKind, | |||
4681 | UI.DependentToolChain->getTriple().normalize(), | |||
4682 | /*CreatePrefixForHost=*/true); | |||
4683 | auto CurI = InputInfo( | |||
4684 | UA, | |||
4685 | GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch, | |||
4686 | /*AtTopLevel=*/false, | |||
4687 | MultipleArchs || | |||
4688 | UI.DependentOffloadKind == Action::OFK_HIP, | |||
4689 | OffloadingPrefix), | |||
4690 | BaseInput); | |||
4691 | // Save the unbundling result. | |||
4692 | UnbundlingResults.push_back(CurI); | |||
4693 | ||||
4694 | // Get the unique string identifier for this dependence and cache the | |||
4695 | // result. | |||
4696 | StringRef Arch; | |||
4697 | if (TargetDeviceOffloadKind == Action::OFK_HIP) { | |||
4698 | if (UI.DependentOffloadKind == Action::OFK_Host) | |||
4699 | Arch = StringRef(); | |||
4700 | else | |||
4701 | Arch = UI.DependentBoundArch; | |||
4702 | } else | |||
4703 | Arch = BoundArch; | |||
4704 | ||||
4705 | CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch, | |||
4706 | UI.DependentOffloadKind)}] = | |||
4707 | CurI; | |||
4708 | } | |||
4709 | ||||
4710 | // Now that we have all the results generated, select the one that should be | |||
4711 | // returned for the current depending action. | |||
4712 | std::pair<const Action *, std::string> ActionTC = { | |||
4713 | A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)}; | |||
4714 | assert(CachedResults.find(ActionTC) != CachedResults.end() &&(static_cast <bool> (CachedResults.find(ActionTC) != CachedResults .end() && "Result does not exist??") ? void (0) : __assert_fail ("CachedResults.find(ActionTC) != CachedResults.end() && \"Result does not exist??\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4715, __extension__ __PRETTY_FUNCTION__)) | |||
4715 | "Result does not exist??")(static_cast <bool> (CachedResults.find(ActionTC) != CachedResults .end() && "Result does not exist??") ? void (0) : __assert_fail ("CachedResults.find(ActionTC) != CachedResults.end() && \"Result does not exist??\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4715, __extension__ __PRETTY_FUNCTION__)); | |||
4716 | Result = CachedResults[ActionTC]; | |||
4717 | } else if (JA->getType() == types::TY_Nothing) | |||
4718 | Result = InputInfo(A, BaseInput); | |||
4719 | else { | |||
4720 | // We only have to generate a prefix for the host if this is not a top-level | |||
4721 | // action. | |||
4722 | std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix( | |||
4723 | A->getOffloadingDeviceKind(), TC->getTriple().normalize(), | |||
4724 | /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() && | |||
4725 | !AtTopLevel); | |||
4726 | if (isa<OffloadWrapperJobAction>(JA)) { | |||
4727 | if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) | |||
4728 | BaseInput = FinalOutput->getValue(); | |||
4729 | else | |||
4730 | BaseInput = getDefaultImageName(); | |||
4731 | BaseInput = | |||
4732 | C.getArgs().MakeArgString(std::string(BaseInput) + "-wrapper"); | |||
4733 | } | |||
4734 | Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch, | |||
4735 | AtTopLevel, MultipleArchs, | |||
4736 | OffloadingPrefix), | |||
4737 | BaseInput); | |||
4738 | } | |||
4739 | ||||
4740 | if (CCCPrintBindings && !CCGenDiagnostics) { | |||
4741 | llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"' | |||
4742 | << " - \"" << T->getName() << "\", inputs: ["; | |||
4743 | for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) { | |||
4744 | llvm::errs() << InputInfos[i].getAsString(); | |||
4745 | if (i + 1 != e) | |||
4746 | llvm::errs() << ", "; | |||
4747 | } | |||
4748 | if (UnbundlingResults.empty()) | |||
4749 | llvm::errs() << "], output: " << Result.getAsString() << "\n"; | |||
4750 | else { | |||
4751 | llvm::errs() << "], outputs: ["; | |||
4752 | for (unsigned i = 0, e = UnbundlingResults.size(); i != e; ++i) { | |||
4753 | llvm::errs() << UnbundlingResults[i].getAsString(); | |||
4754 | if (i + 1 != e) | |||
4755 | llvm::errs() << ", "; | |||
4756 | } | |||
4757 | llvm::errs() << "] \n"; | |||
4758 | } | |||
4759 | } else { | |||
4760 | if (UnbundlingResults.empty()) | |||
4761 | T->ConstructJob( | |||
4762 | C, *JA, Result, InputInfos, | |||
4763 | C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()), | |||
4764 | LinkingOutput); | |||
4765 | else | |||
4766 | T->ConstructJobMultipleOutputs( | |||
4767 | C, *JA, UnbundlingResults, InputInfos, | |||
4768 | C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()), | |||
4769 | LinkingOutput); | |||
4770 | } | |||
4771 | return Result; | |||
4772 | } | |||
4773 | ||||
4774 | const char *Driver::getDefaultImageName() const { | |||
4775 | llvm::Triple Target(llvm::Triple::normalize(TargetTriple)); | |||
4776 | return Target.isOSWindows() ? "a.exe" : "a.out"; | |||
4777 | } | |||
4778 | ||||
4779 | /// Create output filename based on ArgValue, which could either be a | |||
4780 | /// full filename, filename without extension, or a directory. If ArgValue | |||
4781 | /// does not provide a filename, then use BaseName, and use the extension | |||
4782 | /// suitable for FileType. | |||
4783 | static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue, | |||
4784 | StringRef BaseName, | |||
4785 | types::ID FileType) { | |||
4786 | SmallString<128> Filename = ArgValue; | |||
4787 | ||||
4788 | if (ArgValue.empty()) { | |||
4789 | // If the argument is empty, output to BaseName in the current dir. | |||
4790 | Filename = BaseName; | |||
4791 | } else if (llvm::sys::path::is_separator(Filename.back())) { | |||
4792 | // If the argument is a directory, output to BaseName in that dir. | |||
4793 | llvm::sys::path::append(Filename, BaseName); | |||
4794 | } | |||
4795 | ||||
4796 | if (!llvm::sys::path::has_extension(ArgValue)) { | |||
4797 | // If the argument didn't provide an extension, then set it. | |||
4798 | const char *Extension = types::getTypeTempSuffix(FileType, true); | |||
4799 | ||||
4800 | if (FileType == types::TY_Image && | |||
4801 | Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) { | |||
4802 | // The output file is a dll. | |||
4803 | Extension = "dll"; | |||
4804 | } | |||
4805 | ||||
4806 | llvm::sys::path::replace_extension(Filename, Extension); | |||
4807 | } | |||
4808 | ||||
4809 | return Args.MakeArgString(Filename.c_str()); | |||
4810 | } | |||
4811 | ||||
4812 | static bool HasPreprocessOutput(const Action &JA) { | |||
4813 | if (isa<PreprocessJobAction>(JA)) | |||
4814 | return true; | |||
4815 | if (isa<OffloadAction>(JA) && isa<PreprocessJobAction>(JA.getInputs()[0])) | |||
4816 | return true; | |||
4817 | if (isa<OffloadBundlingJobAction>(JA) && | |||
4818 | HasPreprocessOutput(*(JA.getInputs()[0]))) | |||
4819 | return true; | |||
4820 | return false; | |||
4821 | } | |||
4822 | ||||
4823 | const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, | |||
4824 | const char *BaseInput, | |||
4825 | StringRef OrigBoundArch, bool AtTopLevel, | |||
4826 | bool MultipleArchs, | |||
4827 | StringRef OffloadingPrefix) const { | |||
4828 | std::string BoundArch = OrigBoundArch.str(); | |||
4829 | #if defined(_WIN32) | |||
4830 | // BoundArch may contains ':', which is invalid in file names on Windows, | |||
4831 | // therefore replace it with '%'. | |||
4832 | std::replace(BoundArch.begin(), BoundArch.end(), ':', '@'); | |||
4833 | #endif | |||
4834 | ||||
4835 | llvm::PrettyStackTraceString CrashInfo("Computing output path"); | |||
4836 | // Output to a user requested destination? | |||
4837 | if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) { | |||
4838 | if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) | |||
4839 | return C.addResultFile(FinalOutput->getValue(), &JA); | |||
4840 | } | |||
4841 | ||||
4842 | // For /P, preprocess to file named after BaseInput. | |||
4843 | if (C.getArgs().hasArg(options::OPT__SLASH_P)) { | |||
4844 | assert(AtTopLevel && isa<PreprocessJobAction>(JA))(static_cast <bool> (AtTopLevel && isa<PreprocessJobAction >(JA)) ? void (0) : __assert_fail ("AtTopLevel && isa<PreprocessJobAction>(JA)" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4844, __extension__ __PRETTY_FUNCTION__)); | |||
4845 | StringRef BaseName = llvm::sys::path::filename(BaseInput); | |||
4846 | StringRef NameArg; | |||
4847 | if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi)) | |||
4848 | NameArg = A->getValue(); | |||
4849 | return C.addResultFile( | |||
4850 | MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C), | |||
4851 | &JA); | |||
4852 | } | |||
4853 | ||||
4854 | // Default to writing to stdout? | |||
4855 | if (AtTopLevel && !CCGenDiagnostics && HasPreprocessOutput(JA)) { | |||
4856 | return "-"; | |||
4857 | } | |||
4858 | ||||
4859 | // Is this the assembly listing for /FA? | |||
4860 | if (JA.getType() == types::TY_PP_Asm && | |||
4861 | (C.getArgs().hasArg(options::OPT__SLASH_FA) || | |||
4862 | C.getArgs().hasArg(options::OPT__SLASH_Fa))) { | |||
4863 | // Use /Fa and the input filename to determine the asm file name. | |||
4864 | StringRef BaseName = llvm::sys::path::filename(BaseInput); | |||
4865 | StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa); | |||
4866 | return C.addResultFile( | |||
4867 | MakeCLOutputFilename(C.getArgs(), FaValue, BaseName, JA.getType()), | |||
4868 | &JA); | |||
4869 | } | |||
4870 | ||||
4871 | // Output to a temporary file? | |||
4872 | if ((!AtTopLevel && !isSaveTempsEnabled() && | |||
4873 | !C.getArgs().hasArg(options::OPT__SLASH_Fo)) || | |||
4874 | CCGenDiagnostics) { | |||
4875 | StringRef Name = llvm::sys::path::filename(BaseInput); | |||
4876 | std::pair<StringRef, StringRef> Split = Name.split('.'); | |||
4877 | SmallString<128> TmpName; | |||
4878 | const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); | |||
4879 | Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir); | |||
4880 | if (CCGenDiagnostics && A) { | |||
4881 | SmallString<128> CrashDirectory(A->getValue()); | |||
4882 | if (!getVFS().exists(CrashDirectory)) | |||
4883 | llvm::sys::fs::create_directories(CrashDirectory); | |||
4884 | llvm::sys::path::append(CrashDirectory, Split.first); | |||
4885 | const char *Middle = Suffix ? "-%%%%%%." : "-%%%%%%"; | |||
4886 | std::error_code EC = llvm::sys::fs::createUniqueFile( | |||
4887 | CrashDirectory + Middle + Suffix, TmpName); | |||
4888 | if (EC) { | |||
4889 | Diag(clang::diag::err_unable_to_make_temp) << EC.message(); | |||
4890 | return ""; | |||
4891 | } | |||
4892 | } else { | |||
4893 | TmpName = GetTemporaryPath(Split.first, Suffix); | |||
4894 | } | |||
4895 | return C.addTempFile(C.getArgs().MakeArgString(TmpName)); | |||
4896 | } | |||
4897 | ||||
4898 | SmallString<128> BasePath(BaseInput); | |||
4899 | SmallString<128> ExternalPath(""); | |||
4900 | StringRef BaseName; | |||
4901 | ||||
4902 | // Dsymutil actions should use the full path. | |||
4903 | if (isa<DsymutilJobAction>(JA) && C.getArgs().hasArg(options::OPT_dsym_dir)) { | |||
4904 | ExternalPath += C.getArgs().getLastArg(options::OPT_dsym_dir)->getValue(); | |||
4905 | // We use posix style here because the tests (specifically | |||
4906 | // darwin-dsymutil.c) demonstrate that posix style paths are acceptable | |||
4907 | // even on Windows and if we don't then the similar test covering this | |||
4908 | // fails. | |||
4909 | llvm::sys::path::append(ExternalPath, llvm::sys::path::Style::posix, | |||
4910 | llvm::sys::path::filename(BasePath)); | |||
4911 | BaseName = ExternalPath; | |||
4912 | } else if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA)) | |||
4913 | BaseName = BasePath; | |||
4914 | else | |||
4915 | BaseName = llvm::sys::path::filename(BasePath); | |||
4916 | ||||
4917 | // Determine what the derived output name should be. | |||
4918 | const char *NamedOutput; | |||
4919 | ||||
4920 | if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) && | |||
4921 | C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) { | |||
4922 | // The /Fo or /o flag decides the object filename. | |||
4923 | StringRef Val = | |||
4924 | C.getArgs() | |||
4925 | .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o) | |||
4926 | ->getValue(); | |||
4927 | NamedOutput = | |||
4928 | MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object); | |||
4929 | } else if (JA.getType() == types::TY_Image && | |||
4930 | C.getArgs().hasArg(options::OPT__SLASH_Fe, | |||
4931 | options::OPT__SLASH_o)) { | |||
4932 | // The /Fe or /o flag names the linked file. | |||
4933 | StringRef Val = | |||
4934 | C.getArgs() | |||
4935 | .getLastArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o) | |||
4936 | ->getValue(); | |||
4937 | NamedOutput = | |||
4938 | MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Image); | |||
4939 | } else if (JA.getType() == types::TY_Image) { | |||
4940 | if (IsCLMode()) { | |||
4941 | // clang-cl uses BaseName for the executable name. | |||
4942 | NamedOutput = | |||
4943 | MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image); | |||
4944 | } else { | |||
4945 | SmallString<128> Output(getDefaultImageName()); | |||
4946 | // HIP image for device compilation with -fno-gpu-rdc is per compilation | |||
4947 | // unit. | |||
4948 | bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP && | |||
4949 | !C.getArgs().hasFlag(options::OPT_fgpu_rdc, | |||
4950 | options::OPT_fno_gpu_rdc, false); | |||
4951 | if (IsHIPNoRDC) { | |||
4952 | Output = BaseName; | |||
4953 | llvm::sys::path::replace_extension(Output, ""); | |||
4954 | } | |||
4955 | Output += OffloadingPrefix; | |||
4956 | if (MultipleArchs && !BoundArch.empty()) { | |||
4957 | Output += "-"; | |||
4958 | Output.append(BoundArch); | |||
4959 | } | |||
4960 | if (IsHIPNoRDC) | |||
4961 | Output += ".out"; | |||
4962 | NamedOutput = C.getArgs().MakeArgString(Output.c_str()); | |||
4963 | } | |||
4964 | } else if (JA.getType() == types::TY_PCH && IsCLMode()) { | |||
4965 | NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName)); | |||
4966 | } else { | |||
4967 | const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); | |||
4968 | assert(Suffix && "All types used for output should have a suffix.")(static_cast <bool> (Suffix && "All types used for output should have a suffix." ) ? void (0) : __assert_fail ("Suffix && \"All types used for output should have a suffix.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/clang/lib/Driver/Driver.cpp" , 4968, __extension__ __PRETTY_FUNCTION__)); | |||
4969 | ||||
4970 | std::string::size_type End = std::string::npos; | |||
4971 | if (!types::appendSuffixForType(JA.getType())) | |||
4972 | End = BaseName.rfind('.'); | |||
4973 | SmallString<128> Suffixed(BaseName.substr(0, End)); | |||
4974 | Suffixed += OffloadingPrefix; | |||
4975 | if (MultipleArchs && !BoundArch.empty()) { | |||
4976 | Suffixed += "-"; | |||
4977 | Suffixed.append(BoundArch); | |||
4978 | } | |||
4979 | // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for | |||
4980 | // the unoptimized bitcode so that it does not get overwritten by the ".bc" | |||
4981 | // optimized bitcode output. | |||
4982 | auto IsHIPRDCInCompilePhase = [](const JobAction &JA, | |||
4983 | const llvm::opt::DerivedArgList &Args) { | |||
4984 | // The relocatable compilation in HIP implies -emit-llvm. Similarly, use a | |||
4985 | // ".tmp.bc" suffix for the unoptimized bitcode (generated in the compile | |||
4986 | // phase.) | |||
4987 | return isa<CompileJobAction>(JA) && | |||
4988 | JA.getOffloadingDeviceKind() == Action::OFK_HIP && | |||
4989 | Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, | |||
4990 | false); | |||
4991 | }; | |||
4992 | if (!AtTopLevel && JA.getType() == types::TY_LLVM_BC && | |||
4993 | (C.getArgs().hasArg(options::OPT_emit_llvm) || | |||
4994 | IsHIPRDCInCompilePhase(JA, C.getArgs()))) | |||
4995 | Suffixed += ".tmp"; | |||
4996 | Suffixed += '.'; | |||
4997 | Suffixed += Suffix; | |||
4998 | NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str()); | |||
4999 | } | |||
5000 | ||||
5001 | // Prepend object file path if -save-temps=obj | |||
5002 | if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) && | |||
5003 | JA.getType() != types::TY_PCH) { | |||
5004 | Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); | |||
5005 | SmallString<128> TempPath(FinalOutput->getValue()); | |||
5006 | llvm::sys::path::remove_filename(TempPath); | |||
5007 | StringRef OutputFileName = llvm::sys::path::filename(NamedOutput); | |||
5008 | llvm::sys::path::append(TempPath, OutputFileName); | |||
5009 | NamedOutput = C.getArgs().MakeArgString(TempPath.c_str()); | |||
5010 | } | |||
5011 | ||||
5012 | // If we're saving temps and the temp file conflicts with the input file, | |||
5013 | // then avoid overwriting input file. | |||
5014 | if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) { | |||
5015 | bool SameFile = false; | |||
5016 | SmallString<256> Result; | |||
5017 | llvm::sys::fs::current_path(Result); | |||
5018 | llvm::sys::path::append(Result, BaseName); | |||
5019 | llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile); | |||
5020 | // Must share the same path to conflict. | |||
5021 | if (SameFile) { | |||
5022 | StringRef Name = llvm::sys::path::filename(BaseInput); | |||
5023 | std::pair<StringRef, StringRef> Split = Name.split('.'); | |||
5024 | std::string TmpName = GetTemporaryPath( | |||
5025 | Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode())); | |||
5026 | return C.addTempFile(C.getArgs().MakeArgString(TmpName)); | |||
5027 | } | |||
5028 | } | |||
5029 | ||||
5030 | // As an annoying special case, PCH generation doesn't strip the pathname. | |||
5031 | if (JA.getType() == types::TY_PCH && !IsCLMode()) { | |||
5032 | llvm::sys::path::remove_filename(BasePath); | |||
5033 | if (BasePath.empty()) | |||
5034 | BasePath = NamedOutput; | |||
5035 | else | |||
5036 | llvm::sys::path::append(BasePath, NamedOutput); | |||
5037 | return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()), &JA); | |||
5038 | } else { | |||
5039 | return C.addResultFile(NamedOutput, &JA); | |||
5040 | } | |||
5041 | } | |||
5042 | ||||
5043 | std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const { | |||
5044 | // Search for Name in a list of paths. | |||
5045 | auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P) | |||
5046 | -> llvm::Optional<std::string> { | |||
5047 | // Respect a limited subset of the '-Bprefix' functionality in GCC by | |||
5048 | // attempting to use this prefix when looking for file paths. | |||
5049 | for (const auto &Dir : P) { | |||
5050 | if (Dir.empty()) | |||
5051 | continue; | |||
5052 | SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir); | |||
5053 | llvm::sys::path::append(P, Name); | |||
5054 | if (llvm::sys::fs::exists(Twine(P))) | |||
5055 | return std::string(P); | |||
5056 | } | |||
5057 | return None; | |||
5058 | }; | |||
5059 | ||||
5060 | if (auto P = SearchPaths(PrefixDirs)) | |||
5061 | return *P; | |||
5062 | ||||
5063 | SmallString<128> R(ResourceDir); | |||
5064 | llvm::sys::path::append(R, Name); | |||
5065 | if (llvm::sys::fs::exists(Twine(R))) | |||
5066 | return std::string(R.str()); | |||
5067 | ||||
5068 | SmallString<128> P(TC.getCompilerRTPath()); | |||
5069 | llvm::sys::path::append(P, Name); | |||
5070 | if (llvm::sys::fs::exists(Twine(P))) | |||
5071 | return std::string(P.str()); | |||
5072 | ||||
5073 | SmallString<128> D(Dir); | |||
5074 | llvm::sys::path::append(D, "..", Name); | |||
5075 | if (llvm::sys::fs::exists(Twine(D))) | |||
5076 | return std::string(D.str()); | |||
5077 | ||||
5078 | if (auto P = SearchPaths(TC.getLibraryPaths())) | |||
5079 | return *P; | |||
5080 | ||||
5081 | if (auto P = SearchPaths(TC.getFilePaths())) | |||
5082 | return *P; | |||
5083 | ||||
5084 | return std::string(Name); | |||
5085 | } | |||
5086 | ||||
5087 | void Driver::generatePrefixedToolNames( | |||
5088 | StringRef Tool, const ToolChain &TC, | |||
5089 | SmallVectorImpl<std::string> &Names) const { | |||
5090 | // FIXME: Needs a better variable than TargetTriple | |||
5091 | Names.emplace_back((TargetTriple + "-" + Tool).str()); | |||
5092 | Names.emplace_back(Tool); | |||
5093 | } | |||
5094 | ||||
5095 | static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) { | |||
5096 | llvm::sys::path::append(Dir, Name); | |||
5097 | if (llvm::sys::fs::can_execute(Twine(Dir))) | |||
5098 | return true; | |||
5099 | llvm::sys::path::remove_filename(Dir); | |||
5100 | return false; | |||
5101 | } | |||
5102 | ||||
5103 | std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const { | |||
5104 | SmallVector<std::string, 2> TargetSpecificExecutables; | |||
5105 | generatePrefixedToolNames(Name, TC, TargetSpecificExecutables); | |||
5106 | ||||
5107 | // Respect a limited subset of the '-Bprefix' functionality in GCC by | |||
5108 | // attempting to use this prefix when looking for program paths. | |||
5109 | for (const auto &PrefixDir : PrefixDirs) { | |||
5110 | if (llvm::sys::fs::is_directory(PrefixDir)) { | |||
5111 | SmallString<128> P(PrefixDir); | |||
5112 | if (ScanDirForExecutable(P, Name)) | |||
5113 | return std::string(P.str()); | |||
5114 | } else { | |||
5115 | SmallString<128> P((PrefixDir + Name).str()); | |||
5116 | if (llvm::sys::fs::can_execute(Twine(P))) | |||
5117 | return std::string(P.str()); | |||
5118 | } | |||
5119 | } | |||
5120 | ||||
5121 | const ToolChain::path_list &List = TC.getProgramPaths(); | |||
5122 | for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) { | |||
5123 | // For each possible name of the tool look for it in | |||
5124 | // program paths first, then the path. | |||
5125 | // Higher priority names will be first, meaning that | |||
5126 | // a higher priority name in the path will be found | |||
5127 | // instead of a lower priority name in the program path. | |||
5128 | // E.g. <triple>-gcc on the path will be found instead | |||
5129 | // of gcc in the program path | |||
5130 | for (const auto &Path : List) { | |||
5131 | SmallString<128> P(Path); | |||
5132 | if (ScanDirForExecutable(P, TargetSpecificExecutable)) | |||
5133 | return std::string(P.str()); | |||
5134 | } | |||
5135 | ||||
5136 | // Fall back to the path | |||
5137 | if (llvm::ErrorOr<std::string> P = | |||
5138 | llvm::sys::findProgramByName(TargetSpecificExecutable)) | |||
5139 | return *P; | |||
5140 | } | |||
5141 | ||||
5142 | return std::string(Name); | |||
5143 | } | |||
5144 | ||||
5145 | std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const { | |||
5146 | SmallString<128> Path; | |||
5147 | std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path); | |||
5148 | if (EC) { | |||
5149 | Diag(clang::diag::err_unable_to_make_temp) << EC.message(); | |||
5150 | return ""; | |||
5151 | } | |||
5152 | ||||
5153 | return std::string(Path.str()); | |||
5154 | } | |||
5155 | ||||
5156 | std::string Driver::GetTemporaryDirectory(StringRef Prefix) const { | |||
5157 | SmallString<128> Path; | |||
5158 | std::error_code EC = llvm::sys::fs::createUniqueDirectory(Prefix, Path); | |||
5159 | if (EC) { | |||
5160 | Diag(clang::diag::err_unable_to_make_temp) << EC.message(); | |||
5161 | return ""; | |||
5162 | } | |||
5163 | ||||
5164 | return std::string(Path.str()); | |||
5165 | } | |||
5166 | ||||
5167 | std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const { | |||
5168 | SmallString<128> Output; | |||
5169 | if (Arg *FpArg = C.getArgs().getLastArg(options::OPT__SLASH_Fp)) { | |||
5170 | // FIXME: If anybody needs it, implement this obscure rule: | |||
5171 | // "If you specify a directory without a file name, the default file name | |||
5172 | // is VCx0.pch., where x is the major version of Visual C++ in use." | |||
5173 | Output = FpArg->getValue(); | |||
5174 | ||||
5175 | // "If you do not specify an extension as part of the path name, an | |||
5176 | // extension of .pch is assumed. " | |||
5177 | if (!llvm::sys::path::has_extension(Output)) | |||
5178 | Output += ".pch"; | |||
5179 | } else { | |||
5180 | if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc)) | |||
5181 | Output = YcArg->getValue(); | |||
5182 | if (Output.empty()) | |||
5183 | Output = BaseName; | |||
5184 | llvm::sys::path::replace_extension(Output, ".pch"); | |||
5185 | } | |||
5186 | return std::string(Output.str()); | |||
5187 | } | |||
5188 | ||||
5189 | const ToolChain &Driver::getToolChain(const ArgList &Args, | |||
5190 | const llvm::Triple &Target) const { | |||
5191 | ||||
5192 | auto &TC = ToolChains[Target.str()]; | |||
5193 | if (!TC) { | |||
5194 | switch (Target.getOS()) { | |||
5195 | case llvm::Triple::AIX: | |||
5196 | TC = std::make_unique<toolchains::AIX>(*this, Target, Args); | |||
5197 | break; | |||
5198 | case llvm::Triple::Haiku: | |||
5199 | TC = std::make_unique<toolchains::Haiku>(*this, Target, Args); | |||
5200 | break; | |||
5201 | case llvm::Triple::Ananas: | |||
5202 | TC = std::make_unique<toolchains::Ananas>(*this, Target, Args); | |||
5203 | break; | |||
5204 | case llvm::Triple::CloudABI: | |||
5205 | TC = std::make_unique<toolchains::CloudABI>(*this, Target, Args); | |||
5206 | break; | |||
5207 | case llvm::Triple::Darwin: | |||
5208 | case llvm::Triple::MacOSX: | |||
5209 | case llvm::Triple::IOS: | |||
5210 | case llvm::Triple::TvOS: | |||
5211 | case llvm::Triple::WatchOS: | |||
5212 | TC = std::make_unique<toolchains::DarwinClang>(*this, Target, Args); | |||
5213 | break; | |||
5214 | case llvm::Triple::DragonFly: | |||
5215 | TC = std::make_unique<toolchains::DragonFly>(*this, Target, Args); | |||
5216 | break; | |||
5217 | case llvm::Triple::OpenBSD: | |||
5218 | TC = std::make_unique<toolchains::OpenBSD>(*this, Target, Args); | |||
5219 | break; | |||
5220 | case llvm::Triple::NetBSD: | |||
5221 | TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args); | |||
5222 | break; | |||
5223 | case llvm::Triple::FreeBSD: | |||
5224 | TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args); | |||
5225 | break; | |||
5226 | case llvm::Triple::Minix: | |||
5227 | TC = std::make_unique<toolchains::Minix>(*this, Target, Args); | |||
5228 | break; | |||
5229 | case llvm::Triple::Linux: | |||
5230 | case llvm::Triple::ELFIAMCU: | |||
5231 | if (Target.getArch() == llvm::Triple::hexagon) | |||
5232 | TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target, | |||
5233 | Args); | |||
5234 | else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) && | |||
5235 | !Target.hasEnvironment()) | |||
5236 | TC = std::make_unique<toolchains::MipsLLVMToolChain>(*this, Target, | |||
5237 | Args); | |||
5238 | else if (Target.isPPC()) | |||
5239 | TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target, | |||
5240 | Args); | |||
5241 | else if (Target.getArch() == llvm::Triple::ve) | |||
5242 | TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args); | |||
5243 | ||||
5244 | else | |||
5245 | TC = std::make_unique<toolchains::Linux>(*this, Target, Args); | |||
5246 | break; | |||
5247 | case llvm::Triple::NaCl: | |||
5248 | TC = std::make_unique<toolchains::NaClToolChain>(*this, Target, Args); | |||
5249 | break; | |||
5250 | case llvm::Triple::Fuchsia: | |||
5251 | TC = std::make_unique<toolchains::Fuchsia>(*this, Target, Args); | |||
5252 | break; | |||
5253 | case llvm::Triple::Solaris: | |||
5254 | TC = std::make_unique<toolchains::Solaris>(*this, Target, Args); | |||
5255 | break; | |||
5256 | case llvm::Triple::AMDHSA: | |||
5257 | TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args); | |||
5258 | break; | |||
5259 | case llvm::Triple::AMDPAL: | |||
5260 | case llvm::Triple::Mesa3D: | |||
5261 | TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args); | |||
5262 | break; | |||
5263 | case llvm::Triple::Win32: | |||
5264 | switch (Target.getEnvironment()) { | |||
5265 | default: | |||
5266 | if (Target.isOSBinFormatELF()) | |||
5267 | TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args); | |||
5268 | else if (Target.isOSBinFormatMachO()) | |||
5269 | TC = std::make_unique<toolchains::MachO>(*this, Target, Args); | |||
5270 | else | |||
5271 | TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args); | |||
5272 | break; | |||
5273 | case llvm::Triple::GNU: | |||
5274 | TC = std::make_unique<toolchains::MinGW>(*this, Target, Args); | |||
5275 | break; | |||
5276 | case llvm::Triple::Itanium: | |||
5277 | TC = std::make_unique<toolchains::CrossWindowsToolChain>(*this, Target, | |||
5278 | Args); | |||
5279 | break; | |||
5280 | case llvm::Triple::MSVC: | |||
5281 | case llvm::Triple::UnknownEnvironment: | |||
5282 | if (Args.getLastArgValue(options::OPT_fuse_ld_EQ) | |||
5283 | .startswith_lower("bfd")) | |||
5284 | TC = std::make_unique<toolchains::CrossWindowsToolChain>( | |||
5285 | *this, Target, Args); | |||
5286 | else | |||
5287 | TC = | |||
5288 | std::make_unique<toolchains::MSVCToolChain>(*this, Target, Args); | |||
5289 | break; | |||
5290 | } | |||
5291 | break; | |||
5292 | case llvm::Triple::PS4: | |||
5293 | TC = std::make_unique<toolchains::PS4CPU>(*this, Target, Args); | |||
5294 | break; | |||
5295 | case llvm::Triple::Contiki: | |||
5296 | TC = std::make_unique<toolchains::Contiki>(*this, Target, Args); | |||
5297 | break; | |||
5298 | case llvm::Triple::Hurd: | |||
5299 | TC = std::make_unique<toolchains::Hurd>(*this, Target, Args); | |||
5300 | break; | |||
5301 | case llvm::Triple::ZOS: | |||
5302 | TC = std::make_unique<toolchains::ZOS>(*this, Target, Args); | |||
5303 | break; | |||
5304 | default: | |||
5305 | // Of these targets, Hexagon is the only one that might have | |||
5306 | // an OS of Linux, in which case it got handled above already. | |||
5307 | switch (Target.getArch()) { | |||
5308 | case llvm::Triple::tce: | |||
5309 | TC = std::make_unique<toolchains::TCEToolChain>(*this, Target, Args); | |||
5310 | break; | |||
5311 | case llvm::Triple::tcele: | |||
5312 | TC = std::make_unique<toolchains::TCELEToolChain>(*this, Target, Args); | |||
5313 | break; | |||
5314 | case llvm::Triple::hexagon: | |||
5315 | TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target, | |||
5316 | Args); | |||
5317 | break; | |||
5318 | case llvm::Triple::lanai: | |||
5319 | TC = std::make_unique<toolchains::LanaiToolChain>(*this, Target, Args); | |||
5320 | break; | |||
5321 | case llvm::Triple::xcore: | |||
5322 | TC = std::make_unique<toolchains::XCoreToolChain>(*this, Target, Args); | |||
5323 | break; | |||
5324 | case llvm::Triple::wasm32: | |||
5325 | case llvm::Triple::wasm64: | |||
5326 | TC = std::make_unique<toolchains::WebAssembly>(*this, Target, Args); | |||
5327 | break; | |||
5328 | case llvm::Triple::avr: | |||
5329 | TC = std::make_unique<toolchains::AVRToolChain>(*this, Target, Args); | |||
5330 | break; | |||
5331 | case llvm::Triple::msp430: | |||
5332 | TC = | |||
5333 | std::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args); | |||
5334 | break; | |||
5335 | case llvm::Triple::riscv32: | |||
5336 | case llvm::Triple::riscv64: | |||
5337 | if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args)) | |||
5338 | TC = | |||
5339 | std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args); | |||
5340 | else | |||
5341 | TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args); | |||
5342 | break; | |||
5343 | case llvm::Triple::ve: | |||
5344 | TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args); | |||
5345 | break; | |||
5346 | default: | |||
5347 | if (Target.getVendor() == llvm::Triple::Myriad) | |||
5348 | TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target, | |||
5349 | Args); | |||
5350 | else if (toolchains::BareMetal::handlesTarget(Target)) | |||
5351 | TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args); | |||
5352 | else if (Target.isOSBinFormatELF()) | |||
5353 | TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args); | |||
5354 | else if (Target.isOSBinFormatMachO()) | |||
5355 | TC = std::make_unique<toolchains::MachO>(*this, Target, Args); | |||
5356 | else | |||
5357 | TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args); | |||
5358 | } | |||
5359 | } | |||
5360 | } | |||
5361 | ||||
5362 | // Intentionally omitted from the switch above: llvm::Triple::CUDA. CUDA | |||
5363 | // compiles always need two toolchains, the CUDA toolchain and the host | |||
5364 | // toolchain. So the only valid way to create a CUDA toolchain is via | |||
5365 | // CreateOffloadingDeviceToolChains. | |||
5366 | ||||
5367 | return *TC; | |||
5368 | } | |||
5369 | ||||
5370 | bool Driver::ShouldUseClangCompiler(const JobAction &JA) const { | |||
5371 | // Say "no" if there is not exactly one input of a type clang understands. | |||
5372 | if (JA.size() != 1 || | |||
5373 | !types::isAcceptedByClang((*JA.input_begin())->getType())) | |||
5374 | return false; | |||
5375 | ||||
5376 | // And say "no" if this is not a kind of action clang understands. | |||
5377 | if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) && | |||
5378 | !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA)) | |||
5379 | return false; | |||
5380 | ||||
5381 | return true; | |||
5382 | } | |||
5383 | ||||
5384 | bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const { | |||
5385 | // Say "no" if there is not exactly one input of a type flang understands. | |||
5386 | if (JA.size() != 1 || | |||
5387 | !types::isFortran((*JA.input_begin())->getType())) | |||
5388 | return false; | |||
5389 | ||||
5390 | // And say "no" if this is not a kind of action flang understands. | |||
5391 | if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA)) | |||
5392 | return false; | |||
5393 | ||||
5394 | return true; | |||
5395 | } | |||
5396 | ||||
5397 | bool Driver::ShouldEmitStaticLibrary(const ArgList &Args) const { | |||
5398 | // Only emit static library if the flag is set explicitly. | |||
5399 | if (Args.hasArg(options::OPT_emit_static_lib)) | |||
5400 | return true; | |||
5401 | return false; | |||
5402 | } | |||
5403 | ||||
5404 | /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the | |||
5405 | /// grouped values as integers. Numbers which are not provided are set to 0. | |||
5406 | /// | |||
5407 | /// \return True if the entire string was parsed (9.2), or all groups were | |||
5408 | /// parsed (10.3.5extrastuff). | |||
5409 | bool Driver::GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor, | |||
5410 | unsigned &Micro, bool &HadExtra) { | |||
5411 | HadExtra = false; | |||
5412 | ||||
5413 | Major = Minor = Micro = 0; | |||
5414 | if (Str.empty()) | |||
5415 | return false; | |||
5416 | ||||
5417 | if (Str.consumeInteger(10, Major)) | |||
5418 | return false; | |||
5419 | if (Str.empty()) | |||
5420 | return true; | |||
5421 | if (Str[0] != '.') | |||
5422 | return false; | |||
5423 | ||||
5424 | Str = Str.drop_front(1); | |||
5425 | ||||
5426 | if (Str.consumeInteger(10, Minor)) | |||
5427 | return false; | |||
5428 | if (Str.empty()) | |||
5429 | return true; | |||
5430 | if (Str[0] != '.') | |||
5431 | return false; | |||
5432 | Str = Str.drop_front(1); | |||
5433 | ||||
5434 | if (Str.consumeInteger(10, Micro)) | |||
5435 | return false; | |||
5436 | if (!Str.empty()) | |||
5437 | HadExtra = true; | |||
5438 | return true; | |||
5439 | } | |||
5440 | ||||
5441 | /// Parse digits from a string \p Str and fulfill \p Digits with | |||
5442 | /// the parsed numbers. This method assumes that the max number of | |||
5443 | /// digits to look for is equal to Digits.size(). | |||
5444 | /// | |||
5445 | /// \return True if the entire string was parsed and there are | |||
5446 | /// no extra characters remaining at the end. | |||
5447 | bool Driver::GetReleaseVersion(StringRef Str, | |||
5448 | MutableArrayRef<unsigned> Digits) { | |||
5449 | if (Str.empty()) | |||
5450 | return false; | |||
5451 | ||||
5452 | unsigned CurDigit = 0; | |||
5453 | while (CurDigit < Digits.size()) { | |||
5454 | unsigned Digit; | |||
5455 | if (Str.consumeInteger(10, Digit)) | |||
5456 | return false; | |||
5457 | Digits[CurDigit] = Digit; | |||
5458 | if (Str.empty()) | |||
5459 | return true; | |||
5460 | if (Str[0] != '.') | |||
5461 | return false; | |||
5462 | Str = Str.drop_front(1); | |||
5463 | CurDigit++; | |||
5464 | } | |||
5465 | ||||
5466 | // More digits than requested, bail out... | |||
5467 | return false; | |||
5468 | } | |||
5469 | ||||
5470 | std::pair<unsigned, unsigned> | |||
5471 | Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const { | |||
5472 | unsigned IncludedFlagsBitmask = 0; | |||
5473 | unsigned ExcludedFlagsBitmask = options::NoDriverOption; | |||
5474 | ||||
5475 | if (IsClCompatMode) { | |||
5476 | // Include CL and Core options. | |||
5477 | IncludedFlagsBitmask |= options::CLOption; | |||
5478 | IncludedFlagsBitmask |= options::CoreOption; | |||
5479 | } else { | |||
5480 | ExcludedFlagsBitmask |= options::CLOption; | |||
5481 | } | |||
5482 | ||||
5483 | return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask); | |||
5484 | } | |||
5485 | ||||
5486 | bool clang::driver::isOptimizationLevelFast(const ArgList &Args) { | |||
5487 | return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false); | |||
5488 | } | |||
5489 | ||||
5490 | bool clang::driver::willEmitRemarks(const ArgList &Args) { | |||
5491 | // -fsave-optimization-record enables it. | |||
5492 | if (Args.hasFlag(options::OPT_fsave_optimization_record, | |||
5493 | options::OPT_fno_save_optimization_record, false)) | |||
5494 | return true; | |||
5495 | ||||
5496 | // -fsave-optimization-record=<format> enables it as well. | |||
5497 | if (Args.hasFlag(options::OPT_fsave_optimization_record_EQ, | |||
5498 | options::OPT_fno_save_optimization_record, false)) | |||
5499 | return true; | |||
5500 | ||||
5501 | // -foptimization-record-file alone enables it too. | |||
5502 | if (Args.hasFlag(options::OPT_foptimization_record_file_EQ, | |||
5503 | options::OPT_fno_save_optimization_record, false)) | |||
5504 | return true; | |||
5505 | ||||
5506 | // -foptimization-record-passes alone enables it too. | |||
5507 | if (Args.hasFlag(options::OPT_foptimization_record_passes_EQ, | |||
5508 | options::OPT_fno_save_optimization_record, false)) | |||
5509 | return true; | |||
5510 | return false; | |||
5511 | } |
1 | //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- 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 | // This file defines the SmallVector class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_ADT_SMALLVECTOR_H |
14 | #define LLVM_ADT_SMALLVECTOR_H |
15 | |
16 | #include "llvm/ADT/iterator_range.h" |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/ErrorHandling.h" |
19 | #include "llvm/Support/MathExtras.h" |
20 | #include "llvm/Support/MemAlloc.h" |
21 | #include "llvm/Support/type_traits.h" |
22 | #include <algorithm> |
23 | #include <cassert> |
24 | #include <cstddef> |
25 | #include <cstdlib> |
26 | #include <cstring> |
27 | #include <initializer_list> |
28 | #include <iterator> |
29 | #include <limits> |
30 | #include <memory> |
31 | #include <new> |
32 | #include <type_traits> |
33 | #include <utility> |
34 | |
35 | namespace llvm { |
36 | |
37 | /// This is all the stuff common to all SmallVectors. |
38 | /// |
39 | /// The template parameter specifies the type which should be used to hold the |
40 | /// Size and Capacity of the SmallVector, so it can be adjusted. |
41 | /// Using 32 bit size is desirable to shrink the size of the SmallVector. |
42 | /// Using 64 bit size is desirable for cases like SmallVector<char>, where a |
43 | /// 32 bit size would limit the vector to ~4GB. SmallVectors are used for |
44 | /// buffering bitcode output - which can exceed 4GB. |
45 | template <class Size_T> class SmallVectorBase { |
46 | protected: |
47 | void *BeginX; |
48 | Size_T Size = 0, Capacity; |
49 | |
50 | /// The maximum value of the Size_T used. |
51 | static constexpr size_t SizeTypeMax() { |
52 | return std::numeric_limits<Size_T>::max(); |
53 | } |
54 | |
55 | SmallVectorBase() = delete; |
56 | SmallVectorBase(void *FirstEl, size_t TotalCapacity) |
57 | : BeginX(FirstEl), Capacity(TotalCapacity) {} |
58 | |
59 | /// This is a helper for \a grow() that's out of line to reduce code |
60 | /// duplication. This function will report a fatal error if it can't grow at |
61 | /// least to \p MinSize. |
62 | void *mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity); |
63 | |
64 | /// This is an implementation of the grow() method which only works |
65 | /// on POD-like data types and is out of line to reduce code duplication. |
66 | /// This function will report a fatal error if it cannot increase capacity. |
67 | void grow_pod(void *FirstEl, size_t MinSize, size_t TSize); |
68 | |
69 | public: |
70 | size_t size() const { return Size; } |
71 | size_t capacity() const { return Capacity; } |
72 | |
73 | LLVM_NODISCARD[[clang::warn_unused_result]] bool empty() const { return !Size; } |
74 | |
75 | /// Set the array size to \p N, which the current array must have enough |
76 | /// capacity for. |
77 | /// |
78 | /// This does not construct or destroy any elements in the vector. |
79 | /// |
80 | /// Clients can use this in conjunction with capacity() to write past the end |
81 | /// of the buffer when they know that more elements are available, and only |
82 | /// update the size later. This avoids the cost of value initializing elements |
83 | /// which will only be overwritten. |
84 | void set_size(size_t N) { |
85 | assert(N <= capacity())(static_cast <bool> (N <= capacity()) ? void (0) : __assert_fail ("N <= capacity()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 85, __extension__ __PRETTY_FUNCTION__)); |
86 | Size = N; |
87 | } |
88 | }; |
89 | |
90 | template <class T> |
91 | using SmallVectorSizeType = |
92 | typename std::conditional<sizeof(T) < 4 && sizeof(void *) >= 8, uint64_t, |
93 | uint32_t>::type; |
94 | |
95 | /// Figure out the offset of the first element. |
96 | template <class T, typename = void> struct SmallVectorAlignmentAndSize { |
97 | alignas(SmallVectorBase<SmallVectorSizeType<T>>) char Base[sizeof( |
98 | SmallVectorBase<SmallVectorSizeType<T>>)]; |
99 | alignas(T) char FirstEl[sizeof(T)]; |
100 | }; |
101 | |
102 | /// This is the part of SmallVectorTemplateBase which does not depend on whether |
103 | /// the type T is a POD. The extra dummy template argument is used by ArrayRef |
104 | /// to avoid unnecessarily requiring T to be complete. |
105 | template <typename T, typename = void> |
106 | class SmallVectorTemplateCommon |
107 | : public SmallVectorBase<SmallVectorSizeType<T>> { |
108 | using Base = SmallVectorBase<SmallVectorSizeType<T>>; |
109 | |
110 | /// Find the address of the first element. For this pointer math to be valid |
111 | /// with small-size of 0 for T with lots of alignment, it's important that |
112 | /// SmallVectorStorage is properly-aligned even for small-size of 0. |
113 | void *getFirstEl() const { |
114 | return const_cast<void *>(reinterpret_cast<const void *>( |
115 | reinterpret_cast<const char *>(this) + |
116 | offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)__builtin_offsetof(SmallVectorAlignmentAndSize<T>, FirstEl ))); |
117 | } |
118 | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. |
119 | |
120 | protected: |
121 | SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {} |
122 | |
123 | void grow_pod(size_t MinSize, size_t TSize) { |
124 | Base::grow_pod(getFirstEl(), MinSize, TSize); |
125 | } |
126 | |
127 | /// Return true if this is a smallvector which has not had dynamic |
128 | /// memory allocated for it. |
129 | bool isSmall() const { return this->BeginX == getFirstEl(); } |
130 | |
131 | /// Put this vector in a state of being small. |
132 | void resetToSmall() { |
133 | this->BeginX = getFirstEl(); |
134 | this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. |
135 | } |
136 | |
137 | /// Return true if V is an internal reference to the given range. |
138 | bool isReferenceToRange(const void *V, const void *First, const void *Last) const { |
139 | // Use std::less to avoid UB. |
140 | std::less<> LessThan; |
141 | return !LessThan(V, First) && LessThan(V, Last); |
142 | } |
143 | |
144 | /// Return true if V is an internal reference to this vector. |
145 | bool isReferenceToStorage(const void *V) const { |
146 | return isReferenceToRange(V, this->begin(), this->end()); |
147 | } |
148 | |
149 | /// Return true if First and Last form a valid (possibly empty) range in this |
150 | /// vector's storage. |
151 | bool isRangeInStorage(const void *First, const void *Last) const { |
152 | // Use std::less to avoid UB. |
153 | std::less<> LessThan; |
154 | return !LessThan(First, this->begin()) && !LessThan(Last, First) && |
155 | !LessThan(this->end(), Last); |
156 | } |
157 | |
158 | /// Return true unless Elt will be invalidated by resizing the vector to |
159 | /// NewSize. |
160 | bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) { |
161 | // Past the end. |
162 | if (LLVM_LIKELY(!isReferenceToStorage(Elt))__builtin_expect((bool)(!isReferenceToStorage(Elt)), true)) |
163 | return true; |
164 | |
165 | // Return false if Elt will be destroyed by shrinking. |
166 | if (NewSize <= this->size()) |
167 | return Elt < this->begin() + NewSize; |
168 | |
169 | // Return false if we need to grow. |
170 | return NewSize <= this->capacity(); |
171 | } |
172 | |
173 | /// Check whether Elt will be invalidated by resizing the vector to NewSize. |
174 | void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) { |
175 | assert(isSafeToReferenceAfterResize(Elt, NewSize) &&(static_cast <bool> (isSafeToReferenceAfterResize(Elt, NewSize ) && "Attempting to reference an element of the vector in an operation " "that invalidates it") ? void (0) : __assert_fail ("isSafeToReferenceAfterResize(Elt, NewSize) && \"Attempting to reference an element of the vector in an operation \" \"that invalidates it\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 177, __extension__ __PRETTY_FUNCTION__)) |
176 | "Attempting to reference an element of the vector in an operation "(static_cast <bool> (isSafeToReferenceAfterResize(Elt, NewSize ) && "Attempting to reference an element of the vector in an operation " "that invalidates it") ? void (0) : __assert_fail ("isSafeToReferenceAfterResize(Elt, NewSize) && \"Attempting to reference an element of the vector in an operation \" \"that invalidates it\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 177, __extension__ __PRETTY_FUNCTION__)) |
177 | "that invalidates it")(static_cast <bool> (isSafeToReferenceAfterResize(Elt, NewSize ) && "Attempting to reference an element of the vector in an operation " "that invalidates it") ? void (0) : __assert_fail ("isSafeToReferenceAfterResize(Elt, NewSize) && \"Attempting to reference an element of the vector in an operation \" \"that invalidates it\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 177, __extension__ __PRETTY_FUNCTION__)); |
178 | } |
179 | |
180 | /// Check whether Elt will be invalidated by increasing the size of the |
181 | /// vector by N. |
182 | void assertSafeToAdd(const void *Elt, size_t N = 1) { |
183 | this->assertSafeToReferenceAfterResize(Elt, this->size() + N); |
184 | } |
185 | |
186 | /// Check whether any part of the range will be invalidated by clearing. |
187 | void assertSafeToReferenceAfterClear(const T *From, const T *To) { |
188 | if (From == To) |
189 | return; |
190 | this->assertSafeToReferenceAfterResize(From, 0); |
191 | this->assertSafeToReferenceAfterResize(To - 1, 0); |
192 | } |
193 | template < |
194 | class ItTy, |
195 | std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value, |
196 | bool> = false> |
197 | void assertSafeToReferenceAfterClear(ItTy, ItTy) {} |
198 | |
199 | /// Check whether any part of the range will be invalidated by growing. |
200 | void assertSafeToAddRange(const T *From, const T *To) { |
201 | if (From == To) |
202 | return; |
203 | this->assertSafeToAdd(From, To - From); |
204 | this->assertSafeToAdd(To - 1, To - From); |
205 | } |
206 | template < |
207 | class ItTy, |
208 | std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value, |
209 | bool> = false> |
210 | void assertSafeToAddRange(ItTy, ItTy) {} |
211 | |
212 | /// Reserve enough space to add one element, and return the updated element |
213 | /// pointer in case it was a reference to the storage. |
214 | template <class U> |
215 | static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt, |
216 | size_t N) { |
217 | size_t NewSize = This->size() + N; |
218 | if (LLVM_LIKELY(NewSize <= This->capacity())__builtin_expect((bool)(NewSize <= This->capacity()), true )) |
219 | return &Elt; |
220 | |
221 | bool ReferencesStorage = false; |
222 | int64_t Index = -1; |
223 | if (!U::TakesParamByValue) { |
224 | if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))__builtin_expect((bool)(This->isReferenceToStorage(&Elt )), false)) { |
225 | ReferencesStorage = true; |
226 | Index = &Elt - This->begin(); |
227 | } |
228 | } |
229 | This->grow(NewSize); |
230 | return ReferencesStorage ? This->begin() + Index : &Elt; |
231 | } |
232 | |
233 | public: |
234 | using size_type = size_t; |
235 | using difference_type = ptrdiff_t; |
236 | using value_type = T; |
237 | using iterator = T *; |
238 | using const_iterator = const T *; |
239 | |
240 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; |
241 | using reverse_iterator = std::reverse_iterator<iterator>; |
242 | |
243 | using reference = T &; |
244 | using const_reference = const T &; |
245 | using pointer = T *; |
246 | using const_pointer = const T *; |
247 | |
248 | using Base::capacity; |
249 | using Base::empty; |
250 | using Base::size; |
251 | |
252 | // forward iterator creation methods. |
253 | iterator begin() { return (iterator)this->BeginX; } |
254 | const_iterator begin() const { return (const_iterator)this->BeginX; } |
255 | iterator end() { return begin() + size(); } |
256 | const_iterator end() const { return begin() + size(); } |
257 | |
258 | // reverse iterator creation methods. |
259 | reverse_iterator rbegin() { return reverse_iterator(end()); } |
260 | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } |
261 | reverse_iterator rend() { return reverse_iterator(begin()); } |
262 | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} |
263 | |
264 | size_type size_in_bytes() const { return size() * sizeof(T); } |
265 | size_type max_size() const { |
266 | return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T)); |
267 | } |
268 | |
269 | size_t capacity_in_bytes() const { return capacity() * sizeof(T); } |
270 | |
271 | /// Return a pointer to the vector's buffer, even if empty(). |
272 | pointer data() { return pointer(begin()); } |
273 | /// Return a pointer to the vector's buffer, even if empty(). |
274 | const_pointer data() const { return const_pointer(begin()); } |
275 | |
276 | reference operator[](size_type idx) { |
277 | assert(idx < size())(static_cast <bool> (idx < size()) ? void (0) : __assert_fail ("idx < size()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 277, __extension__ __PRETTY_FUNCTION__)); |
278 | return begin()[idx]; |
279 | } |
280 | const_reference operator[](size_type idx) const { |
281 | assert(idx < size())(static_cast <bool> (idx < size()) ? void (0) : __assert_fail ("idx < size()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 281, __extension__ __PRETTY_FUNCTION__)); |
282 | return begin()[idx]; |
283 | } |
284 | |
285 | reference front() { |
286 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 286, __extension__ __PRETTY_FUNCTION__)); |
287 | return begin()[0]; |
288 | } |
289 | const_reference front() const { |
290 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 290, __extension__ __PRETTY_FUNCTION__)); |
291 | return begin()[0]; |
292 | } |
293 | |
294 | reference back() { |
295 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 295, __extension__ __PRETTY_FUNCTION__)); |
296 | return end()[-1]; |
297 | } |
298 | const_reference back() const { |
299 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 299, __extension__ __PRETTY_FUNCTION__)); |
300 | return end()[-1]; |
301 | } |
302 | }; |
303 | |
304 | /// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put |
305 | /// method implementations that are designed to work with non-trivial T's. |
306 | /// |
307 | /// We approximate is_trivially_copyable with trivial move/copy construction and |
308 | /// trivial destruction. While the standard doesn't specify that you're allowed |
309 | /// copy these types with memcpy, there is no way for the type to observe this. |
310 | /// This catches the important case of std::pair<POD, POD>, which is not |
311 | /// trivially assignable. |
312 | template <typename T, bool = (is_trivially_copy_constructible<T>::value) && |
313 | (is_trivially_move_constructible<T>::value) && |
314 | std::is_trivially_destructible<T>::value> |
315 | class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { |
316 | friend class SmallVectorTemplateCommon<T>; |
317 | |
318 | protected: |
319 | static constexpr bool TakesParamByValue = false; |
320 | using ValueParamT = const T &; |
321 | |
322 | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} |
323 | |
324 | static void destroy_range(T *S, T *E) { |
325 | while (S != E) { |
326 | --E; |
327 | E->~T(); |
328 | } |
329 | } |
330 | |
331 | /// Move the range [I, E) into the uninitialized memory starting with "Dest", |
332 | /// constructing elements as needed. |
333 | template<typename It1, typename It2> |
334 | static void uninitialized_move(It1 I, It1 E, It2 Dest) { |
335 | std::uninitialized_copy(std::make_move_iterator(I), |
336 | std::make_move_iterator(E), Dest); |
337 | } |
338 | |
339 | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", |
340 | /// constructing elements as needed. |
341 | template<typename It1, typename It2> |
342 | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { |
343 | std::uninitialized_copy(I, E, Dest); |
344 | } |
345 | |
346 | /// Grow the allocated memory (without initializing new elements), doubling |
347 | /// the size of the allocated memory. Guarantees space for at least one more |
348 | /// element, or MinSize more elements if specified. |
349 | void grow(size_t MinSize = 0); |
350 | |
351 | /// Create a new allocation big enough for \p MinSize and pass back its size |
352 | /// in \p NewCapacity. This is the first section of \a grow(). |
353 | T *mallocForGrow(size_t MinSize, size_t &NewCapacity) { |
354 | return static_cast<T *>( |
355 | SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow( |
356 | MinSize, sizeof(T), NewCapacity)); |
357 | } |
358 | |
359 | /// Move existing elements over to the new allocation \p NewElts, the middle |
360 | /// section of \a grow(). |
361 | void moveElementsForGrow(T *NewElts); |
362 | |
363 | /// Transfer ownership of the allocation, finishing up \a grow(). |
364 | void takeAllocationForGrow(T *NewElts, size_t NewCapacity); |
365 | |
366 | /// Reserve enough space to add one element, and return the updated element |
367 | /// pointer in case it was a reference to the storage. |
368 | const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) { |
369 | return this->reserveForParamAndGetAddressImpl(this, Elt, N); |
370 | } |
371 | |
372 | /// Reserve enough space to add one element, and return the updated element |
373 | /// pointer in case it was a reference to the storage. |
374 | T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) { |
375 | return const_cast<T *>( |
376 | this->reserveForParamAndGetAddressImpl(this, Elt, N)); |
377 | } |
378 | |
379 | static T &&forward_value_param(T &&V) { return std::move(V); } |
380 | static const T &forward_value_param(const T &V) { return V; } |
381 | |
382 | void growAndAssign(size_t NumElts, const T &Elt) { |
383 | // Grow manually in case Elt is an internal reference. |
384 | size_t NewCapacity; |
385 | T *NewElts = mallocForGrow(NumElts, NewCapacity); |
386 | std::uninitialized_fill_n(NewElts, NumElts, Elt); |
387 | this->destroy_range(this->begin(), this->end()); |
388 | takeAllocationForGrow(NewElts, NewCapacity); |
389 | this->set_size(NumElts); |
390 | } |
391 | |
392 | template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) { |
393 | // Grow manually in case one of Args is an internal reference. |
394 | size_t NewCapacity; |
395 | T *NewElts = mallocForGrow(0, NewCapacity); |
396 | ::new ((void *)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...); |
397 | moveElementsForGrow(NewElts); |
398 | takeAllocationForGrow(NewElts, NewCapacity); |
399 | this->set_size(this->size() + 1); |
400 | return this->back(); |
401 | } |
402 | |
403 | public: |
404 | void push_back(const T &Elt) { |
405 | const T *EltPtr = reserveForParamAndGetAddress(Elt); |
406 | ::new ((void *)this->end()) T(*EltPtr); |
407 | this->set_size(this->size() + 1); |
408 | } |
409 | |
410 | void push_back(T &&Elt) { |
411 | T *EltPtr = reserveForParamAndGetAddress(Elt); |
412 | ::new ((void *)this->end()) T(::std::move(*EltPtr)); |
413 | this->set_size(this->size() + 1); |
414 | } |
415 | |
416 | void pop_back() { |
417 | this->set_size(this->size() - 1); |
418 | this->end()->~T(); |
419 | } |
420 | }; |
421 | |
422 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
423 | template <typename T, bool TriviallyCopyable> |
424 | void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) { |
425 | size_t NewCapacity; |
426 | T *NewElts = mallocForGrow(MinSize, NewCapacity); |
427 | moveElementsForGrow(NewElts); |
428 | takeAllocationForGrow(NewElts, NewCapacity); |
429 | } |
430 | |
431 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
432 | template <typename T, bool TriviallyCopyable> |
433 | void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow( |
434 | T *NewElts) { |
435 | // Move the elements over. |
436 | this->uninitialized_move(this->begin(), this->end(), NewElts); |
437 | |
438 | // Destroy the original elements. |
439 | destroy_range(this->begin(), this->end()); |
440 | } |
441 | |
442 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
443 | template <typename T, bool TriviallyCopyable> |
444 | void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow( |
445 | T *NewElts, size_t NewCapacity) { |
446 | // If this wasn't grown from the inline copy, deallocate the old space. |
447 | if (!this->isSmall()) |
448 | free(this->begin()); |
449 | |
450 | this->BeginX = NewElts; |
451 | this->Capacity = NewCapacity; |
452 | } |
453 | |
454 | /// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put |
455 | /// method implementations that are designed to work with trivially copyable |
456 | /// T's. This allows using memcpy in place of copy/move construction and |
457 | /// skipping destruction. |
458 | template <typename T> |
459 | class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { |
460 | friend class SmallVectorTemplateCommon<T>; |
461 | |
462 | protected: |
463 | /// True if it's cheap enough to take parameters by value. Doing so avoids |
464 | /// overhead related to mitigations for reference invalidation. |
465 | static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *); |
466 | |
467 | /// Either const T& or T, depending on whether it's cheap enough to take |
468 | /// parameters by value. |
469 | using ValueParamT = |
470 | typename std::conditional<TakesParamByValue, T, const T &>::type; |
471 | |
472 | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} |
473 | |
474 | // No need to do a destroy loop for POD's. |
475 | static void destroy_range(T *, T *) {} |
476 | |
477 | /// Move the range [I, E) onto the uninitialized memory |
478 | /// starting with "Dest", constructing elements into it as needed. |
479 | template<typename It1, typename It2> |
480 | static void uninitialized_move(It1 I, It1 E, It2 Dest) { |
481 | // Just do a copy. |
482 | uninitialized_copy(I, E, Dest); |
483 | } |
484 | |
485 | /// Copy the range [I, E) onto the uninitialized memory |
486 | /// starting with "Dest", constructing elements into it as needed. |
487 | template<typename It1, typename It2> |
488 | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { |
489 | // Arbitrary iterator types; just use the basic implementation. |
490 | std::uninitialized_copy(I, E, Dest); |
491 | } |
492 | |
493 | /// Copy the range [I, E) onto the uninitialized memory |
494 | /// starting with "Dest", constructing elements into it as needed. |
495 | template <typename T1, typename T2> |
496 | static void uninitialized_copy( |
497 | T1 *I, T1 *E, T2 *Dest, |
498 | std::enable_if_t<std::is_same<typename std::remove_const<T1>::type, |
499 | T2>::value> * = nullptr) { |
500 | // Use memcpy for PODs iterated by pointers (which includes SmallVector |
501 | // iterators): std::uninitialized_copy optimizes to memmove, but we can |
502 | // use memcpy here. Note that I and E are iterators and thus might be |
503 | // invalid for memcpy if they are equal. |
504 | if (I != E) |
505 | memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T)); |
506 | } |
507 | |
508 | /// Double the size of the allocated memory, guaranteeing space for at |
509 | /// least one more element or MinSize if specified. |
510 | void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); } |
511 | |
512 | /// Reserve enough space to add one element, and return the updated element |
513 | /// pointer in case it was a reference to the storage. |
514 | const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) { |
515 | return this->reserveForParamAndGetAddressImpl(this, Elt, N); |
516 | } |
517 | |
518 | /// Reserve enough space to add one element, and return the updated element |
519 | /// pointer in case it was a reference to the storage. |
520 | T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) { |
521 | return const_cast<T *>( |
522 | this->reserveForParamAndGetAddressImpl(this, Elt, N)); |
523 | } |
524 | |
525 | /// Copy \p V or return a reference, depending on \a ValueParamT. |
526 | static ValueParamT forward_value_param(ValueParamT V) { return V; } |
527 | |
528 | void growAndAssign(size_t NumElts, T Elt) { |
529 | // Elt has been copied in case it's an internal reference, side-stepping |
530 | // reference invalidation problems without losing the realloc optimization. |
531 | this->set_size(0); |
532 | this->grow(NumElts); |
533 | std::uninitialized_fill_n(this->begin(), NumElts, Elt); |
534 | this->set_size(NumElts); |
535 | } |
536 | |
537 | template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) { |
538 | // Use push_back with a copy in case Args has an internal reference, |
539 | // side-stepping reference invalidation problems without losing the realloc |
540 | // optimization. |
541 | push_back(T(std::forward<ArgTypes>(Args)...)); |
542 | return this->back(); |
543 | } |
544 | |
545 | public: |
546 | void push_back(ValueParamT Elt) { |
547 | const T *EltPtr = reserveForParamAndGetAddress(Elt); |
548 | memcpy(reinterpret_cast<void *>(this->end()), EltPtr, sizeof(T)); |
549 | this->set_size(this->size() + 1); |
550 | } |
551 | |
552 | void pop_back() { this->set_size(this->size() - 1); } |
553 | }; |
554 | |
555 | /// This class consists of common code factored out of the SmallVector class to |
556 | /// reduce code duplication based on the SmallVector 'N' template parameter. |
557 | template <typename T> |
558 | class SmallVectorImpl : public SmallVectorTemplateBase<T> { |
559 | using SuperClass = SmallVectorTemplateBase<T>; |
560 | |
561 | public: |
562 | using iterator = typename SuperClass::iterator; |
563 | using const_iterator = typename SuperClass::const_iterator; |
564 | using reference = typename SuperClass::reference; |
565 | using size_type = typename SuperClass::size_type; |
566 | |
567 | protected: |
568 | using SmallVectorTemplateBase<T>::TakesParamByValue; |
569 | using ValueParamT = typename SuperClass::ValueParamT; |
570 | |
571 | // Default ctor - Initialize to empty. |
572 | explicit SmallVectorImpl(unsigned N) |
573 | : SmallVectorTemplateBase<T>(N) {} |
574 | |
575 | public: |
576 | SmallVectorImpl(const SmallVectorImpl &) = delete; |
577 | |
578 | ~SmallVectorImpl() { |
579 | // Subclass has already destructed this vector's elements. |
580 | // If this wasn't grown from the inline copy, deallocate the old space. |
581 | if (!this->isSmall()) |
582 | free(this->begin()); |
583 | } |
584 | |
585 | void clear() { |
586 | this->destroy_range(this->begin(), this->end()); |
587 | this->Size = 0; |
588 | } |
589 | |
590 | private: |
591 | template <bool ForOverwrite> void resizeImpl(size_type N) { |
592 | if (N < this->size()) { |
593 | this->pop_back_n(this->size() - N); |
594 | } else if (N > this->size()) { |
595 | this->reserve(N); |
596 | for (auto I = this->end(), E = this->begin() + N; I != E; ++I) |
597 | if (ForOverwrite) |
598 | new (&*I) T; |
599 | else |
600 | new (&*I) T(); |
601 | this->set_size(N); |
602 | } |
603 | } |
604 | |
605 | public: |
606 | void resize(size_type N) { resizeImpl<false>(N); } |
607 | |
608 | /// Like resize, but \ref T is POD, the new values won't be initialized. |
609 | void resize_for_overwrite(size_type N) { resizeImpl<true>(N); } |
610 | |
611 | void resize(size_type N, ValueParamT NV) { |
612 | if (N == this->size()) |
613 | return; |
614 | |
615 | if (N < this->size()) { |
616 | this->pop_back_n(this->size() - N); |
617 | return; |
618 | } |
619 | |
620 | // N > this->size(). Defer to append. |
621 | this->append(N - this->size(), NV); |
622 | } |
623 | |
624 | void reserve(size_type N) { |
625 | if (this->capacity() < N) |
626 | this->grow(N); |
627 | } |
628 | |
629 | void pop_back_n(size_type NumItems) { |
630 | assert(this->size() >= NumItems)(static_cast <bool> (this->size() >= NumItems) ? void (0) : __assert_fail ("this->size() >= NumItems", "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 630, __extension__ __PRETTY_FUNCTION__)); |
631 | this->destroy_range(this->end() - NumItems, this->end()); |
632 | this->set_size(this->size() - NumItems); |
633 | } |
634 | |
635 | LLVM_NODISCARD[[clang::warn_unused_result]] T pop_back_val() { |
636 | T Result = ::std::move(this->back()); |
637 | this->pop_back(); |
638 | return Result; |
639 | } |
640 | |
641 | void swap(SmallVectorImpl &RHS); |
642 | |
643 | /// Add the specified range to the end of the SmallVector. |
644 | template <typename in_iter, |
645 | typename = std::enable_if_t<std::is_convertible< |
646 | typename std::iterator_traits<in_iter>::iterator_category, |
647 | std::input_iterator_tag>::value>> |
648 | void append(in_iter in_start, in_iter in_end) { |
649 | this->assertSafeToAddRange(in_start, in_end); |
650 | size_type NumInputs = std::distance(in_start, in_end); |
651 | this->reserve(this->size() + NumInputs); |
652 | this->uninitialized_copy(in_start, in_end, this->end()); |
653 | this->set_size(this->size() + NumInputs); |
654 | } |
655 | |
656 | /// Append \p NumInputs copies of \p Elt to the end. |
657 | void append(size_type NumInputs, ValueParamT Elt) { |
658 | const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs); |
659 | std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr); |
660 | this->set_size(this->size() + NumInputs); |
661 | } |
662 | |
663 | void append(std::initializer_list<T> IL) { |
664 | append(IL.begin(), IL.end()); |
665 | } |
666 | |
667 | void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); } |
668 | |
669 | void assign(size_type NumElts, ValueParamT Elt) { |
670 | // Note that Elt could be an internal reference. |
671 | if (NumElts > this->capacity()) { |
672 | this->growAndAssign(NumElts, Elt); |
673 | return; |
674 | } |
675 | |
676 | // Assign over existing elements. |
677 | std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt); |
678 | if (NumElts > this->size()) |
679 | std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt); |
680 | else if (NumElts < this->size()) |
681 | this->destroy_range(this->begin() + NumElts, this->end()); |
682 | this->set_size(NumElts); |
683 | } |
684 | |
685 | // FIXME: Consider assigning over existing elements, rather than clearing & |
686 | // re-initializing them - for all assign(...) variants. |
687 | |
688 | template <typename in_iter, |
689 | typename = std::enable_if_t<std::is_convertible< |
690 | typename std::iterator_traits<in_iter>::iterator_category, |
691 | std::input_iterator_tag>::value>> |
692 | void assign(in_iter in_start, in_iter in_end) { |
693 | this->assertSafeToReferenceAfterClear(in_start, in_end); |
694 | clear(); |
695 | append(in_start, in_end); |
696 | } |
697 | |
698 | void assign(std::initializer_list<T> IL) { |
699 | clear(); |
700 | append(IL); |
701 | } |
702 | |
703 | void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); } |
704 | |
705 | iterator erase(const_iterator CI) { |
706 | // Just cast away constness because this is a non-const member function. |
707 | iterator I = const_cast<iterator>(CI); |
708 | |
709 | assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(CI) && \"Iterator to erase is out of bounds.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 709, __extension__ __PRETTY_FUNCTION__)); |
710 | |
711 | iterator N = I; |
712 | // Shift all elts down one. |
713 | std::move(I+1, this->end(), I); |
714 | // Drop the last elt. |
715 | this->pop_back(); |
716 | return(N); |
717 | } |
718 | |
719 | iterator erase(const_iterator CS, const_iterator CE) { |
720 | // Just cast away constness because this is a non-const member function. |
721 | iterator S = const_cast<iterator>(CS); |
722 | iterator E = const_cast<iterator>(CE); |
723 | |
724 | assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.")(static_cast <bool> (this->isRangeInStorage(S, E) && "Range to erase is out of bounds.") ? void (0) : __assert_fail ("this->isRangeInStorage(S, E) && \"Range to erase is out of bounds.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 724, __extension__ __PRETTY_FUNCTION__)); |
725 | |
726 | iterator N = S; |
727 | // Shift all elts down. |
728 | iterator I = std::move(E, this->end(), S); |
729 | // Drop the last elts. |
730 | this->destroy_range(I, this->end()); |
731 | this->set_size(I - this->begin()); |
732 | return(N); |
733 | } |
734 | |
735 | private: |
736 | template <class ArgType> iterator insert_one_impl(iterator I, ArgType &&Elt) { |
737 | // Callers ensure that ArgType is derived from T. |
738 | static_assert( |
739 | std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>, |
740 | T>::value, |
741 | "ArgType must be derived from T!"); |
742 | |
743 | if (I == this->end()) { // Important special case for empty vector. |
744 | this->push_back(::std::forward<ArgType>(Elt)); |
745 | return this->end()-1; |
746 | } |
747 | |
748 | assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(I) && \"Insertion iterator is out of bounds.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 748, __extension__ __PRETTY_FUNCTION__)); |
749 | |
750 | // Grow if necessary. |
751 | size_t Index = I - this->begin(); |
752 | std::remove_reference_t<ArgType> *EltPtr = |
753 | this->reserveForParamAndGetAddress(Elt); |
754 | I = this->begin() + Index; |
755 | |
756 | ::new ((void*) this->end()) T(::std::move(this->back())); |
757 | // Push everything else over. |
758 | std::move_backward(I, this->end()-1, this->end()); |
759 | this->set_size(this->size() + 1); |
760 | |
761 | // If we just moved the element we're inserting, be sure to update |
762 | // the reference (never happens if TakesParamByValue). |
763 | static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value, |
764 | "ArgType must be 'T' when taking by value!"); |
765 | if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end())) |
766 | ++EltPtr; |
767 | |
768 | *I = ::std::forward<ArgType>(*EltPtr); |
769 | return I; |
770 | } |
771 | |
772 | public: |
773 | iterator insert(iterator I, T &&Elt) { |
774 | return insert_one_impl(I, this->forward_value_param(std::move(Elt))); |
775 | } |
776 | |
777 | iterator insert(iterator I, const T &Elt) { |
778 | return insert_one_impl(I, this->forward_value_param(Elt)); |
779 | } |
780 | |
781 | iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) { |
782 | // Convert iterator to elt# to avoid invalidating iterator when we reserve() |
783 | size_t InsertElt = I - this->begin(); |
784 | |
785 | if (I == this->end()) { // Important special case for empty vector. |
786 | append(NumToInsert, Elt); |
787 | return this->begin()+InsertElt; |
788 | } |
789 | |
790 | assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(I) && \"Insertion iterator is out of bounds.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 790, __extension__ __PRETTY_FUNCTION__)); |
791 | |
792 | // Ensure there is enough space, and get the (maybe updated) address of |
793 | // Elt. |
794 | const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert); |
795 | |
796 | // Uninvalidate the iterator. |
797 | I = this->begin()+InsertElt; |
798 | |
799 | // If there are more elements between the insertion point and the end of the |
800 | // range than there are being inserted, we can use a simple approach to |
801 | // insertion. Since we already reserved space, we know that this won't |
802 | // reallocate the vector. |
803 | if (size_t(this->end()-I) >= NumToInsert) { |
804 | T *OldEnd = this->end(); |
805 | append(std::move_iterator<iterator>(this->end() - NumToInsert), |
806 | std::move_iterator<iterator>(this->end())); |
807 | |
808 | // Copy the existing elements that get replaced. |
809 | std::move_backward(I, OldEnd-NumToInsert, OldEnd); |
810 | |
811 | // If we just moved the element we're inserting, be sure to update |
812 | // the reference (never happens if TakesParamByValue). |
813 | if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end()) |
814 | EltPtr += NumToInsert; |
815 | |
816 | std::fill_n(I, NumToInsert, *EltPtr); |
817 | return I; |
818 | } |
819 | |
820 | // Otherwise, we're inserting more elements than exist already, and we're |
821 | // not inserting at the end. |
822 | |
823 | // Move over the elements that we're about to overwrite. |
824 | T *OldEnd = this->end(); |
825 | this->set_size(this->size() + NumToInsert); |
826 | size_t NumOverwritten = OldEnd-I; |
827 | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); |
828 | |
829 | // If we just moved the element we're inserting, be sure to update |
830 | // the reference (never happens if TakesParamByValue). |
831 | if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end()) |
832 | EltPtr += NumToInsert; |
833 | |
834 | // Replace the overwritten part. |
835 | std::fill_n(I, NumOverwritten, *EltPtr); |
836 | |
837 | // Insert the non-overwritten middle part. |
838 | std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr); |
839 | return I; |
840 | } |
841 | |
842 | template <typename ItTy, |
843 | typename = std::enable_if_t<std::is_convertible< |
844 | typename std::iterator_traits<ItTy>::iterator_category, |
845 | std::input_iterator_tag>::value>> |
846 | iterator insert(iterator I, ItTy From, ItTy To) { |
847 | // Convert iterator to elt# to avoid invalidating iterator when we reserve() |
848 | size_t InsertElt = I - this->begin(); |
849 | |
850 | if (I == this->end()) { // Important special case for empty vector. |
851 | append(From, To); |
852 | return this->begin()+InsertElt; |
853 | } |
854 | |
855 | assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(I) && \"Insertion iterator is out of bounds.\"" , "/build/llvm-toolchain-snapshot-13~++20210506100649+6304c0836a4d/llvm/include/llvm/ADT/SmallVector.h" , 855, __extension__ __PRETTY_FUNCTION__)); |
856 | |
857 | // Check that the reserve that follows doesn't invalidate the iterators. |
858 | this->assertSafeToAddRange(From, To); |
859 | |
860 | size_t NumToInsert = std::distance(From, To); |
861 | |
862 | // Ensure there is enough space. |
863 | reserve(this->size() + NumToInsert); |
864 | |
865 | // Uninvalidate the iterator. |
866 | I = this->begin()+InsertElt; |
867 | |
868 | // If there are more elements between the insertion point and the end of the |
869 | // range than there are being inserted, we can use a simple approach to |
870 | // insertion. Since we already reserved space, we know that this won't |
871 | // reallocate the vector. |
872 | if (size_t(this->end()-I) >= NumToInsert) { |
873 | T *OldEnd = this->end(); |
874 | append(std::move_iterator<iterator>(this->end() - NumToInsert), |
875 | std::move_iterator<iterator>(this->end())); |
876 | |
877 | // Copy the existing elements that get replaced. |
878 | std::move_backward(I, OldEnd-NumToInsert, OldEnd); |
879 | |
880 | std::copy(From, To, I); |
881 | return I; |
882 | } |
883 | |
884 | // Otherwise, we're inserting more elements than exist already, and we're |
885 | // not inserting at the end. |
886 | |
887 | // Move over the elements that we're about to overwrite. |
888 | T *OldEnd = this->end(); |
889 | this->set_size(this->size() + NumToInsert); |
890 | size_t NumOverwritten = OldEnd-I; |
891 | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); |
892 | |
893 | // Replace the overwritten part. |
894 | for (T *J = I; NumOverwritten > 0; --NumOverwritten) { |
895 | *J = *From; |
896 | ++J; ++From; |
897 | } |
898 | |
899 | // Insert the non-overwritten middle part. |
900 | this->uninitialized_copy(From, To, OldEnd); |
901 | return I; |
902 | } |
903 | |
904 | void insert(iterator I, std::initializer_list<T> IL) { |
905 | insert(I, IL.begin(), IL.end()); |
906 | } |
907 | |
908 | template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) { |
909 | if (LLVM_UNLIKELY(this->size() >= this->capacity())__builtin_expect((bool)(this->size() >= this->capacity ()), false)) |
910 | return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...); |
911 | |
912 | ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); |
913 | this->set_size(this->size() + 1); |
914 | return this->back(); |
915 | } |
916 | |
917 | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); |
918 | |
919 | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); |
920 | |
921 | bool operator==(const SmallVectorImpl &RHS) const { |
922 | if (this->size() != RHS.size()) return false; |
923 | return std::equal(this->begin(), this->end(), RHS.begin()); |
924 | } |
925 | bool operator!=(const SmallVectorImpl &RHS) const { |
926 | return !(*this == RHS); |
927 | } |
928 | |
929 | bool operator<(const SmallVectorImpl &RHS) const { |
930 | return std::lexicographical_compare(this->begin(), this->end(), |
931 | RHS.begin(), RHS.end()); |
932 | } |
933 | }; |
934 | |
935 | template <typename T> |
936 | void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { |
937 | if (this == &RHS) return; |
938 | |
939 | // We can only avoid copying elements if neither vector is small. |
940 | if (!this->isSmall() && !RHS.isSmall()) { |
941 | std::swap(this->BeginX, RHS.BeginX); |
942 | std::swap(this->Size, RHS.Size); |
943 | std::swap(this->Capacity, RHS.Capacity); |
944 | return; |
945 | } |
946 | this->reserve(RHS.size()); |
947 | RHS.reserve(this->size()); |
948 | |
949 | // Swap the shared elements. |
950 | size_t NumShared = this->size(); |
951 | if (NumShared > RHS.size()) NumShared = RHS.size(); |
952 | for (size_type i = 0; i != NumShared; ++i) |
953 | std::swap((*this)[i], RHS[i]); |
954 | |
955 | // Copy over the extra elts. |
956 | if (this->size() > RHS.size()) { |
957 | size_t EltDiff = this->size() - RHS.size(); |
958 | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); |
959 | RHS.set_size(RHS.size() + EltDiff); |
960 | this->destroy_range(this->begin()+NumShared, this->end()); |
961 | this->set_size(NumShared); |
962 | } else if (RHS.size() > this->size()) { |
963 | size_t EltDiff = RHS.size() - this->size(); |
964 | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); |
965 | this->set_size(this->size() + EltDiff); |
966 | this->destroy_range(RHS.begin()+NumShared, RHS.end()); |
967 | RHS.set_size(NumShared); |
968 | } |
969 | } |
970 | |
971 | template <typename T> |
972 | SmallVectorImpl<T> &SmallVectorImpl<T>:: |
973 | operator=(const SmallVectorImpl<T> &RHS) { |
974 | // Avoid self-assignment. |
975 | if (this == &RHS) return *this; |
976 | |
977 | // If we already have sufficient space, assign the common elements, then |
978 | // destroy any excess. |
979 | size_t RHSSize = RHS.size(); |
980 | size_t CurSize = this->size(); |
981 | if (CurSize >= RHSSize) { |
982 | // Assign common elements. |
983 | iterator NewEnd; |
984 | if (RHSSize) |
985 | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); |
986 | else |
987 | NewEnd = this->begin(); |
988 | |
989 | // Destroy excess elements. |
990 | this->destroy_range(NewEnd, this->end()); |
991 | |
992 | // Trim. |
993 | this->set_size(RHSSize); |
994 | return *this; |
995 | } |
996 | |
997 | // If we have to grow to have enough elements, destroy the current elements. |
998 | // This allows us to avoid copying them during the grow. |
999 | // FIXME: don't do this if they're efficiently moveable. |
1000 | if (this->capacity() < RHSSize) { |
1001 | // Destroy current elements. |
1002 | this->clear(); |
1003 | CurSize = 0; |
1004 | this->grow(RHSSize); |
1005 | } else if (CurSize) { |
1006 | // Otherwise, use assignment for the already-constructed elements. |
1007 | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); |
1008 | } |
1009 | |
1010 | // Copy construct the new elements in place. |
1011 | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), |
1012 | this->begin()+CurSize); |
1013 | |
1014 | // Set end. |
1015 | this->set_size(RHSSize); |
1016 | return *this; |
1017 | } |
1018 | |
1019 | template <typename T> |
1020 | SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { |
1021 | // Avoid self-assignment. |
1022 | if (this == &RHS) return *this; |
1023 | |
1024 | // If the RHS isn't small, clear this vector and then steal its buffer. |
1025 | if (!RHS.isSmall()) { |
1026 | this->destroy_range(this->begin(), this->end()); |
1027 | if (!this->isSmall()) free(this->begin()); |
1028 | this->BeginX = RHS.BeginX; |
1029 | this->Size = RHS.Size; |
1030 | this->Capacity = RHS.Capacity; |
1031 | RHS.resetToSmall(); |
1032 | return *this; |
1033 | } |
1034 | |
1035 | // If we already have sufficient space, assign the common elements, then |
1036 | // destroy any excess. |
1037 | size_t RHSSize = RHS.size(); |
1038 | size_t CurSize = this->size(); |
1039 | if (CurSize >= RHSSize) { |
1040 | // Assign common elements. |
1041 | iterator NewEnd = this->begin(); |
1042 | if (RHSSize) |
1043 | NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd); |
1044 | |
1045 | // Destroy excess elements and trim the bounds. |
1046 | this->destroy_range(NewEnd, this->end()); |
1047 | this->set_size(RHSSize); |
1048 | |
1049 | // Clear the RHS. |
1050 | RHS.clear(); |
1051 | |
1052 | return *this; |
1053 | } |
1054 | |
1055 | // If we have to grow to have enough elements, destroy the current elements. |
1056 | // This allows us to avoid copying them during the grow. |
1057 | // FIXME: this may not actually make any sense if we can efficiently move |
1058 | // elements. |
1059 | if (this->capacity() < RHSSize) { |
1060 | // Destroy current elements. |
1061 | this->clear(); |
1062 | CurSize = 0; |
1063 | this->grow(RHSSize); |
1064 | } else if (CurSize) { |
1065 | // Otherwise, use assignment for the already-constructed elements. |
1066 | std::move(RHS.begin(), RHS.begin()+CurSize, this->begin()); |
1067 | } |
1068 | |
1069 | // Move-construct the new elements in place. |
1070 | this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), |
1071 | this->begin()+CurSize); |
1072 | |
1073 | // Set end. |
1074 | this->set_size(RHSSize); |
1075 | |
1076 | RHS.clear(); |
1077 | return *this; |
1078 | } |
1079 | |
1080 | /// Storage for the SmallVector elements. This is specialized for the N=0 case |
1081 | /// to avoid allocating unnecessary storage. |
1082 | template <typename T, unsigned N> |
1083 | struct SmallVectorStorage { |
1084 | alignas(T) char InlineElts[N * sizeof(T)]; |
1085 | }; |
1086 | |
1087 | /// We need the storage to be properly aligned even for small-size of 0 so that |
1088 | /// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is |
1089 | /// well-defined. |
1090 | template <typename T> struct alignas(T) SmallVectorStorage<T, 0> {}; |
1091 | |
1092 | /// Forward declaration of SmallVector so that |
1093 | /// calculateSmallVectorDefaultInlinedElements can reference |
1094 | /// `sizeof(SmallVector<T, 0>)`. |
1095 | template <typename T, unsigned N> class LLVM_GSL_OWNER[[gsl::Owner]] SmallVector; |
1096 | |
1097 | /// Helper class for calculating the default number of inline elements for |
1098 | /// `SmallVector<T>`. |
1099 | /// |
1100 | /// This should be migrated to a constexpr function when our minimum |
1101 | /// compiler support is enough for multi-statement constexpr functions. |
1102 | template <typename T> struct CalculateSmallVectorDefaultInlinedElements { |
1103 | // Parameter controlling the default number of inlined elements |
1104 | // for `SmallVector<T>`. |
1105 | // |
1106 | // The default number of inlined elements ensures that |
1107 | // 1. There is at least one inlined element. |
1108 | // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless |
1109 | // it contradicts 1. |
1110 | static constexpr size_t kPreferredSmallVectorSizeof = 64; |
1111 | |
1112 | // static_assert that sizeof(T) is not "too big". |
1113 | // |
1114 | // Because our policy guarantees at least one inlined element, it is possible |
1115 | // for an arbitrarily large inlined element to allocate an arbitrarily large |
1116 | // amount of inline storage. We generally consider it an antipattern for a |
1117 | // SmallVector to allocate an excessive amount of inline storage, so we want |
1118 | // to call attention to these cases and make sure that users are making an |
1119 | // intentional decision if they request a lot of inline storage. |
1120 | // |
1121 | // We want this assertion to trigger in pathological cases, but otherwise |
1122 | // not be too easy to hit. To accomplish that, the cutoff is actually somewhat |
1123 | // larger than kPreferredSmallVectorSizeof (otherwise, |
1124 | // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that |
1125 | // pattern seems useful in practice). |
1126 | // |
1127 | // One wrinkle is that this assertion is in theory non-portable, since |
1128 | // sizeof(T) is in general platform-dependent. However, we don't expect this |
1129 | // to be much of an issue, because most LLVM development happens on 64-bit |
1130 | // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for |
1131 | // 32-bit hosts, dodging the issue. The reverse situation, where development |
1132 | // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a |
1133 | // 64-bit host, is expected to be very rare. |
1134 | static_assert( |
1135 | sizeof(T) <= 256, |
1136 | "You are trying to use a default number of inlined elements for " |
1137 | "`SmallVector<T>` but `sizeof(T)` is really big! Please use an " |
1138 | "explicit number of inlined elements with `SmallVector<T, N>` to make " |
1139 | "sure you really want that much inline storage."); |
1140 | |
1141 | // Discount the size of the header itself when calculating the maximum inline |
1142 | // bytes. |
1143 | static constexpr size_t PreferredInlineBytes = |
1144 | kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>); |
1145 | static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T); |
1146 | static constexpr size_t value = |
1147 | NumElementsThatFit == 0 ? 1 : NumElementsThatFit; |
1148 | }; |
1149 | |
1150 | /// This is a 'vector' (really, a variable-sized array), optimized |
1151 | /// for the case when the array is small. It contains some number of elements |
1152 | /// in-place, which allows it to avoid heap allocation when the actual number of |
1153 | /// elements is below that threshold. This allows normal "small" cases to be |
1154 | /// fast without losing generality for large inputs. |
1155 | /// |
1156 | /// \note |
1157 | /// In the absence of a well-motivated choice for the number of inlined |
1158 | /// elements \p N, it is recommended to use \c SmallVector<T> (that is, |
1159 | /// omitting the \p N). This will choose a default number of inlined elements |
1160 | /// reasonable for allocation on the stack (for example, trying to keep \c |
1161 | /// sizeof(SmallVector<T>) around 64 bytes). |
1162 | /// |
1163 | /// \warning This does not attempt to be exception safe. |
1164 | /// |
1165 | /// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h |
1166 | template <typename T, |
1167 | unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value> |
1168 | class LLVM_GSL_OWNER[[gsl::Owner]] SmallVector : public SmallVectorImpl<T>, |
1169 | SmallVectorStorage<T, N> { |
1170 | public: |
1171 | SmallVector() : SmallVectorImpl<T>(N) {} |
1172 | |
1173 | ~SmallVector() { |
1174 | // Destroy the constructed elements in the vector. |
1175 | this->destroy_range(this->begin(), this->end()); |
1176 | } |
1177 | |
1178 | explicit SmallVector(size_t Size, const T &Value = T()) |
1179 | : SmallVectorImpl<T>(N) { |
1180 | this->assign(Size, Value); |
1181 | } |
1182 | |
1183 | template <typename ItTy, |
1184 | typename = std::enable_if_t<std::is_convertible< |
1185 | typename std::iterator_traits<ItTy>::iterator_category, |
1186 | std::input_iterator_tag>::value>> |
1187 | SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) { |
1188 | this->append(S, E); |
1189 | } |
1190 | |
1191 | template <typename RangeTy> |
1192 | explicit SmallVector(const iterator_range<RangeTy> &R) |
1193 | : SmallVectorImpl<T>(N) { |
1194 | this->append(R.begin(), R.end()); |
1195 | } |
1196 | |
1197 | SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) { |
1198 | this->assign(IL); |
1199 | } |
1200 | |
1201 | SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { |
1202 | if (!RHS.empty()) |
1203 | SmallVectorImpl<T>::operator=(RHS); |
1204 | } |
1205 | |
1206 | SmallVector &operator=(const SmallVector &RHS) { |
1207 | SmallVectorImpl<T>::operator=(RHS); |
1208 | return *this; |
1209 | } |
1210 | |
1211 | SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) { |
1212 | if (!RHS.empty()) |
1213 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1214 | } |
1215 | |
1216 | SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) { |
1217 | if (!RHS.empty()) |
1218 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1219 | } |
1220 | |
1221 | SmallVector &operator=(SmallVector &&RHS) { |
1222 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1223 | return *this; |
1224 | } |
1225 | |
1226 | SmallVector &operator=(SmallVectorImpl<T> &&RHS) { |
1227 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1228 | return *this; |
1229 | } |
1230 | |
1231 | SmallVector &operator=(std::initializer_list<T> IL) { |
1232 | this->assign(IL); |
1233 | return *this; |
1234 | } |
1235 | }; |
1236 | |
1237 | template <typename T, unsigned N> |
1238 | inline size_t capacity_in_bytes(const SmallVector<T, N> &X) { |
1239 | return X.capacity_in_bytes(); |
1240 | } |
1241 | |
1242 | /// Given a range of type R, iterate the entire range and return a |
1243 | /// SmallVector with elements of the vector. This is useful, for example, |
1244 | /// when you want to iterate a range and then sort the results. |
1245 | template <unsigned Size, typename R> |
1246 | SmallVector<typename std::remove_const<typename std::remove_reference< |
1247 | decltype(*std::begin(std::declval<R &>()))>::type>::type, |
1248 | Size> |
1249 | to_vector(R &&Range) { |
1250 | return {std::begin(Range), std::end(Range)}; |
1251 | } |
1252 | |
1253 | } // end namespace llvm |
1254 | |
1255 | namespace std { |
1256 | |
1257 | /// Implement std::swap in terms of SmallVector swap. |
1258 | template<typename T> |
1259 | inline void |
1260 | swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { |
1261 | LHS.swap(RHS); |
1262 | } |
1263 | |
1264 | /// Implement std::swap in terms of SmallVector swap. |
1265 | template<typename T, unsigned N> |
1266 | inline void |
1267 | swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { |
1268 | LHS.swap(RHS); |
1269 | } |
1270 | |
1271 | } // end namespace std |
1272 | |
1273 | #endif // LLVM_ADT_SMALLVECTOR_H |