/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- Clang.cpp - Clang+LLVM ToolChain Implementations --------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "Clang.h" |
10 | | #include "AMDGPU.h" |
11 | | #include "Arch/AArch64.h" |
12 | | #include "Arch/ARM.h" |
13 | | #include "Arch/CSKY.h" |
14 | | #include "Arch/LoongArch.h" |
15 | | #include "Arch/M68k.h" |
16 | | #include "Arch/Mips.h" |
17 | | #include "Arch/PPC.h" |
18 | | #include "Arch/RISCV.h" |
19 | | #include "Arch/Sparc.h" |
20 | | #include "Arch/SystemZ.h" |
21 | | #include "Arch/VE.h" |
22 | | #include "Arch/X86.h" |
23 | | #include "CommonArgs.h" |
24 | | #include "Hexagon.h" |
25 | | #include "MSP430.h" |
26 | | #include "PS4CPU.h" |
27 | | #include "clang/Basic/CLWarnings.h" |
28 | | #include "clang/Basic/CharInfo.h" |
29 | | #include "clang/Basic/CodeGenOptions.h" |
30 | | #include "clang/Basic/HeaderInclude.h" |
31 | | #include "clang/Basic/LangOptions.h" |
32 | | #include "clang/Basic/MakeSupport.h" |
33 | | #include "clang/Basic/ObjCRuntime.h" |
34 | | #include "clang/Basic/Version.h" |
35 | | #include "clang/Config/config.h" |
36 | | #include "clang/Driver/Action.h" |
37 | | #include "clang/Driver/Distro.h" |
38 | | #include "clang/Driver/DriverDiagnostic.h" |
39 | | #include "clang/Driver/InputInfo.h" |
40 | | #include "clang/Driver/Options.h" |
41 | | #include "clang/Driver/SanitizerArgs.h" |
42 | | #include "clang/Driver/Types.h" |
43 | | #include "clang/Driver/XRayArgs.h" |
44 | | #include "llvm/ADT/SmallSet.h" |
45 | | #include "llvm/ADT/StringExtras.h" |
46 | | #include "llvm/Config/llvm-config.h" |
47 | | #include "llvm/Option/ArgList.h" |
48 | | #include "llvm/Support/CodeGen.h" |
49 | | #include "llvm/Support/Compiler.h" |
50 | | #include "llvm/Support/Compression.h" |
51 | | #include "llvm/Support/Error.h" |
52 | | #include "llvm/Support/FileSystem.h" |
53 | | #include "llvm/Support/Path.h" |
54 | | #include "llvm/Support/Process.h" |
55 | | #include "llvm/Support/RISCVISAInfo.h" |
56 | | #include "llvm/Support/YAMLParser.h" |
57 | | #include "llvm/TargetParser/ARMTargetParserCommon.h" |
58 | | #include "llvm/TargetParser/Host.h" |
59 | | #include "llvm/TargetParser/LoongArchTargetParser.h" |
60 | | #include "llvm/TargetParser/RISCVTargetParser.h" |
61 | | #include <cctype> |
62 | | |
63 | | using namespace clang::driver; |
64 | | using namespace clang::driver::tools; |
65 | | using namespace clang; |
66 | | using namespace llvm::opt; |
67 | | |
68 | 47.5k | static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { |
69 | 47.5k | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC, |
70 | 47.5k | options::OPT_fminimize_whitespace, |
71 | 47.5k | options::OPT_fno_minimize_whitespace)) { |
72 | 8 | if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P)4 && |
73 | 8 | !Args.hasArg(options::OPT__SLASH_EP)3 && !D.CCCIsCPP()3 ) { |
74 | 3 | D.Diag(clang::diag::err_drv_argument_only_allowed_with) |
75 | 3 | << A->getBaseArg().getAsString(Args) |
76 | 3 | << (D.IsCLMode() ? "/E, /P or /EP"1 : "-E"2 ); |
77 | 3 | } |
78 | 8 | } |
79 | 47.5k | } |
80 | | |
81 | 47.7k | static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { |
82 | | // In gcc, only ARM checks this, but it seems reasonable to check universally. |
83 | 47.7k | if (Args.hasArg(options::OPT_static)) |
84 | 108 | if (const Arg *A = |
85 | 108 | Args.getLastArg(options::OPT_dynamic, options::OPT_mdynamic_no_pic)) |
86 | 1 | D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) |
87 | 1 | << "-static"; |
88 | 47.7k | } |
89 | | |
90 | | // Add backslashes to escape spaces and other backslashes. |
91 | | // This is used for the space-separated argument list specified with |
92 | | // the -dwarf-debug-flags option. |
93 | | static void EscapeSpacesAndBackslashes(const char *Arg, |
94 | 364 | SmallVectorImpl<char> &Res) { |
95 | 9.58k | for (; *Arg; ++Arg9.21k ) { |
96 | 9.21k | switch (*Arg) { |
97 | 9.20k | default: |
98 | 9.20k | break; |
99 | 9.20k | case ' ': |
100 | 12 | case '\\': |
101 | 12 | Res.push_back('\\'); |
102 | 12 | break; |
103 | 9.21k | } |
104 | 9.21k | Res.push_back(*Arg); |
105 | 9.21k | } |
106 | 364 | } |
107 | | |
108 | | /// Apply \a Work on the current tool chain \a RegularToolChain and any other |
109 | | /// offloading tool chain that is associated with the current action \a JA. |
110 | | static void |
111 | | forAllAssociatedToolChains(Compilation &C, const JobAction &JA, |
112 | | const ToolChain &RegularToolChain, |
113 | 78.9k | llvm::function_ref<void(const ToolChain &)> Work) { |
114 | | // Apply Work on the current/regular tool chain. |
115 | 78.9k | Work(RegularToolChain); |
116 | | |
117 | | // Apply Work on all the offloading tool chains associated with the current |
118 | | // action. |
119 | 78.9k | if (JA.isHostOffloading(Action::OFK_Cuda)) |
120 | 136 | Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>()); |
121 | 78.7k | else if (JA.isDeviceOffloading(Action::OFK_Cuda)) |
122 | 142 | Work(*C.getSingleOffloadToolChain<Action::OFK_Host>()); |
123 | 78.6k | else if (JA.isHostOffloading(Action::OFK_HIP)) |
124 | 486 | Work(*C.getSingleOffloadToolChain<Action::OFK_HIP>()); |
125 | 78.1k | else if (JA.isDeviceOffloading(Action::OFK_HIP)) |
126 | 798 | Work(*C.getSingleOffloadToolChain<Action::OFK_Host>()); |
127 | | |
128 | 78.9k | if (JA.isHostOffloading(Action::OFK_OpenMP)) { |
129 | 8 | auto TCs = C.getOffloadToolChains<Action::OFK_OpenMP>(); |
130 | 16 | for (auto II = TCs.first, IE = TCs.second; II != IE; ++II8 ) |
131 | 8 | Work(*II->second); |
132 | 78.8k | } else if (JA.isDeviceOffloading(Action::OFK_OpenMP)) |
133 | 9 | Work(*C.getSingleOffloadToolChain<Action::OFK_Host>()); |
134 | | |
135 | | // |
136 | | // TODO: Add support for other offloading programming models here. |
137 | | // |
138 | 78.9k | } |
139 | | |
140 | | /// This is a helper function for validating the optional refinement step |
141 | | /// parameter in reciprocal argument strings. Return false if there is an error |
142 | | /// parsing the refinement step. Otherwise, return true and set the Position |
143 | | /// of the refinement step in the input string. |
144 | | static bool getRefinementStep(StringRef In, const Driver &D, |
145 | 42 | const Arg &A, size_t &Position) { |
146 | 42 | const char RefinementStepToken = ':'; |
147 | 42 | Position = In.find(RefinementStepToken); |
148 | 42 | if (Position != StringRef::npos) { |
149 | 15 | StringRef Option = A.getOption().getName(); |
150 | 15 | StringRef RefStep = In.substr(Position + 1); |
151 | | // Allow exactly one numeric character for the additional refinement |
152 | | // step parameter. This is reasonable for all currently-supported |
153 | | // operations and architectures because we would expect that a larger value |
154 | | // of refinement steps would cause the estimate "optimization" to |
155 | | // under-perform the native operation. Also, if the estimate does not |
156 | | // converge quickly, it probably will not ever converge, so further |
157 | | // refinement steps will not produce a better answer. |
158 | 15 | if (RefStep.size() != 1) { |
159 | 2 | D.Diag(diag::err_drv_invalid_value) << Option << RefStep; |
160 | 2 | return false; |
161 | 2 | } |
162 | 13 | char RefStepChar = RefStep[0]; |
163 | 13 | if (RefStepChar < '0' || RefStepChar > '9') { |
164 | 0 | D.Diag(diag::err_drv_invalid_value) << Option << RefStep; |
165 | 0 | return false; |
166 | 0 | } |
167 | 13 | } |
168 | 40 | return true; |
169 | 42 | } |
170 | | |
171 | | /// The -mrecip flag requires processing of many optional parameters. |
172 | | static void ParseMRecip(const Driver &D, const ArgList &Args, |
173 | 47.7k | ArgStringList &OutStrings) { |
174 | 47.7k | StringRef DisabledPrefixIn = "!"; |
175 | 47.7k | StringRef DisabledPrefixOut = "!"; |
176 | 47.7k | StringRef EnabledPrefixOut = ""; |
177 | 47.7k | StringRef Out = "-mrecip="; |
178 | | |
179 | 47.7k | Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ); |
180 | 47.7k | if (!A) |
181 | 47.7k | return; |
182 | | |
183 | 29 | unsigned NumOptions = A->getNumValues(); |
184 | 29 | if (NumOptions == 0) { |
185 | | // No option is the same as "all". |
186 | 1 | OutStrings.push_back(Args.MakeArgString(Out + "all")); |
187 | 1 | return; |
188 | 1 | } |
189 | | |
190 | | // Pass through "all", "none", or "default" with an optional refinement step. |
191 | 28 | if (NumOptions == 1) { |
192 | 14 | StringRef Val = A->getValue(0); |
193 | 14 | size_t RefStepLoc; |
194 | 14 | if (!getRefinementStep(Val, D, *A, RefStepLoc)) |
195 | 2 | return; |
196 | 12 | StringRef ValBase = Val.slice(0, RefStepLoc); |
197 | 12 | if (ValBase == "all" || ValBase == "none"10 || ValBase == "default"9 ) { |
198 | 4 | OutStrings.push_back(Args.MakeArgString(Out + Val)); |
199 | 4 | return; |
200 | 4 | } |
201 | 12 | } |
202 | | |
203 | | // Each reciprocal type may be enabled or disabled individually. |
204 | | // Check each input value for validity, concatenate them all back together, |
205 | | // and pass through. |
206 | | |
207 | 22 | llvm::StringMap<bool> OptionStrings; |
208 | 22 | OptionStrings.insert(std::make_pair("divd", false)); |
209 | 22 | OptionStrings.insert(std::make_pair("divf", false)); |
210 | 22 | OptionStrings.insert(std::make_pair("divh", false)); |
211 | 22 | OptionStrings.insert(std::make_pair("vec-divd", false)); |
212 | 22 | OptionStrings.insert(std::make_pair("vec-divf", false)); |
213 | 22 | OptionStrings.insert(std::make_pair("vec-divh", false)); |
214 | 22 | OptionStrings.insert(std::make_pair("sqrtd", false)); |
215 | 22 | OptionStrings.insert(std::make_pair("sqrtf", false)); |
216 | 22 | OptionStrings.insert(std::make_pair("sqrth", false)); |
217 | 22 | OptionStrings.insert(std::make_pair("vec-sqrtd", false)); |
218 | 22 | OptionStrings.insert(std::make_pair("vec-sqrtf", false)); |
219 | 22 | OptionStrings.insert(std::make_pair("vec-sqrth", false)); |
220 | | |
221 | 44 | for (unsigned i = 0; i != NumOptions; ++i22 ) { |
222 | 28 | StringRef Val = A->getValue(i); |
223 | | |
224 | 28 | bool IsDisabled = Val.startswith(DisabledPrefixIn); |
225 | | // Ignore the disablement token for string matching. |
226 | 28 | if (IsDisabled) |
227 | 3 | Val = Val.substr(1); |
228 | | |
229 | 28 | size_t RefStep; |
230 | 28 | if (!getRefinementStep(Val, D, *A, RefStep)) |
231 | 0 | return; |
232 | | |
233 | 28 | StringRef ValBase = Val.slice(0, RefStep); |
234 | 28 | llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase); |
235 | 28 | if (OptionIter == OptionStrings.end()) { |
236 | | // Try again specifying float suffix. |
237 | 8 | OptionIter = OptionStrings.find(ValBase.str() + 'f'); |
238 | 8 | if (OptionIter == OptionStrings.end()) { |
239 | | // The input name did not match any known option string. |
240 | 1 | D.Diag(diag::err_drv_unknown_argument) << Val; |
241 | 1 | return; |
242 | 1 | } |
243 | | // The option was specified without a half or float or double suffix. |
244 | | // Make sure that the double or half entry was not already specified. |
245 | | // The float entry will be checked below. |
246 | 7 | if (OptionStrings[ValBase.str() + 'd'] || |
247 | 7 | OptionStrings[ValBase.str() + 'h']) { |
248 | 1 | D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val; |
249 | 1 | return; |
250 | 1 | } |
251 | 7 | } |
252 | | |
253 | 26 | if (OptionIter->second == true) { |
254 | | // Duplicate option specified. |
255 | 4 | D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val; |
256 | 4 | return; |
257 | 4 | } |
258 | | |
259 | | // Mark the matched option as found. Do not allow duplicate specifiers. |
260 | 22 | OptionIter->second = true; |
261 | | |
262 | | // If the precision was not specified, also mark the double and half entry |
263 | | // as found. |
264 | 22 | if (ValBase.back() != 'f' && ValBase.back() != 'd'16 && ValBase.back() != 'h'10 ) { |
265 | 6 | OptionStrings[ValBase.str() + 'd'] = true; |
266 | 6 | OptionStrings[ValBase.str() + 'h'] = true; |
267 | 6 | } |
268 | | |
269 | | // Build the output string. |
270 | 22 | StringRef Prefix = IsDisabled ? DisabledPrefixOut3 : EnabledPrefixOut19 ; |
271 | 22 | Out = Args.MakeArgString(Out + Prefix + Val); |
272 | 22 | if (i != NumOptions - 1) |
273 | 12 | Out = Args.MakeArgString(Out + ","); |
274 | 22 | } |
275 | | |
276 | 16 | OutStrings.push_back(Args.MakeArgString(Out)); |
277 | 16 | } |
278 | | |
279 | | /// The -mprefer-vector-width option accepts either a positive integer |
280 | | /// or the string "none". |
281 | | static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args, |
282 | 47.7k | ArgStringList &CmdArgs) { |
283 | 47.7k | Arg *A = Args.getLastArg(options::OPT_mprefer_vector_width_EQ); |
284 | 47.7k | if (!A) |
285 | 47.7k | return; |
286 | | |
287 | 9 | StringRef Value = A->getValue(); |
288 | 9 | if (Value == "none") { |
289 | 1 | CmdArgs.push_back("-mprefer-vector-width=none"); |
290 | 8 | } else { |
291 | 8 | unsigned Width; |
292 | 8 | if (Value.getAsInteger(10, Width)) { |
293 | 3 | D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value; |
294 | 3 | return; |
295 | 3 | } |
296 | 5 | CmdArgs.push_back(Args.MakeArgString("-mprefer-vector-width=" + Value)); |
297 | 5 | } |
298 | 9 | } |
299 | | |
300 | | static bool |
301 | | shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, |
302 | 3.03k | const llvm::Triple &Triple) { |
303 | | // We use the zero-cost exception tables for Objective-C if the non-fragile |
304 | | // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and |
305 | | // later. |
306 | 3.03k | if (runtime.isNonFragile()) |
307 | 2.90k | return true; |
308 | | |
309 | 124 | if (!Triple.isMacOSX()) |
310 | 107 | return false; |
311 | | |
312 | 17 | return (!Triple.isMacOSXVersionLT(10, 5) && |
313 | 17 | (13 Triple.getArch() == llvm::Triple::x86_6413 || |
314 | 13 | Triple.getArch() == llvm::Triple::arm9 )); |
315 | 124 | } |
316 | | |
317 | | /// Adds exception related arguments to the driver command arguments. There's a |
318 | | /// main flag, -fexceptions and also language specific flags to enable/disable |
319 | | /// C++ and Objective-C exceptions. This makes it possible to for example |
320 | | /// disable C++ exceptions but enable Objective-C exceptions. |
321 | | static bool addExceptionArgs(const ArgList &Args, types::ID InputType, |
322 | | const ToolChain &TC, bool KernelOrKext, |
323 | | const ObjCRuntime &objcRuntime, |
324 | 47.0k | ArgStringList &CmdArgs) { |
325 | 47.0k | const llvm::Triple &Triple = TC.getTriple(); |
326 | | |
327 | 47.0k | if (KernelOrKext) { |
328 | | // -mkernel and -fapple-kext imply no exceptions, so claim exception related |
329 | | // arguments now to avoid warnings about unused arguments. |
330 | 30 | Args.ClaimAllArgs(options::OPT_fexceptions); |
331 | 30 | Args.ClaimAllArgs(options::OPT_fno_exceptions); |
332 | 30 | Args.ClaimAllArgs(options::OPT_fobjc_exceptions); |
333 | 30 | Args.ClaimAllArgs(options::OPT_fno_objc_exceptions); |
334 | 30 | Args.ClaimAllArgs(options::OPT_fcxx_exceptions); |
335 | 30 | Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions); |
336 | 30 | Args.ClaimAllArgs(options::OPT_fasync_exceptions); |
337 | 30 | Args.ClaimAllArgs(options::OPT_fno_async_exceptions); |
338 | 30 | return false; |
339 | 30 | } |
340 | | |
341 | | // See if the user explicitly enabled exceptions. |
342 | 47.0k | bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, |
343 | 47.0k | false); |
344 | | |
345 | 47.0k | bool EHa = Args.hasFlag(options::OPT_fasync_exceptions, |
346 | 47.0k | options::OPT_fno_async_exceptions, false); |
347 | 47.0k | if (EHa) { |
348 | 0 | CmdArgs.push_back("-fasync-exceptions"); |
349 | 0 | EH = true; |
350 | 0 | } |
351 | | |
352 | | // Obj-C exceptions are enabled by default, regardless of -fexceptions. This |
353 | | // is not necessarily sensible, but follows GCC. |
354 | 47.0k | if (types::isObjC(InputType) && |
355 | 47.0k | Args.hasFlag(options::OPT_fobjc_exceptions, |
356 | 3.03k | options::OPT_fno_objc_exceptions, true)) { |
357 | 3.03k | CmdArgs.push_back("-fobjc-exceptions"); |
358 | | |
359 | 3.03k | EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple); |
360 | 3.03k | } |
361 | | |
362 | 47.0k | if (types::isCXX(InputType)) { |
363 | | // Disable C++ EH by default on XCore and PS4/PS5. |
364 | 31.2k | bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore && |
365 | 31.2k | !Triple.isPS()31.2k && !Triple.isDriverKit()31.2k ; |
366 | 31.2k | Arg *ExceptionArg = Args.getLastArg( |
367 | 31.2k | options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions, |
368 | 31.2k | options::OPT_fexceptions, options::OPT_fno_exceptions); |
369 | 31.2k | if (ExceptionArg) |
370 | 13.7k | CXXExceptionsEnabled = |
371 | 13.7k | ExceptionArg->getOption().matches(options::OPT_fcxx_exceptions) || |
372 | 13.7k | ExceptionArg->getOption().matches(options::OPT_fexceptions)13.7k ; |
373 | | |
374 | 31.2k | if (CXXExceptionsEnabled) { |
375 | 31.1k | CmdArgs.push_back("-fcxx-exceptions"); |
376 | | |
377 | 31.1k | EH = true; |
378 | 31.1k | } |
379 | 31.2k | } |
380 | | |
381 | | // OPT_fignore_exceptions means exception could still be thrown, |
382 | | // but no clean up or catch would happen in current module. |
383 | | // So we do not set EH to false. |
384 | 47.0k | Args.AddLastArg(CmdArgs, options::OPT_fignore_exceptions); |
385 | | |
386 | 47.0k | if (EH) |
387 | 34.4k | CmdArgs.push_back("-fexceptions"); |
388 | 47.0k | return EH; |
389 | 47.0k | } |
390 | | |
391 | | static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC, |
392 | 47.7k | const JobAction &JA) { |
393 | 47.7k | bool Default = true; |
394 | 47.7k | if (TC.getTriple().isOSDarwin()) { |
395 | | // The native darwin assembler doesn't support the linker_option directives, |
396 | | // so we disable them if we think the .s file will be passed to it. |
397 | 17.7k | Default = TC.useIntegratedAs(); |
398 | 17.7k | } |
399 | | // The linker_option directives are intended for host compilation. |
400 | 47.7k | if (JA.isDeviceOffloading(Action::OFK_Cuda) || |
401 | 47.7k | JA.isDeviceOffloading(Action::OFK_HIP)47.6k ) |
402 | 510 | Default = false; |
403 | 47.7k | return Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink, |
404 | 47.7k | Default); |
405 | 47.7k | } |
406 | | |
407 | 47.7k | static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { |
408 | 47.7k | switch (Triple.getArch()){ |
409 | 45.8k | default: |
410 | 45.8k | return false; |
411 | 1.84k | case llvm::Triple::arm: |
412 | 1.90k | case llvm::Triple::thumb: |
413 | | // ARM Darwin targets require a frame pointer to be always present to aid |
414 | | // offline debugging via backtraces. |
415 | 1.90k | return Triple.isOSDarwin(); |
416 | 47.7k | } |
417 | 47.7k | } |
418 | | |
419 | | static bool useFramePointerForTargetByDefault(const ArgList &Args, |
420 | 47.5k | const llvm::Triple &Triple) { |
421 | 47.5k | if (Args.hasArg(options::OPT_pg) && !Args.hasArg(options::OPT_mfentry)49 ) |
422 | 45 | return true; |
423 | | |
424 | 47.5k | if (Triple.isAndroid()) { |
425 | 198 | switch (Triple.getArch()) { |
426 | 67 | case llvm::Triple::aarch64: |
427 | 152 | case llvm::Triple::arm: |
428 | 152 | case llvm::Triple::armeb: |
429 | 154 | case llvm::Triple::thumb: |
430 | 154 | case llvm::Triple::thumbeb: |
431 | 166 | case llvm::Triple::riscv64: |
432 | 166 | return true; |
433 | 32 | default: |
434 | 32 | break; |
435 | 198 | } |
436 | 198 | } |
437 | | |
438 | 47.3k | switch (Triple.getArch()) { |
439 | 14 | case llvm::Triple::xcore: |
440 | 111 | case llvm::Triple::wasm32: |
441 | 143 | case llvm::Triple::wasm64: |
442 | 192 | case llvm::Triple::msp430: |
443 | | // XCore never wants frame pointers, regardless of OS. |
444 | | // WebAssembly never wants frame pointers. |
445 | 192 | return false; |
446 | 231 | case llvm::Triple::ppc: |
447 | 239 | case llvm::Triple::ppcle: |
448 | 474 | case llvm::Triple::ppc64: |
449 | 591 | case llvm::Triple::ppc64le: |
450 | 983 | case llvm::Triple::riscv32: |
451 | 1.31k | case llvm::Triple::riscv64: |
452 | 1.44k | case llvm::Triple::sparc: |
453 | 1.45k | case llvm::Triple::sparcel: |
454 | 1.52k | case llvm::Triple::sparcv9: |
455 | 2.19k | case llvm::Triple::amdgcn: |
456 | 2.25k | case llvm::Triple::r600: |
457 | 2.28k | case llvm::Triple::csky: |
458 | 2.32k | case llvm::Triple::loongarch32: |
459 | 2.43k | case llvm::Triple::loongarch64: |
460 | 2.43k | return !areOptimizationsEnabled(Args); |
461 | 44.7k | default: |
462 | 44.7k | break; |
463 | 47.3k | } |
464 | | |
465 | 44.7k | if (Triple.isOSFuchsia() || Triple.isOSNetBSD()44.6k ) { |
466 | 187 | return !areOptimizationsEnabled(Args); |
467 | 187 | } |
468 | | |
469 | 44.5k | if (Triple.isOSLinux() || Triple.isOSHurd()40.4k ) { |
470 | 4.07k | switch (Triple.getArch()) { |
471 | | // Don't use a frame pointer on linux if optimizing for certain targets. |
472 | 450 | case llvm::Triple::arm: |
473 | 493 | case llvm::Triple::armeb: |
474 | 506 | case llvm::Triple::thumb: |
475 | 517 | case llvm::Triple::thumbeb: |
476 | 565 | case llvm::Triple::mips64: |
477 | 600 | case llvm::Triple::mips64el: |
478 | 768 | case llvm::Triple::mips: |
479 | 800 | case llvm::Triple::mipsel: |
480 | 844 | case llvm::Triple::systemz: |
481 | 1.24k | case llvm::Triple::x86: |
482 | 3.64k | case llvm::Triple::x86_64: |
483 | 3.64k | return !areOptimizationsEnabled(Args); |
484 | 433 | default: |
485 | 433 | return true; |
486 | 4.07k | } |
487 | 4.07k | } |
488 | | |
489 | 40.4k | if (Triple.isOSWindows()) { |
490 | 8.72k | switch (Triple.getArch()) { |
491 | 183 | case llvm::Triple::x86: |
492 | 183 | return !areOptimizationsEnabled(Args); |
493 | 8.44k | case llvm::Triple::x86_64: |
494 | 8.44k | return Triple.isOSBinFormatMachO(); |
495 | 58 | case llvm::Triple::arm: |
496 | 72 | case llvm::Triple::thumb: |
497 | | // Windows on ARM builds with FPO disabled to aid fast stack walking |
498 | 72 | return true; |
499 | 31 | default: |
500 | | // All other supported Windows ISAs use xdata unwind information, so frame |
501 | | // pointers are not generally useful. |
502 | 31 | return false; |
503 | 8.72k | } |
504 | 8.72k | } |
505 | | |
506 | 31.7k | return true; |
507 | 40.4k | } |
508 | | |
509 | | static CodeGenOptions::FramePointerKind |
510 | 47.7k | getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) { |
511 | | // We have 4 states: |
512 | | // |
513 | | // 00) leaf retained, non-leaf retained |
514 | | // 01) leaf retained, non-leaf omitted (this is invalid) |
515 | | // 10) leaf omitted, non-leaf retained |
516 | | // (what -momit-leaf-frame-pointer was designed for) |
517 | | // 11) leaf omitted, non-leaf omitted |
518 | | // |
519 | | // "omit" options taking precedence over "no-omit" options is the only way |
520 | | // to make 3 valid states representable |
521 | 47.7k | Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer, |
522 | 47.7k | options::OPT_fno_omit_frame_pointer); |
523 | 47.7k | bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer)55 ; |
524 | 47.7k | bool NoOmitFP = |
525 | 47.7k | A && A->getOption().matches(options::OPT_fno_omit_frame_pointer)55 ; |
526 | 47.7k | bool OmitLeafFP = |
527 | 47.7k | Args.hasFlag(options::OPT_momit_leaf_frame_pointer, |
528 | 47.7k | options::OPT_mno_omit_leaf_frame_pointer, |
529 | 47.7k | Triple.isAArch64() || Triple.isPS()45.9k || Triple.isVE()45.6k || |
530 | 47.7k | (45.6k Triple.isAndroid()45.6k && Triple.isRISCV64()131 )); |
531 | 47.7k | if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple)47.7k || |
532 | 47.7k | (47.6k !OmitFP47.6k && useFramePointerForTargetByDefault(Args, Triple)47.5k )) { |
533 | 38.8k | if (OmitLeafFP) |
534 | 2.05k | return CodeGenOptions::FramePointerKind::NonLeaf; |
535 | 36.7k | return CodeGenOptions::FramePointerKind::All; |
536 | 38.8k | } |
537 | 8.90k | return CodeGenOptions::FramePointerKind::None; |
538 | 47.7k | } |
539 | | |
540 | | /// Add a CC1 option to specify the debug compilation directory. |
541 | | static const char *addDebugCompDirArg(const ArgList &Args, |
542 | | ArgStringList &CmdArgs, |
543 | 48.2k | const llvm::vfs::FileSystem &VFS) { |
544 | 48.2k | if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, |
545 | 48.2k | options::OPT_fdebug_compilation_dir_EQ)) { |
546 | 18 | if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) |
547 | 3 | CmdArgs.push_back(Args.MakeArgString(Twine("-fdebug-compilation-dir=") + |
548 | 3 | A->getValue())); |
549 | 15 | else |
550 | 15 | A->render(Args, CmdArgs); |
551 | 48.2k | } else if (llvm::ErrorOr<std::string> CWD = |
552 | 48.2k | VFS.getCurrentWorkingDirectory()) { |
553 | 48.2k | CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD)); |
554 | 48.2k | } |
555 | 48.2k | StringRef Path(CmdArgs.back()); |
556 | 48.2k | return Path.substr(Path.find('=') + 1).data(); |
557 | 48.2k | } |
558 | | |
559 | | static void addDebugObjectName(const ArgList &Args, ArgStringList &CmdArgs, |
560 | | const char *DebugCompilationDir, |
561 | 102 | const char *OutputFileName) { |
562 | | // No need to generate a value for -object-file-name if it was provided. |
563 | 102 | for (auto *Arg : Args.filtered(options::OPT_Xclang)) |
564 | 4 | if (StringRef(Arg->getValue()).startswith("-object-file-name")) |
565 | 0 | return; |
566 | | |
567 | 102 | if (Args.hasArg(options::OPT_object_file_name_EQ)) |
568 | 0 | return; |
569 | | |
570 | 102 | SmallString<128> ObjFileNameForDebug(OutputFileName); |
571 | 102 | if (ObjFileNameForDebug != "-" && |
572 | 102 | !llvm::sys::path::is_absolute(ObjFileNameForDebug)77 && |
573 | 102 | (49 !DebugCompilationDir49 || |
574 | 49 | llvm::sys::path::is_absolute(DebugCompilationDir))) { |
575 | | // Make the path absolute in the debug infos like MSVC does. |
576 | 38 | llvm::sys::fs::make_absolute(ObjFileNameForDebug); |
577 | 38 | } |
578 | | // If the object file name is a relative path, then always use Windows |
579 | | // backslash style as -object-file-name is used for embedding object file path |
580 | | // in codeview and it can only be generated when targeting on Windows. |
581 | | // Otherwise, just use native absolute path. |
582 | 102 | llvm::sys::path::Style Style = |
583 | 102 | llvm::sys::path::is_absolute(ObjFileNameForDebug) |
584 | 102 | ? llvm::sys::path::Style::native66 |
585 | 102 | : llvm::sys::path::Style::windows_backslash36 ; |
586 | 102 | llvm::sys::path::remove_dots(ObjFileNameForDebug, /*remove_dot_dot=*/true, |
587 | 102 | Style); |
588 | 102 | CmdArgs.push_back( |
589 | 102 | Args.MakeArgString(Twine("-object-file-name=") + ObjFileNameForDebug)); |
590 | 102 | } |
591 | | |
592 | | /// Add a CC1 and CC1AS option to specify the debug file path prefix map. |
593 | | static void addDebugPrefixMapArg(const Driver &D, const ToolChain &TC, |
594 | 48.1k | const ArgList &Args, ArgStringList &CmdArgs) { |
595 | 48.1k | auto AddOneArg = [&](StringRef Map, StringRef Name) { |
596 | 31 | if (!Map.contains('=')) |
597 | 5 | D.Diag(diag::err_drv_invalid_argument_to_option) << Map << Name; |
598 | 26 | else |
599 | 26 | CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map)); |
600 | 31 | }; |
601 | | |
602 | 48.1k | for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ, |
603 | 48.1k | options::OPT_fdebug_prefix_map_EQ)) { |
604 | 25 | AddOneArg(A->getValue(), A->getOption().getName()); |
605 | 25 | A->claim(); |
606 | 25 | } |
607 | 48.1k | std::string GlobalRemapEntry = TC.GetGlobalDebugPathRemapping(); |
608 | 48.1k | if (GlobalRemapEntry.empty()) |
609 | 48.1k | return; |
610 | 7 | AddOneArg(GlobalRemapEntry, "environment"); |
611 | 7 | } |
612 | | |
613 | | /// Add a CC1 and CC1AS option to specify the macro file path prefix map. |
614 | | static void addMacroPrefixMapArg(const Driver &D, const ArgList &Args, |
615 | 47.5k | ArgStringList &CmdArgs) { |
616 | 47.5k | for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ, |
617 | 47.5k | options::OPT_fmacro_prefix_map_EQ)) { |
618 | 25 | StringRef Map = A->getValue(); |
619 | 25 | if (!Map.contains('=')) |
620 | 2 | D.Diag(diag::err_drv_invalid_argument_to_option) |
621 | 2 | << Map << A->getOption().getName(); |
622 | 23 | else |
623 | 23 | CmdArgs.push_back(Args.MakeArgString("-fmacro-prefix-map=" + Map)); |
624 | 25 | A->claim(); |
625 | 25 | } |
626 | 47.5k | } |
627 | | |
628 | | /// Add a CC1 and CC1AS option to specify the coverage file path prefix map. |
629 | | static void addCoveragePrefixMapArg(const Driver &D, const ArgList &Args, |
630 | 47.4k | ArgStringList &CmdArgs) { |
631 | 47.4k | for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ, |
632 | 47.4k | options::OPT_fcoverage_prefix_map_EQ)) { |
633 | 20 | StringRef Map = A->getValue(); |
634 | 20 | if (!Map.contains('=')) |
635 | 2 | D.Diag(diag::err_drv_invalid_argument_to_option) |
636 | 2 | << Map << A->getOption().getName(); |
637 | 18 | else |
638 | 18 | CmdArgs.push_back(Args.MakeArgString("-fcoverage-prefix-map=" + Map)); |
639 | 20 | A->claim(); |
640 | 20 | } |
641 | 47.4k | } |
642 | | |
643 | | /// Vectorize at all optimization levels greater than 1 except for -Oz. |
644 | | /// For -Oz the loop vectorizer is disabled, while the slp vectorizer is |
645 | | /// enabled. |
646 | 95.5k | static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) { |
647 | 95.5k | if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { |
648 | 6.80k | if (A->getOption().matches(options::OPT_O4) || |
649 | 6.80k | A->getOption().matches(options::OPT_Ofast)6.79k ) |
650 | 60 | return true; |
651 | | |
652 | 6.74k | if (A->getOption().matches(options::OPT_O0)) |
653 | 5.64k | return false; |
654 | | |
655 | 1.09k | assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag"); |
656 | | |
657 | | // Vectorize -Os. |
658 | 1.09k | StringRef S(A->getValue()); |
659 | 1.09k | if (S == "s") |
660 | 66 | return true; |
661 | | |
662 | | // Don't vectorize -Oz, unless it's the slp vectorizer. |
663 | 1.03k | if (S == "z") |
664 | 16 | return isSlpVec; |
665 | | |
666 | 1.01k | unsigned OptLevel = 0; |
667 | 1.01k | if (S.getAsInteger(10, OptLevel)) |
668 | 14 | return false; |
669 | | |
670 | 1.00k | return OptLevel > 1; |
671 | 1.01k | } |
672 | | |
673 | 88.7k | return false; |
674 | 95.5k | } |
675 | | |
676 | | /// Add -x lang to \p CmdArgs for \p Input. |
677 | | static void addDashXForInput(const ArgList &Args, const InputInfo &Input, |
678 | 47.7k | ArgStringList &CmdArgs) { |
679 | | // When using -verify-pch, we don't want to provide the type |
680 | | // 'precompiled-header' if it was inferred from the file extension |
681 | 47.7k | if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH2 ) |
682 | 1 | return; |
683 | | |
684 | 47.7k | CmdArgs.push_back("-x"); |
685 | 47.7k | if (Args.hasArg(options::OPT_rewrite_objc)) |
686 | 10 | CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX)); |
687 | 47.7k | else { |
688 | | // Map the driver type to the frontend type. This is mostly an identity |
689 | | // mapping, except that the distinction between module interface units |
690 | | // and other source files does not exist at the frontend layer. |
691 | 47.7k | const char *ClangType; |
692 | 47.7k | switch (Input.getType()) { |
693 | 32 | case types::TY_CXXModule: |
694 | 32 | ClangType = "c++"; |
695 | 32 | break; |
696 | 0 | case types::TY_PP_CXXModule: |
697 | 0 | ClangType = "c++-cpp-output"; |
698 | 0 | break; |
699 | 47.7k | default: |
700 | 47.7k | ClangType = types::getTypeName(Input.getType()); |
701 | 47.7k | break; |
702 | 47.7k | } |
703 | 47.7k | CmdArgs.push_back(ClangType); |
704 | 47.7k | } |
705 | 47.7k | } |
706 | | |
707 | | static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, |
708 | | const JobAction &JA, const InputInfo &Output, |
709 | | const ArgList &Args, SanitizerArgs &SanArgs, |
710 | 47.0k | ArgStringList &CmdArgs) { |
711 | 47.0k | const Driver &D = TC.getDriver(); |
712 | 47.0k | auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate, |
713 | 47.0k | options::OPT_fprofile_generate_EQ, |
714 | 47.0k | options::OPT_fno_profile_generate); |
715 | 47.0k | if (PGOGenerateArg && |
716 | 47.0k | PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)44 ) |
717 | 7 | PGOGenerateArg = nullptr; |
718 | | |
719 | 47.0k | auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args); |
720 | | |
721 | 47.0k | auto *ProfileGenerateArg = Args.getLastArg( |
722 | 47.0k | options::OPT_fprofile_instr_generate, |
723 | 47.0k | options::OPT_fprofile_instr_generate_EQ, |
724 | 47.0k | options::OPT_fno_profile_instr_generate); |
725 | 47.0k | if (ProfileGenerateArg && |
726 | 47.0k | ProfileGenerateArg->getOption().matches( |
727 | 63 | options::OPT_fno_profile_instr_generate)) |
728 | 7 | ProfileGenerateArg = nullptr; |
729 | | |
730 | 47.0k | if (PGOGenerateArg && ProfileGenerateArg37 ) |
731 | 2 | D.Diag(diag::err_drv_argument_not_allowed_with) |
732 | 2 | << PGOGenerateArg->getSpelling() << ProfileGenerateArg->getSpelling(); |
733 | | |
734 | 47.0k | auto *ProfileUseArg = getLastProfileUseArg(Args); |
735 | | |
736 | 47.0k | if (PGOGenerateArg && ProfileUseArg37 ) |
737 | 8 | D.Diag(diag::err_drv_argument_not_allowed_with) |
738 | 8 | << ProfileUseArg->getSpelling() << PGOGenerateArg->getSpelling(); |
739 | | |
740 | 47.0k | if (ProfileGenerateArg && ProfileUseArg56 ) |
741 | 12 | D.Diag(diag::err_drv_argument_not_allowed_with) |
742 | 12 | << ProfileGenerateArg->getSpelling() << ProfileUseArg->getSpelling(); |
743 | | |
744 | 47.0k | if (CSPGOGenerateArg && PGOGenerateArg7 ) { |
745 | 1 | D.Diag(diag::err_drv_argument_not_allowed_with) |
746 | 1 | << CSPGOGenerateArg->getSpelling() << PGOGenerateArg->getSpelling(); |
747 | 1 | PGOGenerateArg = nullptr; |
748 | 1 | } |
749 | | |
750 | 47.0k | if (TC.getTriple().isOSAIX()) { |
751 | 241 | if (Arg *ProfileSampleUseArg = getLastProfileSampleUseArg(Args)) |
752 | 1 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
753 | 1 | << ProfileSampleUseArg->getSpelling() << TC.getTriple().str(); |
754 | 241 | } |
755 | | |
756 | 47.0k | if (ProfileGenerateArg) { |
757 | 56 | if (ProfileGenerateArg->getOption().matches( |
758 | 56 | options::OPT_fprofile_instr_generate_EQ)) |
759 | 9 | CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-instrument-path=") + |
760 | 9 | ProfileGenerateArg->getValue())); |
761 | | // The default is to use Clang Instrumentation. |
762 | 56 | CmdArgs.push_back("-fprofile-instrument=clang"); |
763 | 56 | if (TC.getTriple().isWindowsMSVCEnvironment()) { |
764 | | // Add dependent lib for clang_rt.profile |
765 | 11 | CmdArgs.push_back(Args.MakeArgString( |
766 | 11 | "--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile"))); |
767 | 11 | } |
768 | 56 | } |
769 | | |
770 | 47.0k | Arg *PGOGenArg = nullptr; |
771 | 47.0k | if (PGOGenerateArg) { |
772 | 36 | assert(!CSPGOGenerateArg); |
773 | 36 | PGOGenArg = PGOGenerateArg; |
774 | 36 | CmdArgs.push_back("-fprofile-instrument=llvm"); |
775 | 36 | } |
776 | 47.0k | if (CSPGOGenerateArg) { |
777 | 7 | assert(!PGOGenerateArg); |
778 | 7 | PGOGenArg = CSPGOGenerateArg; |
779 | 7 | CmdArgs.push_back("-fprofile-instrument=csllvm"); |
780 | 7 | } |
781 | 47.0k | if (PGOGenArg) { |
782 | 43 | if (TC.getTriple().isWindowsMSVCEnvironment()) { |
783 | | // Add dependent lib for clang_rt.profile |
784 | 2 | CmdArgs.push_back(Args.MakeArgString( |
785 | 2 | "--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile"))); |
786 | 2 | } |
787 | 43 | if (PGOGenArg->getOption().matches( |
788 | 43 | PGOGenerateArg ? options::OPT_fprofile_generate_EQ36 |
789 | 43 | : options::OPT_fcs_profile_generate_EQ7 )) { |
790 | 9 | SmallString<128> Path(PGOGenArg->getValue()); |
791 | 9 | llvm::sys::path::append(Path, "default_%m.profraw"); |
792 | 9 | CmdArgs.push_back( |
793 | 9 | Args.MakeArgString(Twine("-fprofile-instrument-path=") + Path)); |
794 | 9 | } |
795 | 43 | } |
796 | | |
797 | 47.0k | if (ProfileUseArg) { |
798 | 50 | if (ProfileUseArg->getOption().matches(options::OPT_fprofile_instr_use_EQ)) |
799 | 11 | CmdArgs.push_back(Args.MakeArgString( |
800 | 11 | Twine("-fprofile-instrument-use-path=") + ProfileUseArg->getValue())); |
801 | 39 | else if ((ProfileUseArg->getOption().matches( |
802 | 39 | options::OPT_fprofile_use_EQ) || |
803 | 39 | ProfileUseArg->getOption().matches( |
804 | 39 | options::OPT_fprofile_instr_use))) { |
805 | 39 | SmallString<128> Path( |
806 | 39 | ProfileUseArg->getNumValues() == 0 ? ""16 : ProfileUseArg->getValue()23 ); |
807 | 39 | if (Path.empty() || llvm::sys::fs::is_directory(Path)23 ) |
808 | 21 | llvm::sys::path::append(Path, "default.profdata"); |
809 | 39 | CmdArgs.push_back( |
810 | 39 | Args.MakeArgString(Twine("-fprofile-instrument-use-path=") + Path)); |
811 | 39 | } |
812 | 50 | } |
813 | | |
814 | 47.0k | bool EmitCovNotes = Args.hasFlag(options::OPT_ftest_coverage, |
815 | 47.0k | options::OPT_fno_test_coverage, false) || |
816 | 47.0k | Args.hasArg(options::OPT_coverage)47.0k ; |
817 | 47.0k | bool EmitCovData = TC.needsGCovInstrumentation(Args); |
818 | | |
819 | 47.0k | if (Args.hasFlag(options::OPT_fcoverage_mapping, |
820 | 47.0k | options::OPT_fno_coverage_mapping, false)) { |
821 | 5 | if (!ProfileGenerateArg) |
822 | 1 | D.Diag(clang::diag::err_drv_argument_only_allowed_with) |
823 | 1 | << "-fcoverage-mapping" |
824 | 1 | << "-fprofile-instr-generate"; |
825 | | |
826 | 5 | CmdArgs.push_back("-fcoverage-mapping"); |
827 | 5 | } |
828 | | |
829 | 47.0k | if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, |
830 | 47.0k | options::OPT_fcoverage_compilation_dir_EQ)) { |
831 | 4 | if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) |
832 | 2 | CmdArgs.push_back(Args.MakeArgString( |
833 | 2 | Twine("-fcoverage-compilation-dir=") + A->getValue())); |
834 | 2 | else |
835 | 2 | A->render(Args, CmdArgs); |
836 | 47.0k | } else if (llvm::ErrorOr<std::string> CWD = |
837 | 47.0k | D.getVFS().getCurrentWorkingDirectory()) { |
838 | 47.0k | CmdArgs.push_back(Args.MakeArgString("-fcoverage-compilation-dir=" + *CWD)); |
839 | 47.0k | } |
840 | | |
841 | 47.0k | if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { |
842 | 5 | auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); |
843 | 5 | if (!Args.hasArg(options::OPT_coverage)) |
844 | 0 | D.Diag(clang::diag::err_drv_argument_only_allowed_with) |
845 | 0 | << "-fprofile-exclude-files=" |
846 | 0 | << "--coverage"; |
847 | | |
848 | 5 | StringRef v = Arg->getValue(); |
849 | 5 | CmdArgs.push_back( |
850 | 5 | Args.MakeArgString(Twine("-fprofile-exclude-files=" + v))); |
851 | 5 | } |
852 | | |
853 | 47.0k | if (Args.hasArg(options::OPT_fprofile_filter_files_EQ)) { |
854 | 4 | auto *Arg = Args.getLastArg(options::OPT_fprofile_filter_files_EQ); |
855 | 4 | if (!Args.hasArg(options::OPT_coverage)) |
856 | 0 | D.Diag(clang::diag::err_drv_argument_only_allowed_with) |
857 | 0 | << "-fprofile-filter-files=" |
858 | 0 | << "--coverage"; |
859 | | |
860 | 4 | StringRef v = Arg->getValue(); |
861 | 4 | CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v))); |
862 | 4 | } |
863 | | |
864 | 47.0k | if (const auto *A = Args.getLastArg(options::OPT_fprofile_update_EQ)) { |
865 | 9 | StringRef Val = A->getValue(); |
866 | 9 | if (Val == "atomic" || Val == "prefer-atomic"5 ) |
867 | 6 | CmdArgs.push_back("-fprofile-update=atomic"); |
868 | 3 | else if (Val != "single") |
869 | 1 | D.Diag(diag::err_drv_unsupported_option_argument) |
870 | 1 | << A->getSpelling() << Val; |
871 | 9 | } |
872 | | |
873 | 47.0k | int FunctionGroups = 1; |
874 | 47.0k | int SelectedFunctionGroup = 0; |
875 | 47.0k | if (const auto *A = Args.getLastArg(options::OPT_fprofile_function_groups)) { |
876 | 3 | StringRef Val = A->getValue(); |
877 | 3 | if (Val.getAsInteger(0, FunctionGroups) || FunctionGroups < 1) |
878 | 0 | D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val; |
879 | 3 | } |
880 | 47.0k | if (const auto *A = |
881 | 47.0k | Args.getLastArg(options::OPT_fprofile_selected_function_group)) { |
882 | 3 | StringRef Val = A->getValue(); |
883 | 3 | if (Val.getAsInteger(0, SelectedFunctionGroup) || |
884 | 3 | SelectedFunctionGroup < 0 || SelectedFunctionGroup >= FunctionGroups) |
885 | 0 | D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val; |
886 | 3 | } |
887 | 47.0k | if (FunctionGroups != 1) |
888 | 3 | CmdArgs.push_back(Args.MakeArgString("-fprofile-function-groups=" + |
889 | 3 | Twine(FunctionGroups))); |
890 | 47.0k | if (SelectedFunctionGroup != 0) |
891 | 2 | CmdArgs.push_back(Args.MakeArgString("-fprofile-selected-function-group=" + |
892 | 2 | Twine(SelectedFunctionGroup))); |
893 | | |
894 | | // Leave -fprofile-dir= an unused argument unless .gcda emission is |
895 | | // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider |
896 | | // the flag used. There is no -fno-profile-dir, so the user has no |
897 | | // targeted way to suppress the warning. |
898 | 47.0k | Arg *FProfileDir = nullptr; |
899 | 47.0k | if (Args.hasArg(options::OPT_fprofile_arcs) || |
900 | 47.0k | Args.hasArg(options::OPT_coverage)47.0k ) |
901 | 36 | FProfileDir = Args.getLastArg(options::OPT_fprofile_dir); |
902 | | |
903 | | // TODO: Don't claim -c/-S to warn about -fsyntax-only -c/-S, -E -c/-S, |
904 | | // like we warn about -fsyntax-only -E. |
905 | 47.0k | (void)(Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)39.6k ); |
906 | | |
907 | | // Put the .gcno and .gcda files (if needed) next to the primary output file, |
908 | | // or fall back to a file in the current directory for `clang -c --coverage |
909 | | // d/a.c` in the absence of -o. |
910 | 47.0k | if (EmitCovNotes || EmitCovData46.9k ) { |
911 | 39 | SmallString<128> CoverageFilename; |
912 | 39 | if (Arg *DumpDir = Args.getLastArgNoClaim(options::OPT_dumpdir)) { |
913 | | // Form ${dumpdir}${basename}.gcno. Note that dumpdir may not end with a |
914 | | // path separator. |
915 | 18 | CoverageFilename = DumpDir->getValue(); |
916 | 18 | CoverageFilename += llvm::sys::path::filename(Output.getBaseInput()); |
917 | 21 | } else if (Arg *FinalOutput = |
918 | 21 | C.getArgs().getLastArg(options::OPT__SLASH_Fo)) { |
919 | 1 | CoverageFilename = FinalOutput->getValue(); |
920 | 20 | } else if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) { |
921 | 11 | CoverageFilename = FinalOutput->getValue(); |
922 | 11 | } else { |
923 | 9 | CoverageFilename = llvm::sys::path::filename(Output.getBaseInput()); |
924 | 9 | } |
925 | 39 | if (llvm::sys::path::is_relative(CoverageFilename)) |
926 | 28 | (void)D.getVFS().makeAbsolute(CoverageFilename); |
927 | 39 | llvm::sys::path::replace_extension(CoverageFilename, "gcno"); |
928 | 39 | if (EmitCovNotes) { |
929 | 32 | CmdArgs.push_back( |
930 | 32 | Args.MakeArgString("-coverage-notes-file=" + CoverageFilename)); |
931 | 32 | } |
932 | | |
933 | 39 | if (EmitCovData) { |
934 | 33 | if (FProfileDir) { |
935 | 2 | SmallString<128> Gcno = std::move(CoverageFilename); |
936 | 2 | CoverageFilename = FProfileDir->getValue(); |
937 | 2 | llvm::sys::path::append(CoverageFilename, Gcno); |
938 | 2 | } |
939 | 33 | llvm::sys::path::replace_extension(CoverageFilename, "gcda"); |
940 | 33 | CmdArgs.push_back( |
941 | 33 | Args.MakeArgString("-coverage-data-file=" + CoverageFilename)); |
942 | 33 | } |
943 | 39 | } |
944 | 47.0k | } |
945 | | |
946 | | /// Check whether the given input tree contains any compilation actions. |
947 | 32.2k | static bool ContainsCompileAction(const Action *A) { |
948 | 32.2k | if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A)) |
949 | 11.1k | return true; |
950 | | |
951 | 21.0k | return llvm::any_of(A->inputs(), ContainsCompileAction); |
952 | 32.2k | } |
953 | | |
954 | | /// Check if -relax-all should be passed to the internal assembler. |
955 | | /// This is done by default when compiling non-assembler source with -O0. |
956 | 11.7k | static bool UseRelaxAll(Compilation &C, const ArgList &Args) { |
957 | 11.7k | bool RelaxDefault = true; |
958 | | |
959 | 11.7k | if (Arg *A = Args.getLastArg(options::OPT_O_Group)) |
960 | 2.95k | RelaxDefault = A->getOption().matches(options::OPT_O0); |
961 | | |
962 | 11.7k | if (RelaxDefault) { |
963 | 11.5k | RelaxDefault = false; |
964 | 11.5k | for (const auto &Act : C.getActions()) { |
965 | 11.5k | if (ContainsCompileAction(Act)) { |
966 | 11.1k | RelaxDefault = true; |
967 | 11.1k | break; |
968 | 11.1k | } |
969 | 11.5k | } |
970 | 11.5k | } |
971 | | |
972 | 11.7k | return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all, |
973 | 11.7k | RelaxDefault); |
974 | 11.7k | } |
975 | | |
976 | | static void |
977 | | RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs, |
978 | | llvm::codegenoptions::DebugInfoKind DebugInfoKind, |
979 | | unsigned DwarfVersion, |
980 | 48.2k | llvm::DebuggerKind DebuggerTuning) { |
981 | 48.2k | addDebugInfoKind(CmdArgs, DebugInfoKind); |
982 | 48.2k | if (DwarfVersion > 0) |
983 | 3.76k | CmdArgs.push_back( |
984 | 3.76k | Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion))); |
985 | 48.2k | switch (DebuggerTuning) { |
986 | 20.9k | case llvm::DebuggerKind::GDB: |
987 | 20.9k | CmdArgs.push_back("-debugger-tuning=gdb"); |
988 | 20.9k | break; |
989 | 17.7k | case llvm::DebuggerKind::LLDB: |
990 | 17.7k | CmdArgs.push_back("-debugger-tuning=lldb"); |
991 | 17.7k | break; |
992 | 286 | case llvm::DebuggerKind::SCE: |
993 | 286 | CmdArgs.push_back("-debugger-tuning=sce"); |
994 | 286 | break; |
995 | 5 | case llvm::DebuggerKind::DBX: |
996 | 5 | CmdArgs.push_back("-debugger-tuning=dbx"); |
997 | 5 | break; |
998 | 9.30k | default: |
999 | 9.30k | break; |
1000 | 48.2k | } |
1001 | 48.2k | } |
1002 | | |
1003 | | static bool checkDebugInfoOption(const Arg *A, const ArgList &Args, |
1004 | 6.51k | const Driver &D, const ToolChain &TC) { |
1005 | 6.51k | assert(A && "Expected non-nullptr argument."); |
1006 | 6.51k | if (TC.supportsDebugInfoOption(A)) |
1007 | 6.51k | return true; |
1008 | 0 | D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target) |
1009 | 0 | << A->getAsString(Args) << TC.getTripleString(); |
1010 | 0 | return false; |
1011 | 6.51k | } |
1012 | | |
1013 | | static void RenderDebugInfoCompressionArgs(const ArgList &Args, |
1014 | | ArgStringList &CmdArgs, |
1015 | | const Driver &D, |
1016 | 48.2k | const ToolChain &TC) { |
1017 | 48.2k | const Arg *A = Args.getLastArg(options::OPT_gz_EQ); |
1018 | 48.2k | if (!A) |
1019 | 48.2k | return; |
1020 | 29 | if (checkDebugInfoOption(A, Args, D, TC)) { |
1021 | 26 | StringRef Value = A->getValue(); |
1022 | 26 | if (Value == "none") { |
1023 | 7 | CmdArgs.push_back("--compress-debug-sections=none"); |
1024 | 19 | } else if (Value == "zlib") { |
1025 | 14 | if (llvm::compression::zlib::isAvailable()) { |
1026 | 14 | CmdArgs.push_back( |
1027 | 14 | Args.MakeArgString("--compress-debug-sections=" + Twine(Value))); |
1028 | 14 | } else { |
1029 | 0 | D.Diag(diag::warn_debug_compression_unavailable) << "zlib"; |
1030 | 0 | } |
1031 | 14 | } else if (5 Value == "zstd"5 ) { |
1032 | 2 | if (llvm::compression::zstd::isAvailable()) { |
1033 | 0 | CmdArgs.push_back( |
1034 | 0 | Args.MakeArgString("--compress-debug-sections=" + Twine(Value))); |
1035 | 2 | } else { |
1036 | 2 | D.Diag(diag::warn_debug_compression_unavailable) << "zstd"; |
1037 | 2 | } |
1038 | 3 | } else { |
1039 | 3 | D.Diag(diag::err_drv_unsupported_option_argument) |
1040 | 3 | << A->getSpelling() << Value; |
1041 | 3 | } |
1042 | 26 | } |
1043 | 29 | } |
1044 | | |
1045 | | static void handleAMDGPUCodeObjectVersionOptions(const Driver &D, |
1046 | | const ArgList &Args, |
1047 | | ArgStringList &CmdArgs, |
1048 | 755 | bool IsCC1As = false) { |
1049 | | // If no version was requested by the user, use the default value from the |
1050 | | // back end. This is consistent with the value returned from |
1051 | | // getAMDGPUCodeObjectVersion. This lets clang emit IR for amdgpu without |
1052 | | // requiring the corresponding llvm to have the AMDGPU target enabled, |
1053 | | // provided the user (e.g. front end tests) can use the default. |
1054 | 755 | if (haveAMDGPUCodeObjectVersionArgument(D, Args)) { |
1055 | 19 | unsigned CodeObjVer = getAMDGPUCodeObjectVersion(D, Args); |
1056 | 19 | CmdArgs.insert(CmdArgs.begin() + 1, |
1057 | 19 | Args.MakeArgString(Twine("--amdhsa-code-object-version=") + |
1058 | 19 | Twine(CodeObjVer))); |
1059 | 19 | CmdArgs.insert(CmdArgs.begin() + 1, "-mllvm"); |
1060 | | // -cc1as does not accept -mcode-object-version option. |
1061 | 19 | if (!IsCC1As) |
1062 | 17 | CmdArgs.insert(CmdArgs.begin() + 1, |
1063 | 17 | Args.MakeArgString(Twine("-mcode-object-version=") + |
1064 | 17 | Twine(CodeObjVer))); |
1065 | 19 | } |
1066 | 755 | } |
1067 | | |
1068 | | void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, |
1069 | | const Driver &D, const ArgList &Args, |
1070 | | ArgStringList &CmdArgs, |
1071 | | const InputInfo &Output, |
1072 | 47.5k | const InputInfoList &Inputs) const { |
1073 | 47.5k | const bool IsIAMCU = getToolChain().getTriple().isOSIAMCU(); |
1074 | | |
1075 | 47.5k | CheckPreprocessingOptions(D, Args); |
1076 | | |
1077 | 47.5k | Args.AddLastArg(CmdArgs, options::OPT_C); |
1078 | 47.5k | Args.AddLastArg(CmdArgs, options::OPT_CC); |
1079 | | |
1080 | | // Handle dependency file generation. |
1081 | 47.5k | Arg *ArgM = Args.getLastArg(options::OPT_MM); |
1082 | 47.5k | if (!ArgM) |
1083 | 47.4k | ArgM = Args.getLastArg(options::OPT_M); |
1084 | 47.5k | Arg *ArgMD = Args.getLastArg(options::OPT_MMD); |
1085 | 47.5k | if (!ArgMD) |
1086 | 47.4k | ArgMD = Args.getLastArg(options::OPT_MD); |
1087 | | |
1088 | | // -M and -MM imply -w. |
1089 | 47.5k | if (ArgM) |
1090 | 15 | CmdArgs.push_back("-w"); |
1091 | 47.4k | else |
1092 | 47.4k | ArgM = ArgMD; |
1093 | | |
1094 | 47.5k | if (ArgM) { |
1095 | | // Determine the output location. |
1096 | 2.83k | const char *DepFile; |
1097 | 2.83k | if (Arg *MF = Args.getLastArg(options::OPT_MF)) { |
1098 | 2.81k | DepFile = MF->getValue(); |
1099 | 2.81k | C.addFailureResultFile(DepFile, &JA); |
1100 | 2.81k | } else if (21 Output.getType() == types::TY_Dependencies21 ) { |
1101 | 12 | DepFile = Output.getFilename(); |
1102 | 12 | } else if (9 !ArgMD9 ) { |
1103 | 0 | DepFile = "-"; |
1104 | 9 | } else { |
1105 | 9 | DepFile = getDependencyFileName(Args, Inputs); |
1106 | 9 | C.addFailureResultFile(DepFile, &JA); |
1107 | 9 | } |
1108 | 2.83k | CmdArgs.push_back("-dependency-file"); |
1109 | 2.83k | CmdArgs.push_back(DepFile); |
1110 | | |
1111 | 2.83k | bool HasTarget = false; |
1112 | 2.83k | for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) { |
1113 | 2.77k | HasTarget = true; |
1114 | 2.77k | A->claim(); |
1115 | 2.77k | if (A->getOption().matches(options::OPT_MT)) { |
1116 | 2.77k | A->render(Args, CmdArgs); |
1117 | 2.77k | } else { |
1118 | 5 | CmdArgs.push_back("-MT"); |
1119 | 5 | SmallString<128> Quoted; |
1120 | 5 | quoteMakeTarget(A->getValue(), Quoted); |
1121 | 5 | CmdArgs.push_back(Args.MakeArgString(Quoted)); |
1122 | 5 | } |
1123 | 2.77k | } |
1124 | | |
1125 | | // Add a default target if one wasn't specified. |
1126 | 2.83k | if (!HasTarget) { |
1127 | 67 | const char *DepTarget; |
1128 | | |
1129 | | // If user provided -o, that is the dependency target, except |
1130 | | // when we are only generating a dependency file. |
1131 | 67 | Arg *OutputOpt = Args.getLastArg(options::OPT_o); |
1132 | 67 | if (OutputOpt && Output.getType() != types::TY_Dependencies8 ) { |
1133 | 6 | DepTarget = OutputOpt->getValue(); |
1134 | 61 | } else { |
1135 | | // Otherwise derive from the base input. |
1136 | | // |
1137 | | // FIXME: This should use the computed output file location. |
1138 | 61 | SmallString<128> P(Inputs[0].getBaseInput()); |
1139 | 61 | llvm::sys::path::replace_extension(P, "o"); |
1140 | 61 | DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); |
1141 | 61 | } |
1142 | | |
1143 | 67 | CmdArgs.push_back("-MT"); |
1144 | 67 | SmallString<128> Quoted; |
1145 | 67 | quoteMakeTarget(DepTarget, Quoted); |
1146 | 67 | CmdArgs.push_back(Args.MakeArgString(Quoted)); |
1147 | 67 | } |
1148 | | |
1149 | 2.83k | if (ArgM->getOption().matches(options::OPT_M) || |
1150 | 2.83k | ArgM->getOption().matches(options::OPT_MD)2.82k ) |
1151 | 2.82k | CmdArgs.push_back("-sys-header-deps"); |
1152 | 2.83k | if (Args.hasFlag(options::OPT_canonical_prefixes, |
1153 | 2.83k | options::OPT_no_canonical_prefixes, true)) |
1154 | 2.83k | CmdArgs.push_back("-canonical-system-headers"); |
1155 | 2.83k | if ((isa<PrecompileJobAction>(JA) && |
1156 | 2.83k | !Args.hasArg(options::OPT_fno_module_file_deps)10 ) || |
1157 | 2.83k | Args.hasArg(options::OPT_fmodule_file_deps)2.83k ) |
1158 | 10 | CmdArgs.push_back("-module-file-deps"); |
1159 | 2.83k | } |
1160 | | |
1161 | 47.5k | if (Args.hasArg(options::OPT_MG)) { |
1162 | 4 | if (!ArgM || ArgM->getOption().matches(options::OPT_MD) || |
1163 | 4 | ArgM->getOption().matches(options::OPT_MMD)) |
1164 | 0 | D.Diag(diag::err_drv_mg_requires_m_or_mm); |
1165 | 4 | CmdArgs.push_back("-MG"); |
1166 | 4 | } |
1167 | | |
1168 | 47.5k | Args.AddLastArg(CmdArgs, options::OPT_MP); |
1169 | 47.5k | Args.AddLastArg(CmdArgs, options::OPT_MV); |
1170 | | |
1171 | | // Add offload include arguments specific for CUDA/HIP. This must happen |
1172 | | // before we -I or -include anything else, because we must pick up the |
1173 | | // CUDA/HIP headers from the particular CUDA/ROCm installation, rather than |
1174 | | // from e.g. /usr/local/include. |
1175 | 47.5k | if (JA.isOffloading(Action::OFK_Cuda)) |
1176 | 139 | getToolChain().AddCudaIncludeArgs(Args, CmdArgs); |
1177 | 47.5k | if (JA.isOffloading(Action::OFK_HIP)) |
1178 | 642 | getToolChain().AddHIPIncludeArgs(Args, CmdArgs); |
1179 | | |
1180 | | // If we are compiling for a GPU target we want to override the system headers |
1181 | | // with ones created by the 'libc' project if present. |
1182 | 47.5k | if (!Args.hasArg(options::OPT_nostdinc) && |
1183 | 47.5k | !Args.hasArg(options::OPT_nogpuinc)47.4k && |
1184 | 47.5k | !Args.hasArg(options::OPT_nobuiltininc)46.8k ) { |
1185 | | // Without an offloading language we will include these headers directly. |
1186 | | // Offloading languages will instead only use the declarations stored in |
1187 | | // the resource directory at clang/lib/Headers/llvm_libc_wrappers. |
1188 | 46.8k | if ((getToolChain().getTriple().isNVPTX() || |
1189 | 46.8k | getToolChain().getTriple().isAMDGCN()46.7k ) && |
1190 | 46.8k | C.getActiveOffloadKinds() == Action::OFK_None347 ) { |
1191 | 229 | SmallString<128> P(llvm::sys::path::parent_path(D.InstalledDir)); |
1192 | 229 | llvm::sys::path::append(P, "include"); |
1193 | 229 | llvm::sys::path::append(P, "gpu-none-llvm"); |
1194 | 229 | CmdArgs.push_back("-c-isystem"); |
1195 | 229 | CmdArgs.push_back(Args.MakeArgString(P)); |
1196 | 46.5k | } else if (C.getActiveOffloadKinds() == Action::OFK_OpenMP) { |
1197 | | // TODO: CUDA / HIP include their own headers for some common functions |
1198 | | // implemented here. We'll need to clean those up so they do not conflict. |
1199 | 17 | SmallString<128> P(D.ResourceDir); |
1200 | 17 | llvm::sys::path::append(P, "include"); |
1201 | 17 | llvm::sys::path::append(P, "llvm_libc_wrappers"); |
1202 | 17 | CmdArgs.push_back("-internal-isystem"); |
1203 | 17 | CmdArgs.push_back(Args.MakeArgString(P)); |
1204 | 17 | } |
1205 | 46.8k | } |
1206 | | |
1207 | | // If we are offloading to a target via OpenMP we need to include the |
1208 | | // openmp_wrappers folder which contains alternative system headers. |
1209 | 47.5k | if (JA.isDeviceOffloading(Action::OFK_OpenMP) && |
1210 | 47.5k | !Args.hasArg(options::OPT_nostdinc)9 && |
1211 | 47.5k | !Args.hasArg(options::OPT_nogpuinc)9 && |
1212 | 47.5k | (9 getToolChain().getTriple().isNVPTX()9 || |
1213 | 9 | getToolChain().getTriple().isAMDGCN())) { |
1214 | 9 | if (!Args.hasArg(options::OPT_nobuiltininc)) { |
1215 | | // Add openmp_wrappers/* to our system include path. This lets us wrap |
1216 | | // standard library headers. |
1217 | 9 | SmallString<128> P(D.ResourceDir); |
1218 | 9 | llvm::sys::path::append(P, "include"); |
1219 | 9 | llvm::sys::path::append(P, "openmp_wrappers"); |
1220 | 9 | CmdArgs.push_back("-internal-isystem"); |
1221 | 9 | CmdArgs.push_back(Args.MakeArgString(P)); |
1222 | 9 | } |
1223 | | |
1224 | 9 | CmdArgs.push_back("-include"); |
1225 | 9 | CmdArgs.push_back("__clang_openmp_device_functions.h"); |
1226 | 9 | } |
1227 | | |
1228 | | // Add -i* options, and automatically translate to |
1229 | | // -include-pch/-include-pth for transparent PCH support. It's |
1230 | | // wonky, but we include looking for .gch so we can support seamless |
1231 | | // replacement into a build system already set up to be generating |
1232 | | // .gch files. |
1233 | | |
1234 | 47.5k | if (getToolChain().getDriver().IsCLMode()) { |
1235 | 716 | const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc); |
1236 | 716 | const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu); |
1237 | 716 | if (YcArg && JA.getKind() >= Action::PrecompileJobClass36 && |
1238 | 716 | JA.getKind() <= Action::AssembleJobClass36 ) { |
1239 | 36 | CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj")); |
1240 | | // -fpch-instantiate-templates is the default when creating |
1241 | | // precomp using /Yc |
1242 | 36 | if (Args.hasFlag(options::OPT_fpch_instantiate_templates, |
1243 | 36 | options::OPT_fno_pch_instantiate_templates, true)) |
1244 | 34 | CmdArgs.push_back(Args.MakeArgString("-fpch-instantiate-templates")); |
1245 | 36 | } |
1246 | 716 | if (YcArg || YuArg680 ) { |
1247 | 49 | StringRef ThroughHeader = YcArg ? YcArg->getValue()36 : YuArg->getValue()13 ; |
1248 | 49 | if (!isa<PrecompileJobAction>(JA)) { |
1249 | 31 | CmdArgs.push_back("-include-pch"); |
1250 | 31 | CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath( |
1251 | 31 | C, !ThroughHeader.empty() |
1252 | 31 | ? ThroughHeader26 |
1253 | 31 | : llvm::sys::path::filename(Inputs[0].getBaseInput())5 ))); |
1254 | 31 | } |
1255 | | |
1256 | 49 | if (ThroughHeader.empty()) { |
1257 | 9 | CmdArgs.push_back(Args.MakeArgString( |
1258 | 9 | Twine("-pch-through-hdrstop-") + (YcArg ? "create"8 : "use"1 ))); |
1259 | 40 | } else { |
1260 | 40 | CmdArgs.push_back( |
1261 | 40 | Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader)); |
1262 | 40 | } |
1263 | 49 | } |
1264 | 716 | } |
1265 | | |
1266 | 47.5k | bool RenderedImplicitInclude = false; |
1267 | 47.5k | for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) { |
1268 | 11.0k | if (A->getOption().matches(options::OPT_include) && |
1269 | 11.0k | D.getProbePrecompiled()2.91k ) { |
1270 | | // Handling of gcc-style gch precompiled headers. |
1271 | 2.90k | bool IsFirstImplicitInclude = !RenderedImplicitInclude; |
1272 | 2.90k | RenderedImplicitInclude = true; |
1273 | | |
1274 | 2.90k | bool FoundPCH = false; |
1275 | 2.90k | SmallString<128> P(A->getValue()); |
1276 | | // We want the files to have a name like foo.h.pch. Add a dummy extension |
1277 | | // so that replace_extension does the right thing. |
1278 | 2.90k | P += ".dummy"; |
1279 | 2.90k | llvm::sys::path::replace_extension(P, "pch"); |
1280 | 2.90k | if (D.getVFS().exists(P)) |
1281 | 71 | FoundPCH = true; |
1282 | | |
1283 | 2.90k | if (!FoundPCH) { |
1284 | 2.83k | llvm::sys::path::replace_extension(P, "gch"); |
1285 | 2.83k | if (D.getVFS().exists(P)) { |
1286 | 17 | FoundPCH = true; |
1287 | 17 | } |
1288 | 2.83k | } |
1289 | | |
1290 | 2.90k | if (FoundPCH) { |
1291 | 88 | if (IsFirstImplicitInclude) { |
1292 | 88 | A->claim(); |
1293 | 88 | CmdArgs.push_back("-include-pch"); |
1294 | 88 | CmdArgs.push_back(Args.MakeArgString(P)); |
1295 | 88 | continue; |
1296 | 88 | } else { |
1297 | | // Ignore the PCH if not first on command line and emit warning. |
1298 | 0 | D.Diag(diag::warn_drv_pch_not_first_include) << P |
1299 | 0 | << A->getAsString(Args); |
1300 | 0 | } |
1301 | 88 | } |
1302 | 8.14k | } else if (A->getOption().matches(options::OPT_isystem_after)) { |
1303 | | // Handling of paths which must come late. These entries are handled by |
1304 | | // the toolchain itself after the resource dir is inserted in the right |
1305 | | // search order. |
1306 | | // Do not claim the argument so that the use of the argument does not |
1307 | | // silently go unnoticed on toolchains which do not honour the option. |
1308 | 4 | continue; |
1309 | 8.13k | } else if (A->getOption().matches(options::OPT_stdlibxx_isystem)) { |
1310 | | // Translated to -internal-isystem by the driver, no need to pass to cc1. |
1311 | 18 | continue; |
1312 | 8.12k | } else if (A->getOption().matches(options::OPT_ibuiltininc)) { |
1313 | | // This is used only by the driver. No need to pass to cc1. |
1314 | 6 | continue; |
1315 | 6 | } |
1316 | | |
1317 | | // Not translated, render as usual. |
1318 | 10.9k | A->claim(); |
1319 | 10.9k | A->render(Args, CmdArgs); |
1320 | 10.9k | } |
1321 | | |
1322 | 47.5k | Args.AddAllArgs(CmdArgs, |
1323 | 47.5k | {options::OPT_D, options::OPT_U, options::OPT_I_Group, |
1324 | 47.5k | options::OPT_F, options::OPT_index_header_map}); |
1325 | | |
1326 | | // Add -Wp, and -Xpreprocessor if using the preprocessor. |
1327 | | |
1328 | | // FIXME: There is a very unfortunate problem here, some troubled |
1329 | | // souls abuse -Wp, to pass preprocessor options in gcc syntax. To |
1330 | | // really support that we would have to parse and then translate |
1331 | | // those options. :( |
1332 | 47.5k | Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA, |
1333 | 47.5k | options::OPT_Xpreprocessor); |
1334 | | |
1335 | | // -I- is a deprecated GCC feature, reject it. |
1336 | 47.5k | if (Arg *A = Args.getLastArg(options::OPT_I_)) |
1337 | 0 | D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args); |
1338 | | |
1339 | | // If we have a --sysroot, and don't have an explicit -isysroot flag, add an |
1340 | | // -isysroot to the CC1 invocation. |
1341 | 47.5k | StringRef sysroot = C.getSysRoot(); |
1342 | 47.5k | if (sysroot != "") { |
1343 | 941 | if (!Args.hasArg(options::OPT_isysroot)) { |
1344 | 935 | CmdArgs.push_back("-isysroot"); |
1345 | 935 | CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); |
1346 | 935 | } |
1347 | 941 | } |
1348 | | |
1349 | | // Parse additional include paths from environment variables. |
1350 | | // FIXME: We should probably sink the logic for handling these from the |
1351 | | // frontend into the driver. It will allow deleting 4 otherwise unused flags. |
1352 | | // CPATH - included following the user specified includes (but prior to |
1353 | | // builtin and standard includes). |
1354 | 47.5k | addDirectoryList(Args, CmdArgs, "-I", "CPATH"); |
1355 | | // C_INCLUDE_PATH - system includes enabled when compiling C. |
1356 | 47.5k | addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH"); |
1357 | | // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++. |
1358 | 47.5k | addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH"); |
1359 | | // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC. |
1360 | 47.5k | addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH"); |
1361 | | // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++. |
1362 | 47.5k | addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH"); |
1363 | | |
1364 | | // While adding the include arguments, we also attempt to retrieve the |
1365 | | // arguments of related offloading toolchains or arguments that are specific |
1366 | | // of an offloading programming model. |
1367 | | |
1368 | | // Add C++ include arguments, if needed. |
1369 | 47.5k | if (types::isCXX(Inputs[0].getType())) { |
1370 | 31.4k | bool HasStdlibxxIsystem = Args.hasArg(options::OPT_stdlibxx_isystem); |
1371 | 31.4k | forAllAssociatedToolChains( |
1372 | 31.4k | C, JA, getToolChain(), |
1373 | 32.1k | [&Args, &CmdArgs, HasStdlibxxIsystem](const ToolChain &TC) { |
1374 | 32.1k | HasStdlibxxIsystem ? TC.AddClangCXXStdlibIsystemArgs(Args, CmdArgs)10 |
1375 | 32.1k | : TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs)32.1k ; |
1376 | 32.1k | }); |
1377 | 31.4k | } |
1378 | | |
1379 | | // Add system include arguments for all targets but IAMCU. |
1380 | 47.5k | if (!IsIAMCU) |
1381 | 47.4k | forAllAssociatedToolChains(C, JA, getToolChain(), |
1382 | 48.2k | [&Args, &CmdArgs](const ToolChain &TC) { |
1383 | 48.2k | TC.AddClangSystemIncludeArgs(Args, CmdArgs); |
1384 | 48.2k | }); |
1385 | 10 | else { |
1386 | | // For IAMCU add special include arguments. |
1387 | 10 | getToolChain().AddIAMCUIncludeArgs(Args, CmdArgs); |
1388 | 10 | } |
1389 | | |
1390 | 47.5k | addMacroPrefixMapArg(D, Args, CmdArgs); |
1391 | 47.5k | addCoveragePrefixMapArg(D, Args, CmdArgs); |
1392 | | |
1393 | 47.5k | Args.AddLastArg(CmdArgs, options::OPT_ffile_reproducible, |
1394 | 47.5k | options::OPT_fno_file_reproducible); |
1395 | | |
1396 | 47.5k | if (const char *Epoch = std::getenv("SOURCE_DATE_EPOCH")) { |
1397 | 1 | CmdArgs.push_back("-source-date-epoch"); |
1398 | 1 | CmdArgs.push_back(Args.MakeArgString(Epoch)); |
1399 | 1 | } |
1400 | 47.5k | } |
1401 | | |
1402 | | // FIXME: Move to target hook. |
1403 | 47.7k | static bool isSignedCharDefault(const llvm::Triple &Triple) { |
1404 | 47.7k | switch (Triple.getArch()) { |
1405 | 42.2k | default: |
1406 | 42.2k | return true; |
1407 | | |
1408 | 1.55k | case llvm::Triple::aarch64: |
1409 | 1.55k | case llvm::Triple::aarch64_32: |
1410 | 1.78k | case llvm::Triple::aarch64_be: |
1411 | 3.63k | case llvm::Triple::arm: |
1412 | 3.79k | case llvm::Triple::armeb: |
1413 | 3.86k | case llvm::Triple::thumb: |
1414 | 3.87k | case llvm::Triple::thumbeb: |
1415 | 3.87k | if (Triple.isOSDarwin() || Triple.isOSWindows()3.57k ) |
1416 | 420 | return true; |
1417 | 3.45k | return false; |
1418 | | |
1419 | 234 | case llvm::Triple::ppc: |
1420 | 472 | case llvm::Triple::ppc64: |
1421 | 472 | if (Triple.isOSDarwin()) |
1422 | 0 | return true; |
1423 | 472 | return false; |
1424 | | |
1425 | 137 | case llvm::Triple::hexagon: |
1426 | 145 | case llvm::Triple::ppcle: |
1427 | 262 | case llvm::Triple::ppc64le: |
1428 | 654 | case llvm::Triple::riscv32: |
1429 | 997 | case llvm::Triple::riscv64: |
1430 | 1.09k | case llvm::Triple::systemz: |
1431 | 1.10k | case llvm::Triple::xcore: |
1432 | 1.10k | return false; |
1433 | 47.7k | } |
1434 | 47.7k | } |
1435 | | |
1436 | | static bool hasMultipleInvocations(const llvm::Triple &Triple, |
1437 | 38 | const ArgList &Args) { |
1438 | | // Supported only on Darwin where we invoke the compiler multiple times |
1439 | | // followed by an invocation to lipo. |
1440 | 38 | if (!Triple.isOSDarwin()) |
1441 | 7 | return false; |
1442 | | // If more than one "-arch <arch>" is specified, we're targeting multiple |
1443 | | // architectures resulting in a fat binary. |
1444 | 31 | return Args.getAllArgValues(options::OPT_arch).size() > 1; |
1445 | 38 | } |
1446 | | |
1447 | | static bool checkRemarksOptions(const Driver &D, const ArgList &Args, |
1448 | 38 | const llvm::Triple &Triple) { |
1449 | | // When enabling remarks, we need to error if: |
1450 | | // * The remark file is specified but we're targeting multiple architectures, |
1451 | | // which means more than one remark file is being generated. |
1452 | 38 | bool hasMultipleInvocations = ::hasMultipleInvocations(Triple, Args); |
1453 | 38 | bool hasExplicitOutputFile = |
1454 | 38 | Args.getLastArg(options::OPT_foptimization_record_file_EQ); |
1455 | 38 | if (hasMultipleInvocations && hasExplicitOutputFile4 ) { |
1456 | 2 | D.Diag(diag::err_drv_invalid_output_with_multiple_archs) |
1457 | 2 | << "-foptimization-record-file"; |
1458 | 2 | return false; |
1459 | 2 | } |
1460 | 36 | return true; |
1461 | 38 | } |
1462 | | |
1463 | | static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, |
1464 | | const llvm::Triple &Triple, |
1465 | | const InputInfo &Input, |
1466 | 36 | const InputInfo &Output, const JobAction &JA) { |
1467 | 36 | StringRef Format = "yaml"; |
1468 | 36 | if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) |
1469 | 4 | Format = A->getValue(); |
1470 | | |
1471 | 36 | CmdArgs.push_back("-opt-record-file"); |
1472 | | |
1473 | 36 | const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ); |
1474 | 36 | if (A) { |
1475 | 3 | CmdArgs.push_back(A->getValue()); |
1476 | 33 | } else { |
1477 | 33 | bool hasMultipleArchs = |
1478 | 33 | Triple.isOSDarwin() && // Only supported on Darwin platforms. |
1479 | 33 | Args.getAllArgValues(options::OPT_arch).size() > 127 ; |
1480 | | |
1481 | 33 | SmallString<128> F; |
1482 | | |
1483 | 33 | if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)19 ) { |
1484 | 24 | if (Arg *FinalOutput = Args.getLastArg(options::OPT_o)) |
1485 | 16 | F = FinalOutput->getValue(); |
1486 | 24 | } else { |
1487 | 9 | if (Format != "yaml" && // For YAML, keep the original behavior. |
1488 | 9 | Triple.isOSDarwin()1 && // Enable this only on darwin, since it's the only platform supporting .dSYM bundles. |
1489 | 9 | Output.isFilename()1 ) |
1490 | 1 | F = Output.getFilename(); |
1491 | 9 | } |
1492 | | |
1493 | 33 | if (F.empty()) { |
1494 | | // Use the input filename. |
1495 | 16 | F = llvm::sys::path::stem(Input.getBaseInput()); |
1496 | | |
1497 | | // If we're compiling for an offload architecture (i.e. a CUDA device), |
1498 | | // we need to make the file name for the device compilation different |
1499 | | // from the host compilation. |
1500 | 16 | if (!JA.isDeviceOffloading(Action::OFK_None) && |
1501 | 16 | !JA.isDeviceOffloading(Action::OFK_Host)2 ) { |
1502 | 2 | llvm::sys::path::replace_extension(F, ""); |
1503 | 2 | F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(), |
1504 | 2 | Triple.normalize()); |
1505 | 2 | F += "-"; |
1506 | 2 | F += JA.getOffloadingArch(); |
1507 | 2 | } |
1508 | 16 | } |
1509 | | |
1510 | | // If we're having more than one "-arch", we should name the files |
1511 | | // differently so that every cc1 invocation writes to a different file. |
1512 | | // We're doing that by appending "-<arch>" with "<arch>" being the arch |
1513 | | // name from the triple. |
1514 | 33 | if (hasMultipleArchs) { |
1515 | | // First, remember the extension. |
1516 | 2 | SmallString<64> OldExtension = llvm::sys::path::extension(F); |
1517 | | // then, remove it. |
1518 | 2 | llvm::sys::path::replace_extension(F, ""); |
1519 | | // attach -<arch> to it. |
1520 | 2 | F += "-"; |
1521 | 2 | F += Triple.getArchName(); |
1522 | | // put back the extension. |
1523 | 2 | llvm::sys::path::replace_extension(F, OldExtension); |
1524 | 2 | } |
1525 | | |
1526 | 33 | SmallString<32> Extension; |
1527 | 33 | Extension += "opt."; |
1528 | 33 | Extension += Format; |
1529 | | |
1530 | 33 | llvm::sys::path::replace_extension(F, Extension); |
1531 | 33 | CmdArgs.push_back(Args.MakeArgString(F)); |
1532 | 33 | } |
1533 | | |
1534 | 36 | if (const Arg *A = |
1535 | 36 | Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) { |
1536 | 4 | CmdArgs.push_back("-opt-record-passes"); |
1537 | 4 | CmdArgs.push_back(A->getValue()); |
1538 | 4 | } |
1539 | | |
1540 | 36 | if (!Format.empty()) { |
1541 | 36 | CmdArgs.push_back("-opt-record-format"); |
1542 | 36 | CmdArgs.push_back(Format.data()); |
1543 | 36 | } |
1544 | 36 | } |
1545 | | |
1546 | 3.87k | void AddAAPCSVolatileBitfieldArgs(const ArgList &Args, ArgStringList &CmdArgs) { |
1547 | 3.87k | if (!Args.hasFlag(options::OPT_faapcs_bitfield_width, |
1548 | 3.87k | options::OPT_fno_aapcs_bitfield_width, true)) |
1549 | 2 | CmdArgs.push_back("-fno-aapcs-bitfield-width"); |
1550 | | |
1551 | 3.87k | if (Args.getLastArg(options::OPT_ForceAAPCSBitfieldLoad)) |
1552 | 2 | CmdArgs.push_back("-faapcs-bitfield-load"); |
1553 | 3.87k | } |
1554 | | |
1555 | | namespace { |
1556 | | void RenderARMABI(const Driver &D, const llvm::Triple &Triple, |
1557 | 2.09k | const ArgList &Args, ArgStringList &CmdArgs) { |
1558 | | // Select the ABI to use. |
1559 | | // FIXME: Support -meabi. |
1560 | | // FIXME: Parts of this are duplicated in the backend, unify this somehow. |
1561 | 2.09k | const char *ABIName = nullptr; |
1562 | 2.09k | if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { |
1563 | 4 | ABIName = A->getValue(); |
1564 | 2.08k | } else { |
1565 | 2.08k | std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ false); |
1566 | 2.08k | ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data(); |
1567 | 2.08k | } |
1568 | | |
1569 | 2.09k | CmdArgs.push_back("-target-abi"); |
1570 | 2.09k | CmdArgs.push_back(ABIName); |
1571 | 2.09k | } |
1572 | | |
1573 | 3.87k | void AddUnalignedAccessWarning(ArgStringList &CmdArgs) { |
1574 | 3.87k | auto StrictAlignIter = |
1575 | 115k | llvm::find_if(llvm::reverse(CmdArgs), [](StringRef Arg) { |
1576 | 115k | return Arg == "+strict-align" || Arg == "-strict-align"113k ; |
1577 | 115k | }); |
1578 | 3.87k | if (StrictAlignIter != CmdArgs.rend() && |
1579 | 3.87k | StringRef(*StrictAlignIter) == "+strict-align"1.52k ) |
1580 | 1.52k | CmdArgs.push_back("-Wunaligned-access"); |
1581 | 3.87k | } |
1582 | | } |
1583 | | |
1584 | | static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, |
1585 | 3.87k | ArgStringList &CmdArgs, bool isAArch64) { |
1586 | 3.87k | const Arg *A = isAArch64 |
1587 | 3.87k | ? Args.getLastArg(options::OPT_msign_return_address_EQ, |
1588 | 1.78k | options::OPT_mbranch_protection_EQ) |
1589 | 3.87k | : Args.getLastArg(options::OPT_mbranch_protection_EQ)2.09k ; |
1590 | 3.87k | if (!A) |
1591 | 3.79k | return; |
1592 | | |
1593 | 77 | const Driver &D = TC.getDriver(); |
1594 | 77 | const llvm::Triple &Triple = TC.getEffectiveTriple(); |
1595 | 77 | if (!(isAArch64 || (45 Triple.isArmT32()45 && Triple.isArmMClass()43 ))) |
1596 | 7 | D.Diag(diag::warn_incompatible_branch_protection_option) |
1597 | 7 | << Triple.getArchName(); |
1598 | | |
1599 | 77 | StringRef Scope, Key; |
1600 | 77 | bool IndirectBranches; |
1601 | | |
1602 | 77 | if (A->getOption().matches(options::OPT_msign_return_address_EQ)) { |
1603 | 8 | Scope = A->getValue(); |
1604 | 8 | if (Scope != "none" && Scope != "non-leaf"5 && Scope != "all"3 ) |
1605 | 1 | D.Diag(diag::err_drv_unsupported_option_argument) |
1606 | 1 | << A->getSpelling() << Scope; |
1607 | 8 | Key = "a_key"; |
1608 | 8 | IndirectBranches = false; |
1609 | 69 | } else { |
1610 | 69 | StringRef DiagMsg; |
1611 | 69 | llvm::ARM::ParsedBranchProtection PBP; |
1612 | 69 | if (!llvm::ARM::parseBranchProtection(A->getValue(), PBP, DiagMsg)) |
1613 | 4 | D.Diag(diag::err_drv_unsupported_option_argument) |
1614 | 4 | << A->getSpelling() << DiagMsg; |
1615 | 69 | if (!isAArch64 && PBP.Key == "b_key"45 ) |
1616 | 13 | D.Diag(diag::warn_unsupported_branch_protection) |
1617 | 13 | << "b-key" << A->getAsString(Args); |
1618 | 69 | Scope = PBP.Scope; |
1619 | 69 | Key = PBP.Key; |
1620 | 69 | IndirectBranches = PBP.BranchTargetEnforcement; |
1621 | 69 | } |
1622 | | |
1623 | 77 | CmdArgs.push_back( |
1624 | 77 | Args.MakeArgString(Twine("-msign-return-address=") + Scope)); |
1625 | 77 | if (!Scope.equals("none")) |
1626 | 49 | CmdArgs.push_back( |
1627 | 49 | Args.MakeArgString(Twine("-msign-return-address-key=") + Key)); |
1628 | 77 | if (IndirectBranches) |
1629 | 35 | CmdArgs.push_back("-mbranch-target-enforce"); |
1630 | 77 | } |
1631 | | |
1632 | | void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, |
1633 | 2.09k | ArgStringList &CmdArgs, bool KernelOrKext) const { |
1634 | 2.09k | RenderARMABI(getToolChain().getDriver(), Triple, Args, CmdArgs); |
1635 | | |
1636 | | // Determine floating point ABI from the options & target defaults. |
1637 | 2.09k | arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args); |
1638 | 2.09k | if (ABI == arm::FloatABI::Soft) { |
1639 | | // Floating point operations and argument passing are soft. |
1640 | | // FIXME: This changes CPP defines, we need -target-soft-float. |
1641 | 885 | CmdArgs.push_back("-msoft-float"); |
1642 | 885 | CmdArgs.push_back("-mfloat-abi"); |
1643 | 885 | CmdArgs.push_back("soft"); |
1644 | 1.20k | } else if (ABI == arm::FloatABI::SoftFP) { |
1645 | | // Floating point operations are hard, but argument passing is soft. |
1646 | 969 | CmdArgs.push_back("-mfloat-abi"); |
1647 | 969 | CmdArgs.push_back("soft"); |
1648 | 969 | } else { |
1649 | | // Floating point operations and argument passing are hard. |
1650 | 236 | assert(ABI == arm::FloatABI::Hard && "Invalid float abi!"); |
1651 | 236 | CmdArgs.push_back("-mfloat-abi"); |
1652 | 236 | CmdArgs.push_back("hard"); |
1653 | 236 | } |
1654 | | |
1655 | | // Forward the -mglobal-merge option for explicit control over the pass. |
1656 | 2.09k | if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, |
1657 | 2.09k | options::OPT_mno_global_merge)) { |
1658 | 2 | CmdArgs.push_back("-mllvm"); |
1659 | 2 | if (A->getOption().matches(options::OPT_mno_global_merge)) |
1660 | 1 | CmdArgs.push_back("-arm-global-merge=false"); |
1661 | 1 | else |
1662 | 1 | CmdArgs.push_back("-arm-global-merge=true"); |
1663 | 2 | } |
1664 | | |
1665 | 2.09k | if (!Args.hasFlag(options::OPT_mimplicit_float, |
1666 | 2.09k | options::OPT_mno_implicit_float, true)) |
1667 | 1 | CmdArgs.push_back("-no-implicit-float"); |
1668 | | |
1669 | 2.09k | if (Args.getLastArg(options::OPT_mcmse)) |
1670 | 21 | CmdArgs.push_back("-mcmse"); |
1671 | | |
1672 | 2.09k | AddAAPCSVolatileBitfieldArgs(Args, CmdArgs); |
1673 | | |
1674 | | // Enable/disable return address signing and indirect branch targets. |
1675 | 2.09k | CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, false /*isAArch64*/); |
1676 | | |
1677 | 2.09k | AddUnalignedAccessWarning(CmdArgs); |
1678 | 2.09k | } |
1679 | | |
1680 | | void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple, |
1681 | | const ArgList &Args, bool KernelOrKext, |
1682 | 47.7k | ArgStringList &CmdArgs) const { |
1683 | 47.7k | const ToolChain &TC = getToolChain(); |
1684 | | |
1685 | | // Add the target features |
1686 | 47.7k | getTargetFeatures(TC.getDriver(), EffectiveTriple, Args, CmdArgs, false); |
1687 | | |
1688 | | // Add target specific flags. |
1689 | 47.7k | switch (TC.getArch()) { |
1690 | 1.20k | default: |
1691 | 1.20k | break; |
1692 | | |
1693 | 1.85k | case llvm::Triple::arm: |
1694 | 2.00k | case llvm::Triple::armeb: |
1695 | 2.07k | case llvm::Triple::thumb: |
1696 | 2.09k | case llvm::Triple::thumbeb: |
1697 | | // Use the effective triple, which takes into account the deployment target. |
1698 | 2.09k | AddARMTargetArgs(EffectiveTriple, Args, CmdArgs, KernelOrKext); |
1699 | 2.09k | break; |
1700 | | |
1701 | 1.55k | case llvm::Triple::aarch64: |
1702 | 1.55k | case llvm::Triple::aarch64_32: |
1703 | 1.78k | case llvm::Triple::aarch64_be: |
1704 | 1.78k | AddAArch64TargetArgs(Args, CmdArgs); |
1705 | 1.78k | break; |
1706 | | |
1707 | 32 | case llvm::Triple::loongarch32: |
1708 | 145 | case llvm::Triple::loongarch64: |
1709 | 145 | AddLoongArchTargetArgs(Args, CmdArgs); |
1710 | 145 | break; |
1711 | | |
1712 | 189 | case llvm::Triple::mips: |
1713 | 232 | case llvm::Triple::mipsel: |
1714 | 301 | case llvm::Triple::mips64: |
1715 | 349 | case llvm::Triple::mips64el: |
1716 | 349 | AddMIPSTargetArgs(Args, CmdArgs); |
1717 | 349 | break; |
1718 | | |
1719 | 234 | case llvm::Triple::ppc: |
1720 | 242 | case llvm::Triple::ppcle: |
1721 | 478 | case llvm::Triple::ppc64: |
1722 | 595 | case llvm::Triple::ppc64le: |
1723 | 595 | AddPPCTargetArgs(Args, CmdArgs); |
1724 | 595 | break; |
1725 | | |
1726 | 392 | case llvm::Triple::riscv32: |
1727 | 735 | case llvm::Triple::riscv64: |
1728 | 735 | AddRISCVTargetArgs(Args, CmdArgs); |
1729 | 735 | break; |
1730 | | |
1731 | 133 | case llvm::Triple::sparc: |
1732 | 139 | case llvm::Triple::sparcel: |
1733 | 209 | case llvm::Triple::sparcv9: |
1734 | 209 | AddSparcTargetArgs(Args, CmdArgs); |
1735 | 209 | break; |
1736 | | |
1737 | 98 | case llvm::Triple::systemz: |
1738 | 98 | AddSystemZTargetArgs(Args, CmdArgs); |
1739 | 98 | break; |
1740 | | |
1741 | 11.2k | case llvm::Triple::x86: |
1742 | 40.2k | case llvm::Triple::x86_64: |
1743 | 40.2k | AddX86TargetArgs(Args, CmdArgs); |
1744 | 40.2k | break; |
1745 | | |
1746 | 3 | case llvm::Triple::lanai: |
1747 | 3 | AddLanaiTargetArgs(Args, CmdArgs); |
1748 | 3 | break; |
1749 | | |
1750 | 137 | case llvm::Triple::hexagon: |
1751 | 137 | AddHexagonTargetArgs(Args, CmdArgs); |
1752 | 137 | break; |
1753 | | |
1754 | 97 | case llvm::Triple::wasm32: |
1755 | 129 | case llvm::Triple::wasm64: |
1756 | 129 | AddWebAssemblyTargetArgs(Args, CmdArgs); |
1757 | 129 | break; |
1758 | | |
1759 | 4 | case llvm::Triple::ve: |
1760 | 4 | AddVETargetArgs(Args, CmdArgs); |
1761 | 4 | break; |
1762 | 47.7k | } |
1763 | 47.7k | } |
1764 | | |
1765 | | namespace { |
1766 | | void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args, |
1767 | 1.78k | ArgStringList &CmdArgs) { |
1768 | 1.78k | const char *ABIName = nullptr; |
1769 | 1.78k | if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) |
1770 | 0 | ABIName = A->getValue(); |
1771 | 1.78k | else if (Triple.isOSDarwin()) |
1772 | 181 | ABIName = "darwinpcs"; |
1773 | 1.60k | else |
1774 | 1.60k | ABIName = "aapcs"; |
1775 | | |
1776 | 1.78k | CmdArgs.push_back("-target-abi"); |
1777 | 1.78k | CmdArgs.push_back(ABIName); |
1778 | 1.78k | } |
1779 | | } |
1780 | | |
1781 | | void Clang::AddAArch64TargetArgs(const ArgList &Args, |
1782 | 1.78k | ArgStringList &CmdArgs) const { |
1783 | 1.78k | const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); |
1784 | | |
1785 | 1.78k | if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || |
1786 | 1.78k | Args.hasArg(options::OPT_mkernel) || |
1787 | 1.78k | Args.hasArg(options::OPT_fapple_kext)1.78k ) |
1788 | 3 | CmdArgs.push_back("-disable-red-zone"); |
1789 | | |
1790 | 1.78k | if (!Args.hasFlag(options::OPT_mimplicit_float, |
1791 | 1.78k | options::OPT_mno_implicit_float, true)) |
1792 | 0 | CmdArgs.push_back("-no-implicit-float"); |
1793 | | |
1794 | 1.78k | RenderAArch64ABI(Triple, Args, CmdArgs); |
1795 | | |
1796 | | // Forward the -mglobal-merge option for explicit control over the pass. |
1797 | 1.78k | if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, |
1798 | 1.78k | options::OPT_mno_global_merge)) { |
1799 | 2 | CmdArgs.push_back("-mllvm"); |
1800 | 2 | if (A->getOption().matches(options::OPT_mno_global_merge)) |
1801 | 1 | CmdArgs.push_back("-aarch64-enable-global-merge=false"); |
1802 | 1 | else |
1803 | 1 | CmdArgs.push_back("-aarch64-enable-global-merge=true"); |
1804 | 2 | } |
1805 | | |
1806 | | // Enable/disable return address signing and indirect branch targets. |
1807 | 1.78k | CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, true /*isAArch64*/); |
1808 | | |
1809 | | // Handle -msve_vector_bits=<bits> |
1810 | 1.78k | if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { |
1811 | 22 | StringRef Val = A->getValue(); |
1812 | 22 | const Driver &D = getToolChain().getDriver(); |
1813 | 22 | if (Val.equals("128") || Val.equals("256")19 || Val.equals("512")17 || |
1814 | 22 | Val.equals("1024")15 || Val.equals("2048")13 || Val.equals("128+")11 || |
1815 | 22 | Val.equals("256+")10 || Val.equals("512+")8 || Val.equals("1024+")6 || |
1816 | 22 | Val.equals("2048+")5 ) { |
1817 | 18 | unsigned Bits = 0; |
1818 | 18 | if (Val.endswith("+")) |
1819 | 7 | Val = Val.substr(0, Val.size() - 1); |
1820 | 11 | else { |
1821 | 11 | bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid; |
1822 | 11 | assert(!Invalid && "Failed to parse value"); |
1823 | 11 | CmdArgs.push_back( |
1824 | 11 | Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128))); |
1825 | 11 | } |
1826 | | |
1827 | 18 | bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid; |
1828 | 18 | assert(!Invalid && "Failed to parse value"); |
1829 | 18 | CmdArgs.push_back( |
1830 | 18 | Args.MakeArgString("-mvscale-min=" + llvm::Twine(Bits / 128))); |
1831 | | // Silently drop requests for vector-length agnostic code as it's implied. |
1832 | 18 | } else if (4 !Val.equals("scalable")4 ) |
1833 | | // Handle the unsupported values passed to msve-vector-bits. |
1834 | 2 | D.Diag(diag::err_drv_unsupported_option_argument) |
1835 | 2 | << A->getSpelling() << Val; |
1836 | 22 | } |
1837 | | |
1838 | 1.78k | AddAAPCSVolatileBitfieldArgs(Args, CmdArgs); |
1839 | | |
1840 | 1.78k | if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) { |
1841 | 149 | CmdArgs.push_back("-tune-cpu"); |
1842 | 149 | if (strcmp(A->getValue(), "native") == 0) |
1843 | 0 | CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName())); |
1844 | 149 | else |
1845 | 149 | CmdArgs.push_back(A->getValue()); |
1846 | 149 | } |
1847 | | |
1848 | 1.78k | AddUnalignedAccessWarning(CmdArgs); |
1849 | 1.78k | } |
1850 | | |
1851 | | void Clang::AddLoongArchTargetArgs(const ArgList &Args, |
1852 | 145 | ArgStringList &CmdArgs) const { |
1853 | 145 | const llvm::Triple &Triple = getToolChain().getTriple(); |
1854 | | |
1855 | 145 | CmdArgs.push_back("-target-abi"); |
1856 | 145 | CmdArgs.push_back( |
1857 | 145 | loongarch::getLoongArchABI(getToolChain().getDriver(), Args, Triple) |
1858 | 145 | .data()); |
1859 | | |
1860 | | // Handle -mtune. |
1861 | 145 | if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) { |
1862 | 14 | std::string TuneCPU = A->getValue(); |
1863 | 14 | TuneCPU = loongarch::postProcessTargetCPUString(TuneCPU, Triple); |
1864 | 14 | CmdArgs.push_back("-tune-cpu"); |
1865 | 14 | CmdArgs.push_back(Args.MakeArgString(TuneCPU)); |
1866 | 14 | } |
1867 | 145 | } |
1868 | | |
1869 | | void Clang::AddMIPSTargetArgs(const ArgList &Args, |
1870 | 349 | ArgStringList &CmdArgs) const { |
1871 | 349 | const Driver &D = getToolChain().getDriver(); |
1872 | 349 | StringRef CPUName; |
1873 | 349 | StringRef ABIName; |
1874 | 349 | const llvm::Triple &Triple = getToolChain().getTriple(); |
1875 | 349 | mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
1876 | | |
1877 | 349 | CmdArgs.push_back("-target-abi"); |
1878 | 349 | CmdArgs.push_back(ABIName.data()); |
1879 | | |
1880 | 349 | mips::FloatABI ABI = mips::getMipsFloatABI(D, Args, Triple); |
1881 | 349 | if (ABI == mips::FloatABI::Soft) { |
1882 | | // Floating point operations and argument passing are soft. |
1883 | 62 | CmdArgs.push_back("-msoft-float"); |
1884 | 62 | CmdArgs.push_back("-mfloat-abi"); |
1885 | 62 | CmdArgs.push_back("soft"); |
1886 | 287 | } else { |
1887 | | // Floating point operations and argument passing are hard. |
1888 | 287 | assert(ABI == mips::FloatABI::Hard && "Invalid float abi!"); |
1889 | 287 | CmdArgs.push_back("-mfloat-abi"); |
1890 | 287 | CmdArgs.push_back("hard"); |
1891 | 287 | } |
1892 | | |
1893 | 349 | if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1, |
1894 | 349 | options::OPT_mno_ldc1_sdc1)) { |
1895 | 2 | if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) { |
1896 | 1 | CmdArgs.push_back("-mllvm"); |
1897 | 1 | CmdArgs.push_back("-mno-ldc1-sdc1"); |
1898 | 1 | } |
1899 | 2 | } |
1900 | | |
1901 | 349 | if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division, |
1902 | 349 | options::OPT_mno_check_zero_division)) { |
1903 | 2 | if (A->getOption().matches(options::OPT_mno_check_zero_division)) { |
1904 | 1 | CmdArgs.push_back("-mllvm"); |
1905 | 1 | CmdArgs.push_back("-mno-check-zero-division"); |
1906 | 1 | } |
1907 | 2 | } |
1908 | | |
1909 | 349 | if (Args.getLastArg(options::OPT_mfix4300)) { |
1910 | 0 | CmdArgs.push_back("-mllvm"); |
1911 | 0 | CmdArgs.push_back("-mfix4300"); |
1912 | 0 | } |
1913 | | |
1914 | 349 | if (Arg *A = Args.getLastArg(options::OPT_G)) { |
1915 | 3 | StringRef v = A->getValue(); |
1916 | 3 | CmdArgs.push_back("-mllvm"); |
1917 | 3 | CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v)); |
1918 | 3 | A->claim(); |
1919 | 3 | } |
1920 | | |
1921 | 349 | Arg *GPOpt = Args.getLastArg(options::OPT_mgpopt, options::OPT_mno_gpopt); |
1922 | 349 | Arg *ABICalls = |
1923 | 349 | Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls); |
1924 | | |
1925 | | // -mabicalls is the default for many MIPS environments, even with -fno-pic. |
1926 | | // -mgpopt is the default for static, -fno-pic environments but these two |
1927 | | // options conflict. We want to be certain that -mno-abicalls -mgpopt is |
1928 | | // the only case where -mllvm -mgpopt is passed. |
1929 | | // NOTE: We need a warning here or in the backend to warn when -mgpopt is |
1930 | | // passed explicitly when compiling something with -mabicalls |
1931 | | // (implictly) in affect. Currently the warning is in the backend. |
1932 | | // |
1933 | | // When the ABI in use is N64, we also need to determine the PIC mode that |
1934 | | // is in use, as -fno-pic for N64 implies -mno-abicalls. |
1935 | 349 | bool NoABICalls = |
1936 | 349 | ABICalls && ABICalls->getOption().matches(options::OPT_mno_abicalls)30 ; |
1937 | | |
1938 | 349 | llvm::Reloc::Model RelocationModel; |
1939 | 349 | unsigned PICLevel; |
1940 | 349 | bool IsPIE; |
1941 | 349 | std::tie(RelocationModel, PICLevel, IsPIE) = |
1942 | 349 | ParsePICArgs(getToolChain(), Args); |
1943 | | |
1944 | 349 | NoABICalls = NoABICalls || |
1945 | 349 | (321 RelocationModel == llvm::Reloc::Static321 && ABIName == "n64"66 ); |
1946 | | |
1947 | 349 | bool WantGPOpt = GPOpt && GPOpt->getOption().matches(options::OPT_mgpopt)15 ; |
1948 | | // We quietly ignore -mno-gpopt as the backend defaults to -mno-gpopt. |
1949 | 349 | if (NoABICalls && (28 !GPOpt28 || WantGPOpt12 )) { |
1950 | 26 | CmdArgs.push_back("-mllvm"); |
1951 | 26 | CmdArgs.push_back("-mgpopt"); |
1952 | | |
1953 | 26 | Arg *LocalSData = Args.getLastArg(options::OPT_mlocal_sdata, |
1954 | 26 | options::OPT_mno_local_sdata); |
1955 | 26 | Arg *ExternSData = Args.getLastArg(options::OPT_mextern_sdata, |
1956 | 26 | options::OPT_mno_extern_sdata); |
1957 | 26 | Arg *EmbeddedData = Args.getLastArg(options::OPT_membedded_data, |
1958 | 26 | options::OPT_mno_embedded_data); |
1959 | 26 | if (LocalSData) { |
1960 | 2 | CmdArgs.push_back("-mllvm"); |
1961 | 2 | if (LocalSData->getOption().matches(options::OPT_mlocal_sdata)) { |
1962 | 1 | CmdArgs.push_back("-mlocal-sdata=1"); |
1963 | 1 | } else { |
1964 | 1 | CmdArgs.push_back("-mlocal-sdata=0"); |
1965 | 1 | } |
1966 | 2 | LocalSData->claim(); |
1967 | 2 | } |
1968 | | |
1969 | 26 | if (ExternSData) { |
1970 | 2 | CmdArgs.push_back("-mllvm"); |
1971 | 2 | if (ExternSData->getOption().matches(options::OPT_mextern_sdata)) { |
1972 | 1 | CmdArgs.push_back("-mextern-sdata=1"); |
1973 | 1 | } else { |
1974 | 1 | CmdArgs.push_back("-mextern-sdata=0"); |
1975 | 1 | } |
1976 | 2 | ExternSData->claim(); |
1977 | 2 | } |
1978 | | |
1979 | 26 | if (EmbeddedData) { |
1980 | 2 | CmdArgs.push_back("-mllvm"); |
1981 | 2 | if (EmbeddedData->getOption().matches(options::OPT_membedded_data)) { |
1982 | 1 | CmdArgs.push_back("-membedded-data=1"); |
1983 | 1 | } else { |
1984 | 1 | CmdArgs.push_back("-membedded-data=0"); |
1985 | 1 | } |
1986 | 2 | EmbeddedData->claim(); |
1987 | 2 | } |
1988 | | |
1989 | 323 | } else if ((!ABICalls || (4 !NoABICalls4 && ABICalls2 )) && WantGPOpt321 ) |
1990 | 3 | D.Diag(diag::warn_drv_unsupported_gpopt) << (ABICalls ? 01 : 12 ); |
1991 | | |
1992 | 349 | if (GPOpt) |
1993 | 15 | GPOpt->claim(); |
1994 | | |
1995 | 349 | if (Arg *A = Args.getLastArg(options::OPT_mcompact_branches_EQ)) { |
1996 | 3 | StringRef Val = StringRef(A->getValue()); |
1997 | 3 | if (mips::hasCompactBranches(CPUName)) { |
1998 | 3 | if (Val == "never" || Val == "always"2 || Val == "optimal"1 ) { |
1999 | 3 | CmdArgs.push_back("-mllvm"); |
2000 | 3 | CmdArgs.push_back(Args.MakeArgString("-mips-compact-branches=" + Val)); |
2001 | 3 | } else |
2002 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
2003 | 0 | << A->getSpelling() << Val; |
2004 | 3 | } else |
2005 | 0 | D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName; |
2006 | 3 | } |
2007 | | |
2008 | 349 | if (Arg *A = Args.getLastArg(options::OPT_mrelax_pic_calls, |
2009 | 349 | options::OPT_mno_relax_pic_calls)) { |
2010 | 2 | if (A->getOption().matches(options::OPT_mno_relax_pic_calls)) { |
2011 | 1 | CmdArgs.push_back("-mllvm"); |
2012 | 1 | CmdArgs.push_back("-mips-jalr-reloc=0"); |
2013 | 1 | } |
2014 | 2 | } |
2015 | 349 | } |
2016 | | |
2017 | | void Clang::AddPPCTargetArgs(const ArgList &Args, |
2018 | 595 | ArgStringList &CmdArgs) const { |
2019 | 595 | const Driver &D = getToolChain().getDriver(); |
2020 | 595 | const llvm::Triple &T = getToolChain().getTriple(); |
2021 | 595 | if (Args.getLastArg(options::OPT_mtune_EQ)) { |
2022 | 2 | CmdArgs.push_back("-tune-cpu"); |
2023 | 2 | std::string CPU = ppc::getPPCTuneCPU(Args, T); |
2024 | 2 | CmdArgs.push_back(Args.MakeArgString(CPU)); |
2025 | 2 | } |
2026 | | |
2027 | | // Select the ABI to use. |
2028 | 595 | const char *ABIName = nullptr; |
2029 | 595 | if (T.isOSBinFormatELF()) { |
2030 | 354 | switch (getToolChain().getArch()) { |
2031 | 154 | case llvm::Triple::ppc64: { |
2032 | 154 | if (T.isPPC64ELFv2ABI()) |
2033 | 8 | ABIName = "elfv2"; |
2034 | 146 | else |
2035 | 146 | ABIName = "elfv1"; |
2036 | 154 | break; |
2037 | 0 | } |
2038 | 117 | case llvm::Triple::ppc64le: |
2039 | 117 | ABIName = "elfv2"; |
2040 | 117 | break; |
2041 | 83 | default: |
2042 | 83 | break; |
2043 | 354 | } |
2044 | 354 | } |
2045 | | |
2046 | 595 | bool IEEELongDouble = getToolChain().defaultToIEEELongDouble(); |
2047 | 595 | bool VecExtabi = false; |
2048 | 595 | for (const Arg *A : Args.filtered(options::OPT_mabi_EQ)) { |
2049 | 42 | StringRef V = A->getValue(); |
2050 | 42 | if (V == "ieeelongdouble") { |
2051 | 4 | IEEELongDouble = true; |
2052 | 4 | A->claim(); |
2053 | 38 | } else if (V == "ibmlongdouble") { |
2054 | 6 | IEEELongDouble = false; |
2055 | 6 | A->claim(); |
2056 | 32 | } else if (V == "vec-default") { |
2057 | 5 | VecExtabi = false; |
2058 | 5 | A->claim(); |
2059 | 27 | } else if (V == "vec-extabi") { |
2060 | 7 | VecExtabi = true; |
2061 | 7 | A->claim(); |
2062 | 20 | } else if (V == "elfv1") { |
2063 | 10 | ABIName = "elfv1"; |
2064 | 10 | A->claim(); |
2065 | 10 | } else if (V == "elfv2") { |
2066 | 8 | ABIName = "elfv2"; |
2067 | 8 | A->claim(); |
2068 | 8 | } else if (2 V != "altivec"2 ) |
2069 | | // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore |
2070 | | // the option if given as we don't have backend support for any targets |
2071 | | // that don't use the altivec abi. |
2072 | 0 | ABIName = A->getValue(); |
2073 | 42 | } |
2074 | 595 | if (IEEELongDouble) |
2075 | 4 | CmdArgs.push_back("-mabi=ieeelongdouble"); |
2076 | 595 | if (VecExtabi) { |
2077 | 7 | if (!T.isOSAIX()) |
2078 | 0 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
2079 | 0 | << "-mabi=vec-extabi" << T.str(); |
2080 | 7 | CmdArgs.push_back("-mabi=vec-extabi"); |
2081 | 7 | } |
2082 | | |
2083 | 595 | ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); |
2084 | 595 | if (FloatABI == ppc::FloatABI::Soft) { |
2085 | | // Floating point operations and argument passing are soft. |
2086 | 9 | CmdArgs.push_back("-msoft-float"); |
2087 | 9 | CmdArgs.push_back("-mfloat-abi"); |
2088 | 9 | CmdArgs.push_back("soft"); |
2089 | 586 | } else { |
2090 | | // Floating point operations and argument passing are hard. |
2091 | 586 | assert(FloatABI == ppc::FloatABI::Hard && "Invalid float abi!"); |
2092 | 586 | CmdArgs.push_back("-mfloat-abi"); |
2093 | 586 | CmdArgs.push_back("hard"); |
2094 | 586 | } |
2095 | | |
2096 | 595 | if (ABIName) { |
2097 | 271 | CmdArgs.push_back("-target-abi"); |
2098 | 271 | CmdArgs.push_back(ABIName); |
2099 | 271 | } |
2100 | 595 | } |
2101 | | |
2102 | | static void SetRISCVSmallDataLimit(const ToolChain &TC, const ArgList &Args, |
2103 | 735 | ArgStringList &CmdArgs) { |
2104 | 735 | const Driver &D = TC.getDriver(); |
2105 | 735 | const llvm::Triple &Triple = TC.getTriple(); |
2106 | | // Default small data limitation is eight. |
2107 | 735 | const char *SmallDataLimit = "8"; |
2108 | | // Get small data limitation. |
2109 | 735 | if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, |
2110 | 735 | options::OPT_fPIC)) { |
2111 | | // Not support linker relaxation for PIC. |
2112 | 4 | SmallDataLimit = "0"; |
2113 | 4 | if (Args.hasArg(options::OPT_G)) { |
2114 | 0 | D.Diag(diag::warn_drv_unsupported_sdata); |
2115 | 0 | } |
2116 | 731 | } else if (Args.getLastArgValue(options::OPT_mcmodel_EQ) |
2117 | 731 | .equals_insensitive("large") && |
2118 | 731 | (Triple.getArch() == llvm::Triple::riscv64)1 ) { |
2119 | | // Not support linker relaxation for RV64 with large code model. |
2120 | 1 | SmallDataLimit = "0"; |
2121 | 1 | if (Args.hasArg(options::OPT_G)) { |
2122 | 0 | D.Diag(diag::warn_drv_unsupported_sdata); |
2123 | 0 | } |
2124 | 730 | } else if (Triple.isAndroid()) { |
2125 | | // GP relaxation is not supported on Android. |
2126 | 12 | SmallDataLimit = "0"; |
2127 | 12 | if (Args.hasArg(options::OPT_G)) { |
2128 | 1 | D.Diag(diag::warn_drv_unsupported_sdata); |
2129 | 1 | } |
2130 | 718 | } else if (Arg *A = Args.getLastArg(options::OPT_G)) { |
2131 | 8 | SmallDataLimit = A->getValue(); |
2132 | 8 | } |
2133 | | // Forward the -msmall-data-limit= option. |
2134 | 735 | CmdArgs.push_back("-msmall-data-limit"); |
2135 | 735 | CmdArgs.push_back(SmallDataLimit); |
2136 | 735 | } |
2137 | | |
2138 | | void Clang::AddRISCVTargetArgs(const ArgList &Args, |
2139 | 735 | ArgStringList &CmdArgs) const { |
2140 | 735 | const llvm::Triple &Triple = getToolChain().getTriple(); |
2141 | 735 | StringRef ABIName = riscv::getRISCVABI(Args, Triple); |
2142 | | |
2143 | 735 | CmdArgs.push_back("-target-abi"); |
2144 | 735 | CmdArgs.push_back(ABIName.data()); |
2145 | | |
2146 | 735 | SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs); |
2147 | | |
2148 | 735 | if (!Args.hasFlag(options::OPT_mimplicit_float, |
2149 | 735 | options::OPT_mno_implicit_float, true)) |
2150 | 2 | CmdArgs.push_back("-no-implicit-float"); |
2151 | | |
2152 | 735 | if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) { |
2153 | 14 | CmdArgs.push_back("-tune-cpu"); |
2154 | 14 | if (strcmp(A->getValue(), "native") == 0) |
2155 | 1 | CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName())); |
2156 | 13 | else |
2157 | 13 | CmdArgs.push_back(A->getValue()); |
2158 | 14 | } |
2159 | | |
2160 | | // Handle -mrvv-vector-bits=<bits> |
2161 | 735 | if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) { |
2162 | 15 | StringRef Val = A->getValue(); |
2163 | 15 | const Driver &D = getToolChain().getDriver(); |
2164 | | |
2165 | | // Get minimum VLen from march. |
2166 | 15 | unsigned MinVLen = 0; |
2167 | 15 | StringRef Arch = riscv::getRISCVArch(Args, Triple); |
2168 | 15 | auto ISAInfo = llvm::RISCVISAInfo::parseArchString( |
2169 | 15 | Arch, /*EnableExperimentalExtensions*/ true); |
2170 | 15 | if (!ISAInfo) { |
2171 | | // Ignore parsing error. |
2172 | 0 | consumeError(ISAInfo.takeError()); |
2173 | 15 | } else { |
2174 | 15 | MinVLen = (*ISAInfo)->getMinVLen(); |
2175 | 15 | } |
2176 | | |
2177 | | // If the value is "zvl", use MinVLen from march. Otherwise, try to parse |
2178 | | // as integer as long as we have a MinVLen. |
2179 | 15 | unsigned Bits = 0; |
2180 | 15 | if (Val.equals("zvl") && MinVLen >= llvm::RISCV::RVVBitsPerBlock3 ) { |
2181 | 2 | Bits = MinVLen; |
2182 | 13 | } else if (!Val.getAsInteger(10, Bits)) { |
2183 | | // Only accept power of 2 values beteen RVVBitsPerBlock and 65536 that |
2184 | | // at least MinVLen. |
2185 | 9 | if (Bits < MinVLen || Bits < llvm::RISCV::RVVBitsPerBlock7 || |
2186 | 9 | Bits > 655367 || !llvm::isPowerOf2_32(Bits)6 ) |
2187 | 3 | Bits = 0; |
2188 | 9 | } |
2189 | | |
2190 | | // If we got a valid value try to use it. |
2191 | 15 | if (Bits != 0) { |
2192 | 8 | unsigned VScaleMin = Bits / llvm::RISCV::RVVBitsPerBlock; |
2193 | 8 | CmdArgs.push_back( |
2194 | 8 | Args.MakeArgString("-mvscale-max=" + llvm::Twine(VScaleMin))); |
2195 | 8 | CmdArgs.push_back( |
2196 | 8 | Args.MakeArgString("-mvscale-min=" + llvm::Twine(VScaleMin))); |
2197 | 8 | } else if (7 !Val.equals("scalable")7 ) { |
2198 | | // Handle the unsupported values passed to mrvv-vector-bits. |
2199 | 5 | D.Diag(diag::err_drv_unsupported_option_argument) |
2200 | 5 | << A->getSpelling() << Val; |
2201 | 5 | } |
2202 | 15 | } |
2203 | 735 | } |
2204 | | |
2205 | | void Clang::AddSparcTargetArgs(const ArgList &Args, |
2206 | 209 | ArgStringList &CmdArgs) const { |
2207 | 209 | sparc::FloatABI FloatABI = |
2208 | 209 | sparc::getSparcFloatABI(getToolChain().getDriver(), Args); |
2209 | | |
2210 | 209 | if (FloatABI == sparc::FloatABI::Soft) { |
2211 | | // Floating point operations and argument passing are soft. |
2212 | 5 | CmdArgs.push_back("-msoft-float"); |
2213 | 5 | CmdArgs.push_back("-mfloat-abi"); |
2214 | 5 | CmdArgs.push_back("soft"); |
2215 | 204 | } else { |
2216 | | // Floating point operations and argument passing are hard. |
2217 | 204 | assert(FloatABI == sparc::FloatABI::Hard && "Invalid float abi!"); |
2218 | 204 | CmdArgs.push_back("-mfloat-abi"); |
2219 | 204 | CmdArgs.push_back("hard"); |
2220 | 204 | } |
2221 | | |
2222 | 209 | if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) { |
2223 | 4 | StringRef Name = A->getValue(); |
2224 | 4 | std::string TuneCPU; |
2225 | 4 | if (Name == "native") |
2226 | 0 | TuneCPU = std::string(llvm::sys::getHostCPUName()); |
2227 | 4 | else |
2228 | 4 | TuneCPU = std::string(Name); |
2229 | | |
2230 | 4 | CmdArgs.push_back("-tune-cpu"); |
2231 | 4 | CmdArgs.push_back(Args.MakeArgString(TuneCPU)); |
2232 | 4 | } |
2233 | 209 | } |
2234 | | |
2235 | | void Clang::AddSystemZTargetArgs(const ArgList &Args, |
2236 | 98 | ArgStringList &CmdArgs) const { |
2237 | 98 | if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) { |
2238 | 0 | CmdArgs.push_back("-tune-cpu"); |
2239 | 0 | if (strcmp(A->getValue(), "native") == 0) |
2240 | 0 | CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName())); |
2241 | 0 | else |
2242 | 0 | CmdArgs.push_back(A->getValue()); |
2243 | 0 | } |
2244 | | |
2245 | 98 | bool HasBackchain = |
2246 | 98 | Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false); |
2247 | 98 | bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack, |
2248 | 98 | options::OPT_mno_packed_stack, false); |
2249 | 98 | systemz::FloatABI FloatABI = |
2250 | 98 | systemz::getSystemZFloatABI(getToolChain().getDriver(), Args); |
2251 | 98 | bool HasSoftFloat = (FloatABI == systemz::FloatABI::Soft); |
2252 | 98 | if (HasBackchain && HasPackedStack1 && !HasSoftFloat0 ) { |
2253 | 0 | const Driver &D = getToolChain().getDriver(); |
2254 | 0 | D.Diag(diag::err_drv_unsupported_opt) |
2255 | 0 | << "-mpacked-stack -mbackchain -mhard-float"; |
2256 | 0 | } |
2257 | 98 | if (HasBackchain) |
2258 | 1 | CmdArgs.push_back("-mbackchain"); |
2259 | 98 | if (HasPackedStack) |
2260 | 0 | CmdArgs.push_back("-mpacked-stack"); |
2261 | 98 | if (HasSoftFloat) { |
2262 | | // Floating point operations and argument passing are soft. |
2263 | 1 | CmdArgs.push_back("-msoft-float"); |
2264 | 1 | CmdArgs.push_back("-mfloat-abi"); |
2265 | 1 | CmdArgs.push_back("soft"); |
2266 | 1 | } |
2267 | 98 | } |
2268 | | |
2269 | | void Clang::AddX86TargetArgs(const ArgList &Args, |
2270 | 40.2k | ArgStringList &CmdArgs) const { |
2271 | 40.2k | const Driver &D = getToolChain().getDriver(); |
2272 | 40.2k | addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/false); |
2273 | | |
2274 | 40.2k | if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || |
2275 | 40.2k | Args.hasArg(options::OPT_mkernel)40.2k || |
2276 | 40.2k | Args.hasArg(options::OPT_fapple_kext)40.2k ) |
2277 | 20 | CmdArgs.push_back("-disable-red-zone"); |
2278 | | |
2279 | 40.2k | if (!Args.hasFlag(options::OPT_mtls_direct_seg_refs, |
2280 | 40.2k | options::OPT_mno_tls_direct_seg_refs, true)) |
2281 | 1 | CmdArgs.push_back("-mno-tls-direct-seg-refs"); |
2282 | | |
2283 | | // Default to avoid implicit floating-point for kernel/kext code, but allow |
2284 | | // that to be overridden with -mno-soft-float. |
2285 | 40.2k | bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) || |
2286 | 40.2k | Args.hasArg(options::OPT_fapple_kext)40.2k ); |
2287 | 40.2k | if (Arg *A = Args.getLastArg( |
2288 | 40.2k | options::OPT_msoft_float, options::OPT_mno_soft_float, |
2289 | 40.2k | options::OPT_mimplicit_float, options::OPT_mno_implicit_float)) { |
2290 | 6 | const Option &O = A->getOption(); |
2291 | 6 | NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) || |
2292 | 6 | O.matches(options::OPT_msoft_float)5 ); |
2293 | 6 | } |
2294 | 40.2k | if (NoImplicitFloat) |
2295 | 21 | CmdArgs.push_back("-no-implicit-float"); |
2296 | | |
2297 | 40.2k | if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) { |
2298 | 3 | StringRef Value = A->getValue(); |
2299 | 3 | if (Value == "intel" || Value == "att"2 ) { |
2300 | 2 | CmdArgs.push_back("-mllvm"); |
2301 | 2 | CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value)); |
2302 | 2 | CmdArgs.push_back(Args.MakeArgString("-inline-asm=" + Value)); |
2303 | 2 | } else { |
2304 | 1 | D.Diag(diag::err_drv_unsupported_option_argument) |
2305 | 1 | << A->getSpelling() << Value; |
2306 | 1 | } |
2307 | 40.2k | } else if (D.IsCLMode()) { |
2308 | 703 | CmdArgs.push_back("-mllvm"); |
2309 | 703 | CmdArgs.push_back("-x86-asm-syntax=intel"); |
2310 | 703 | } |
2311 | | |
2312 | 40.2k | if (Arg *A = Args.getLastArg(options::OPT_mskip_rax_setup, |
2313 | 40.2k | options::OPT_mno_skip_rax_setup)) |
2314 | 2 | if (A->getOption().matches(options::OPT_mskip_rax_setup)) |
2315 | 1 | CmdArgs.push_back(Args.MakeArgString("-mskip-rax-setup")); |
2316 | | |
2317 | | // Set flags to support MCU ABI. |
2318 | 40.2k | if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) { |
2319 | 8 | CmdArgs.push_back("-mfloat-abi"); |
2320 | 8 | CmdArgs.push_back("soft"); |
2321 | 8 | CmdArgs.push_back("-mstack-alignment=4"); |
2322 | 8 | } |
2323 | | |
2324 | | // Handle -mtune. |
2325 | | |
2326 | | // Default to "generic" unless -march is present or targetting the PS4/PS5. |
2327 | 40.2k | std::string TuneCPU; |
2328 | 40.2k | if (!Args.hasArg(clang::driver::options::OPT_march_EQ) && |
2329 | 40.2k | !getToolChain().getTriple().isPS()39.7k ) |
2330 | 39.4k | TuneCPU = "generic"; |
2331 | | |
2332 | | // Override based on -mtune. |
2333 | 40.2k | if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) { |
2334 | 10 | StringRef Name = A->getValue(); |
2335 | | |
2336 | 10 | if (Name == "native") { |
2337 | 0 | Name = llvm::sys::getHostCPUName(); |
2338 | 0 | if (!Name.empty()) |
2339 | 0 | TuneCPU = std::string(Name); |
2340 | 0 | } else |
2341 | 10 | TuneCPU = std::string(Name); |
2342 | 10 | } |
2343 | | |
2344 | 40.2k | if (!TuneCPU.empty()) { |
2345 | 39.4k | CmdArgs.push_back("-tune-cpu"); |
2346 | 39.4k | CmdArgs.push_back(Args.MakeArgString(TuneCPU)); |
2347 | 39.4k | } |
2348 | 40.2k | } |
2349 | | |
2350 | | void Clang::AddHexagonTargetArgs(const ArgList &Args, |
2351 | 137 | ArgStringList &CmdArgs) const { |
2352 | 137 | CmdArgs.push_back("-mqdsp6-compat"); |
2353 | 137 | CmdArgs.push_back("-Wreturn-type"); |
2354 | | |
2355 | 137 | if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { |
2356 | 1 | CmdArgs.push_back("-mllvm"); |
2357 | 1 | CmdArgs.push_back( |
2358 | 1 | Args.MakeArgString("-hexagon-small-data-threshold=" + Twine(*G))); |
2359 | 1 | } |
2360 | | |
2361 | 137 | if (!Args.hasArg(options::OPT_fno_short_enums)) |
2362 | 137 | CmdArgs.push_back("-fshort-enums"); |
2363 | 137 | if (Args.getLastArg(options::OPT_mieee_rnd_near)) { |
2364 | 0 | CmdArgs.push_back("-mllvm"); |
2365 | 0 | CmdArgs.push_back("-enable-hexagon-ieee-rnd-near"); |
2366 | 0 | } |
2367 | 137 | CmdArgs.push_back("-mllvm"); |
2368 | 137 | CmdArgs.push_back("-machine-sink-split=0"); |
2369 | 137 | } |
2370 | | |
2371 | | void Clang::AddLanaiTargetArgs(const ArgList &Args, |
2372 | 3 | ArgStringList &CmdArgs) const { |
2373 | 3 | if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { |
2374 | 0 | StringRef CPUName = A->getValue(); |
2375 | |
|
2376 | 0 | CmdArgs.push_back("-target-cpu"); |
2377 | 0 | CmdArgs.push_back(Args.MakeArgString(CPUName)); |
2378 | 0 | } |
2379 | 3 | if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) { |
2380 | 0 | StringRef Value = A->getValue(); |
2381 | | // Only support mregparm=4 to support old usage. Report error for all other |
2382 | | // cases. |
2383 | 0 | int Mregparm; |
2384 | 0 | if (Value.getAsInteger(10, Mregparm)) { |
2385 | 0 | if (Mregparm != 4) { |
2386 | 0 | getToolChain().getDriver().Diag( |
2387 | 0 | diag::err_drv_unsupported_option_argument) |
2388 | 0 | << A->getSpelling() << Value; |
2389 | 0 | } |
2390 | 0 | } |
2391 | 0 | } |
2392 | 3 | } |
2393 | | |
2394 | | void Clang::AddWebAssemblyTargetArgs(const ArgList &Args, |
2395 | 129 | ArgStringList &CmdArgs) const { |
2396 | | // Default to "hidden" visibility. |
2397 | 129 | if (!Args.hasArg(options::OPT_fvisibility_EQ, |
2398 | 129 | options::OPT_fvisibility_ms_compat)) |
2399 | 127 | CmdArgs.push_back("-fvisibility=hidden"); |
2400 | 129 | } |
2401 | | |
2402 | 4 | void Clang::AddVETargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { |
2403 | | // Floating point operations and argument passing are hard. |
2404 | 4 | CmdArgs.push_back("-mfloat-abi"); |
2405 | 4 | CmdArgs.push_back("hard"); |
2406 | 4 | } |
2407 | | |
2408 | | void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, |
2409 | | StringRef Target, const InputInfo &Output, |
2410 | 12 | const InputInfo &Input, const ArgList &Args) const { |
2411 | | // If this is a dry run, do not create the compilation database file. |
2412 | 12 | if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) |
2413 | 0 | return; |
2414 | | |
2415 | 12 | using llvm::yaml::escape; |
2416 | 12 | const Driver &D = getToolChain().getDriver(); |
2417 | | |
2418 | 12 | if (!CompilationDatabase) { |
2419 | 8 | std::error_code EC; |
2420 | 8 | auto File = std::make_unique<llvm::raw_fd_ostream>( |
2421 | 8 | Filename, EC, |
2422 | 8 | llvm::sys::fs::OF_TextWithCRLF | llvm::sys::fs::OF_Append); |
2423 | 8 | if (EC) { |
2424 | 1 | D.Diag(clang::diag::err_drv_compilationdatabase) << Filename |
2425 | 1 | << EC.message(); |
2426 | 1 | return; |
2427 | 1 | } |
2428 | 7 | CompilationDatabase = std::move(File); |
2429 | 7 | } |
2430 | 11 | auto &CDB = *CompilationDatabase; |
2431 | 11 | auto CWD = D.getVFS().getCurrentWorkingDirectory(); |
2432 | 11 | if (!CWD) |
2433 | 0 | CWD = "."; |
2434 | 11 | CDB << "{ \"directory\": \"" << escape(*CWD) << "\""; |
2435 | 11 | CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\""; |
2436 | 11 | if (Output.isFilename()) |
2437 | 10 | CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\""; |
2438 | 11 | CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\""; |
2439 | 11 | SmallString<128> Buf; |
2440 | 11 | Buf = "-x"; |
2441 | 11 | Buf += types::getTypeName(Input.getType()); |
2442 | 11 | CDB << ", \"" << escape(Buf) << "\""; |
2443 | 11 | if (!D.SysRoot.empty() && !Args.hasArg(options::OPT__sysroot_EQ)2 ) { |
2444 | 0 | Buf = "--sysroot="; |
2445 | 0 | Buf += D.SysRoot; |
2446 | 0 | CDB << ", \"" << escape(Buf) << "\""; |
2447 | 0 | } |
2448 | 11 | CDB << ", \"" << escape(Input.getFilename()) << "\""; |
2449 | 11 | if (Output.isFilename()) |
2450 | 10 | CDB << ", \"-o\", \"" << escape(Output.getFilename()) << "\""; |
2451 | 104 | for (auto &A: Args) { |
2452 | 104 | auto &O = A->getOption(); |
2453 | | // Skip language selection, which is positional. |
2454 | 104 | if (O.getID() == options::OPT_x) |
2455 | 4 | continue; |
2456 | | // Skip writing dependency output and the compilation database itself. |
2457 | 100 | if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group58 ) |
2458 | 12 | continue; |
2459 | 88 | if (O.getID() == options::OPT_gen_cdb_fragment_path) |
2460 | 4 | continue; |
2461 | | // Skip inputs. |
2462 | 84 | if (O.getKind() == Option::InputClass) |
2463 | 13 | continue; |
2464 | | // Skip output. |
2465 | 71 | if (O.getID() == options::OPT_o) |
2466 | 8 | continue; |
2467 | | // All other arguments are quoted and appended. |
2468 | 63 | ArgStringList ASL; |
2469 | 63 | A->render(Args, ASL); |
2470 | 63 | for (auto &it: ASL) |
2471 | 76 | CDB << ", \"" << escape(it) << "\""; |
2472 | 63 | } |
2473 | 11 | Buf = "--target="; |
2474 | 11 | Buf += Target; |
2475 | 11 | CDB << ", \"" << escape(Buf) << "\"]},\n"; |
2476 | 11 | } |
2477 | | |
2478 | | void Clang::DumpCompilationDatabaseFragmentToDir( |
2479 | | StringRef Dir, Compilation &C, StringRef Target, const InputInfo &Output, |
2480 | 4 | const InputInfo &Input, const llvm::opt::ArgList &Args) const { |
2481 | | // If this is a dry run, do not create the compilation database file. |
2482 | 4 | if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) |
2483 | 1 | return; |
2484 | | |
2485 | 3 | if (CompilationDatabase) |
2486 | 0 | DumpCompilationDatabase(C, "", Target, Output, Input, Args); |
2487 | | |
2488 | 3 | SmallString<256> Path = Dir; |
2489 | 3 | const auto &Driver = C.getDriver(); |
2490 | 3 | Driver.getVFS().makeAbsolute(Path); |
2491 | 3 | auto Err = llvm::sys::fs::create_directory(Path, /*IgnoreExisting=*/true); |
2492 | 3 | if (Err) { |
2493 | 0 | Driver.Diag(diag::err_drv_compilationdatabase) << Dir << Err.message(); |
2494 | 0 | return; |
2495 | 0 | } |
2496 | | |
2497 | 3 | llvm::sys::path::append( |
2498 | 3 | Path, |
2499 | 3 | Twine(llvm::sys::path::filename(Input.getFilename())) + ".%%%%.json"); |
2500 | 3 | int FD; |
2501 | 3 | SmallString<256> TempPath; |
2502 | 3 | Err = llvm::sys::fs::createUniqueFile(Path, FD, TempPath, |
2503 | 3 | llvm::sys::fs::OF_Text); |
2504 | 3 | if (Err) { |
2505 | 0 | Driver.Diag(diag::err_drv_compilationdatabase) << Path << Err.message(); |
2506 | 0 | return; |
2507 | 0 | } |
2508 | 3 | CompilationDatabase = |
2509 | 3 | std::make_unique<llvm::raw_fd_ostream>(FD, /*shouldClose=*/true); |
2510 | 3 | DumpCompilationDatabase(C, "", Target, Output, Input, Args); |
2511 | 3 | } |
2512 | | |
2513 | 45 | static bool CheckARMImplicitITArg(StringRef Value) { |
2514 | 45 | return Value == "always" || Value == "never"24 || Value == "arm"15 || |
2515 | 45 | Value == "thumb"10 ; |
2516 | 45 | } |
2517 | | |
2518 | | static void AddARMImplicitITArgs(const ArgList &Args, ArgStringList &CmdArgs, |
2519 | 30 | StringRef Value) { |
2520 | 30 | CmdArgs.push_back("-mllvm"); |
2521 | 30 | CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value)); |
2522 | 30 | } |
2523 | | |
2524 | | static void CollectArgsForIntegratedAssembler(Compilation &C, |
2525 | | const ArgList &Args, |
2526 | | ArgStringList &CmdArgs, |
2527 | 11.7k | const Driver &D) { |
2528 | 11.7k | if (UseRelaxAll(C, Args)) |
2529 | 11.1k | CmdArgs.push_back("-mrelax-all"); |
2530 | | |
2531 | | // Only default to -mincremental-linker-compatible if we think we are |
2532 | | // targeting the MSVC linker. |
2533 | 11.7k | bool DefaultIncrementalLinkerCompatible = |
2534 | 11.7k | C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); |
2535 | 11.7k | if (Args.hasFlag(options::OPT_mincremental_linker_compatible, |
2536 | 11.7k | options::OPT_mno_incremental_linker_compatible, |
2537 | 11.7k | DefaultIncrementalLinkerCompatible)) |
2538 | 689 | CmdArgs.push_back("-mincremental-linker-compatible"); |
2539 | | |
2540 | 11.7k | Args.AddLastArg(CmdArgs, options::OPT_femit_dwarf_unwind_EQ); |
2541 | | |
2542 | 11.7k | Args.addOptInFlag(CmdArgs, options::OPT_femit_compact_unwind_non_canonical, |
2543 | 11.7k | options::OPT_fno_emit_compact_unwind_non_canonical); |
2544 | | |
2545 | | // If you add more args here, also add them to the block below that |
2546 | | // starts with "// If CollectArgsForIntegratedAssembler() isn't called below". |
2547 | | |
2548 | | // When passing -I arguments to the assembler we sometimes need to |
2549 | | // unconditionally take the next argument. For example, when parsing |
2550 | | // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the |
2551 | | // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo' |
2552 | | // arg after parsing the '-I' arg. |
2553 | 11.7k | bool TakeNextArg = false; |
2554 | | |
2555 | 11.7k | bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations(); |
2556 | 11.7k | bool UseNoExecStack = false; |
2557 | 11.7k | const char *MipsTargetFeature = nullptr; |
2558 | 11.7k | StringRef ImplicitIt; |
2559 | 11.7k | for (const Arg *A : |
2560 | 11.7k | Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler, |
2561 | 11.7k | options::OPT_mimplicit_it_EQ)) { |
2562 | 179 | A->claim(); |
2563 | | |
2564 | 179 | if (A->getOption().getID() == options::OPT_mimplicit_it_EQ) { |
2565 | 8 | switch (C.getDefaultToolChain().getArch()) { |
2566 | 8 | case llvm::Triple::arm: |
2567 | 8 | case llvm::Triple::armeb: |
2568 | 8 | case llvm::Triple::thumb: |
2569 | 8 | case llvm::Triple::thumbeb: |
2570 | | // Only store the value; the last value set takes effect. |
2571 | 8 | ImplicitIt = A->getValue(); |
2572 | 8 | if (!CheckARMImplicitITArg(ImplicitIt)) |
2573 | 1 | D.Diag(diag::err_drv_unsupported_option_argument) |
2574 | 1 | << A->getSpelling() << ImplicitIt; |
2575 | 8 | continue; |
2576 | 0 | default: |
2577 | 0 | break; |
2578 | 8 | } |
2579 | 8 | } |
2580 | | |
2581 | 194 | for (StringRef Value : A->getValues())171 { |
2582 | 194 | if (TakeNextArg) { |
2583 | 7 | CmdArgs.push_back(Value.data()); |
2584 | 7 | TakeNextArg = false; |
2585 | 7 | continue; |
2586 | 7 | } |
2587 | | |
2588 | 187 | if (C.getDefaultToolChain().getTriple().isOSBinFormatCOFF() && |
2589 | 187 | Value == "-mbig-obj"2 ) |
2590 | 2 | continue; // LLVM handles bigobj automatically |
2591 | | |
2592 | 185 | switch (C.getDefaultToolChain().getArch()) { |
2593 | 63 | default: |
2594 | 63 | break; |
2595 | 63 | case llvm::Triple::wasm32: |
2596 | 0 | case llvm::Triple::wasm64: |
2597 | 0 | if (Value == "--no-type-check") { |
2598 | 0 | CmdArgs.push_back("-mno-type-check"); |
2599 | 0 | continue; |
2600 | 0 | } |
2601 | 0 | break; |
2602 | 0 | case llvm::Triple::thumb: |
2603 | 0 | case llvm::Triple::thumbeb: |
2604 | 90 | case llvm::Triple::arm: |
2605 | 90 | case llvm::Triple::armeb: |
2606 | 90 | if (Value.startswith("-mimplicit-it=")) { |
2607 | | // Only store the value; the last value set takes effect. |
2608 | 37 | ImplicitIt = Value.split("=").second; |
2609 | 37 | if (CheckARMImplicitITArg(ImplicitIt)) |
2610 | 33 | continue; |
2611 | 37 | } |
2612 | 57 | if (Value == "-mthumb") |
2613 | | // -mthumb has already been processed in ComputeLLVMTriple() |
2614 | | // recognize but skip over here. |
2615 | 6 | continue; |
2616 | 51 | break; |
2617 | 51 | case llvm::Triple::mips: |
2618 | 32 | case llvm::Triple::mipsel: |
2619 | 32 | case llvm::Triple::mips64: |
2620 | 32 | case llvm::Triple::mips64el: |
2621 | 32 | if (Value == "--trap") { |
2622 | 3 | CmdArgs.push_back("-target-feature"); |
2623 | 3 | CmdArgs.push_back("+use-tcc-in-div"); |
2624 | 3 | continue; |
2625 | 3 | } |
2626 | 29 | if (Value == "--break") { |
2627 | 3 | CmdArgs.push_back("-target-feature"); |
2628 | 3 | CmdArgs.push_back("-use-tcc-in-div"); |
2629 | 3 | continue; |
2630 | 3 | } |
2631 | 26 | if (Value.startswith("-msoft-float")) { |
2632 | 3 | CmdArgs.push_back("-target-feature"); |
2633 | 3 | CmdArgs.push_back("+soft-float"); |
2634 | 3 | continue; |
2635 | 3 | } |
2636 | 23 | if (Value.startswith("-mhard-float")) { |
2637 | 3 | CmdArgs.push_back("-target-feature"); |
2638 | 3 | CmdArgs.push_back("-soft-float"); |
2639 | 3 | continue; |
2640 | 3 | } |
2641 | | |
2642 | 20 | MipsTargetFeature = llvm::StringSwitch<const char *>(Value) |
2643 | 20 | .Case("-mips1", "+mips1") |
2644 | 20 | .Case("-mips2", "+mips2") |
2645 | 20 | .Case("-mips3", "+mips3") |
2646 | 20 | .Case("-mips4", "+mips4") |
2647 | 20 | .Case("-mips5", "+mips5") |
2648 | 20 | .Case("-mips32", "+mips32") |
2649 | 20 | .Case("-mips32r2", "+mips32r2") |
2650 | 20 | .Case("-mips32r3", "+mips32r3") |
2651 | 20 | .Case("-mips32r5", "+mips32r5") |
2652 | 20 | .Case("-mips32r6", "+mips32r6") |
2653 | 20 | .Case("-mips64", "+mips64") |
2654 | 20 | .Case("-mips64r2", "+mips64r2") |
2655 | 20 | .Case("-mips64r3", "+mips64r3") |
2656 | 20 | .Case("-mips64r5", "+mips64r5") |
2657 | 20 | .Case("-mips64r6", "+mips64r6") |
2658 | 20 | .Default(nullptr); |
2659 | 20 | if (MipsTargetFeature) |
2660 | 20 | continue; |
2661 | 185 | } |
2662 | | |
2663 | 114 | if (Value == "-force_cpusubtype_ALL") { |
2664 | | // Do nothing, this is the default and we don't support anything else. |
2665 | 114 | } else if (Value == "-L") { |
2666 | 1 | CmdArgs.push_back("-msave-temp-labels"); |
2667 | 113 | } else if (Value == "--fatal-warnings") { |
2668 | 4 | CmdArgs.push_back("-massembler-fatal-warnings"); |
2669 | 109 | } else if (Value == "--no-warn" || Value == "-W"107 ) { |
2670 | 3 | CmdArgs.push_back("-massembler-no-warn"); |
2671 | 106 | } else if (Value == "--noexecstack") { |
2672 | 1 | UseNoExecStack = true; |
2673 | 105 | } else if (Value.startswith("-compress-debug-sections") || |
2674 | 105 | Value.startswith("--compress-debug-sections")103 || |
2675 | 105 | Value == "-nocompress-debug-sections"100 || |
2676 | 105 | Value == "--nocompress-debug-sections"100 ) { |
2677 | 6 | CmdArgs.push_back(Value.data()); |
2678 | 99 | } else if (Value == "-mrelax-relocations=yes" || |
2679 | 99 | Value == "--mrelax-relocations=yes"95 ) { |
2680 | 4 | UseRelaxRelocations = true; |
2681 | 95 | } else if (Value == "-mrelax-relocations=no" || |
2682 | 95 | Value == "--mrelax-relocations=no"91 ) { |
2683 | 6 | UseRelaxRelocations = false; |
2684 | 89 | } else if (Value.startswith("-I")) { |
2685 | 5 | CmdArgs.push_back(Value.data()); |
2686 | | // We need to consume the next argument if the current arg is a plain |
2687 | | // -I. The next arg will be the include directory. |
2688 | 5 | if (Value == "-I") |
2689 | 3 | TakeNextArg = true; |
2690 | 84 | } else if (Value.startswith("-gdwarf-")) { |
2691 | | // "-gdwarf-N" options are not cc1as options. |
2692 | 3 | unsigned DwarfVersion = DwarfVersionNum(Value); |
2693 | 3 | if (DwarfVersion == 0) { // Send it onward, and let cc1as complain. |
2694 | 1 | CmdArgs.push_back(Value.data()); |
2695 | 2 | } else { |
2696 | 2 | RenderDebugEnablingArgs(Args, CmdArgs, |
2697 | 2 | llvm::codegenoptions::DebugInfoConstructor, |
2698 | 2 | DwarfVersion, llvm::DebuggerKind::Default); |
2699 | 2 | } |
2700 | 81 | } else if (Value.startswith("-mcpu") || Value.startswith("-mfpu")64 || |
2701 | 81 | Value.startswith("-mhwdiv")61 || Value.startswith("-march")57 ) { |
2702 | | // Do nothing, we'll validate it later. |
2703 | 63 | } else if (18 Value == "-defsym"18 ) { |
2704 | 7 | if (A->getNumValues() != 2) { |
2705 | 2 | D.Diag(diag::err_drv_defsym_invalid_format) << Value; |
2706 | 2 | break; |
2707 | 2 | } |
2708 | 5 | const char *S = A->getValue(1); |
2709 | 5 | auto Pair = StringRef(S).split('='); |
2710 | 5 | auto Sym = Pair.first; |
2711 | 5 | auto SVal = Pair.second; |
2712 | | |
2713 | 5 | if (Sym.empty() || SVal.empty()4 ) { |
2714 | 2 | D.Diag(diag::err_drv_defsym_invalid_format) << S; |
2715 | 2 | break; |
2716 | 2 | } |
2717 | 3 | int64_t IVal; |
2718 | 3 | if (SVal.getAsInteger(0, IVal)) { |
2719 | 1 | D.Diag(diag::err_drv_defsym_invalid_symval) << SVal; |
2720 | 1 | break; |
2721 | 1 | } |
2722 | 2 | CmdArgs.push_back(Value.data()); |
2723 | 2 | TakeNextArg = true; |
2724 | 11 | } else if (Value == "-fdebug-compilation-dir") { |
2725 | 2 | CmdArgs.push_back("-fdebug-compilation-dir"); |
2726 | 2 | TakeNextArg = true; |
2727 | 9 | } else if (Value.consume_front("-fdebug-compilation-dir=")) { |
2728 | | // The flag is a -Wa / -Xassembler argument and Options doesn't |
2729 | | // parse the argument, so this isn't automatically aliased to |
2730 | | // -fdebug-compilation-dir (without '=') here. |
2731 | 2 | CmdArgs.push_back("-fdebug-compilation-dir"); |
2732 | 2 | CmdArgs.push_back(Value.data()); |
2733 | 7 | } else if (Value == "--version") { |
2734 | 1 | D.PrintVersion(C, llvm::outs()); |
2735 | 6 | } else { |
2736 | 6 | D.Diag(diag::err_drv_unsupported_option_argument) |
2737 | 6 | << A->getSpelling() << Value; |
2738 | 6 | } |
2739 | 114 | } |
2740 | 171 | } |
2741 | 11.7k | if (ImplicitIt.size()) |
2742 | 30 | AddARMImplicitITArgs(Args, CmdArgs, ImplicitIt); |
2743 | 11.7k | if (!UseRelaxRelocations) |
2744 | 6 | CmdArgs.push_back("-mrelax-relocations=no"); |
2745 | 11.7k | if (UseNoExecStack) |
2746 | 1 | CmdArgs.push_back("-mnoexecstack"); |
2747 | 11.7k | if (MipsTargetFeature != nullptr) { |
2748 | 17 | CmdArgs.push_back("-target-feature"); |
2749 | 17 | CmdArgs.push_back(MipsTargetFeature); |
2750 | 17 | } |
2751 | | |
2752 | | // forward -fembed-bitcode to assmebler |
2753 | 11.7k | if (C.getDriver().embedBitcodeEnabled() || |
2754 | 11.7k | C.getDriver().embedBitcodeMarkerOnly()11.7k ) |
2755 | 16 | Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ); |
2756 | | |
2757 | 11.7k | if (const char *AsSecureLogFile = getenv("AS_SECURE_LOG_FILE")) { |
2758 | 1 | CmdArgs.push_back("-as-secure-log-file"); |
2759 | 1 | CmdArgs.push_back(Args.MakeArgString(AsSecureLogFile)); |
2760 | 1 | } |
2761 | 11.7k | } |
2762 | | |
2763 | | static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, |
2764 | | bool OFastEnabled, const ArgList &Args, |
2765 | | ArgStringList &CmdArgs, |
2766 | 47.7k | const JobAction &JA) { |
2767 | | // Handle various floating point optimization flags, mapping them to the |
2768 | | // appropriate LLVM code generation flags. This is complicated by several |
2769 | | // "umbrella" flags, so we do this by stepping through the flags incrementally |
2770 | | // adjusting what we think is enabled/disabled, then at the end setting the |
2771 | | // LLVM flags based on the final state. |
2772 | 47.7k | bool HonorINFs = true; |
2773 | 47.7k | bool HonorNaNs = true; |
2774 | 47.7k | bool ApproxFunc = false; |
2775 | | // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes. |
2776 | 47.7k | bool MathErrno = TC.IsMathErrnoDefault(); |
2777 | 47.7k | bool AssociativeMath = false; |
2778 | 47.7k | bool ReciprocalMath = false; |
2779 | 47.7k | bool SignedZeros = true; |
2780 | 47.7k | bool TrappingMath = false; // Implemented via -ffp-exception-behavior |
2781 | 47.7k | bool TrappingMathPresent = false; // Is trapping-math in args, and not |
2782 | | // overriden by ffp-exception-behavior? |
2783 | 47.7k | bool RoundingFPMath = false; |
2784 | 47.7k | bool RoundingMathPresent = false; // Is rounding-math in args? |
2785 | | // -ffp-model values: strict, fast, precise |
2786 | 47.7k | StringRef FPModel = ""; |
2787 | | // -ffp-exception-behavior options: strict, maytrap, ignore |
2788 | 47.7k | StringRef FPExceptionBehavior = ""; |
2789 | | // -ffp-eval-method options: double, extended, source |
2790 | 47.7k | StringRef FPEvalMethod = ""; |
2791 | 47.7k | const llvm::DenormalMode DefaultDenormalFPMath = |
2792 | 47.7k | TC.getDefaultDenormalModeForType(Args, JA); |
2793 | 47.7k | const llvm::DenormalMode DefaultDenormalFP32Math = |
2794 | 47.7k | TC.getDefaultDenormalModeForType(Args, JA, &llvm::APFloat::IEEEsingle()); |
2795 | | |
2796 | 47.7k | llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath; |
2797 | 47.7k | llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math; |
2798 | | // CUDA and HIP don't rely on the frontend to pass an ffp-contract option. |
2799 | | // If one wasn't given by the user, don't pass it here. |
2800 | 47.7k | StringRef FPContract; |
2801 | 47.7k | StringRef LastSeenFfpContractOption; |
2802 | 47.7k | bool SeenUnsafeMathModeOption = false; |
2803 | 47.7k | if (!JA.isDeviceOffloading(Action::OFK_Cuda) && |
2804 | 47.7k | !JA.isOffloading(Action::OFK_HIP)47.7k ) |
2805 | 46.9k | FPContract = "on"; |
2806 | 47.7k | bool StrictFPModel = false; |
2807 | 47.7k | StringRef Float16ExcessPrecision = ""; |
2808 | 47.7k | StringRef BFloat16ExcessPrecision = ""; |
2809 | | |
2810 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { |
2811 | 0 | CmdArgs.push_back("-mlimit-float-precision"); |
2812 | 0 | CmdArgs.push_back(A->getValue()); |
2813 | 0 | } |
2814 | | |
2815 | 776k | for (const Arg *A : Args) { |
2816 | 776k | auto optID = A->getOption().getID(); |
2817 | 776k | bool PreciseFPModel = false; |
2818 | 776k | switch (optID) { |
2819 | 776k | default: |
2820 | 776k | break; |
2821 | 776k | case options::OPT_ffp_model_EQ: { |
2822 | | // If -ffp-model= is seen, reset to fno-fast-math |
2823 | 47 | HonorINFs = true; |
2824 | 47 | HonorNaNs = true; |
2825 | 47 | ApproxFunc = false; |
2826 | | // Turning *off* -ffast-math restores the toolchain default. |
2827 | 47 | MathErrno = TC.IsMathErrnoDefault(); |
2828 | 47 | AssociativeMath = false; |
2829 | 47 | ReciprocalMath = false; |
2830 | 47 | SignedZeros = true; |
2831 | | // -fno_fast_math restores default denormal and fpcontract handling |
2832 | 47 | FPContract = "on"; |
2833 | 47 | DenormalFPMath = llvm::DenormalMode::getIEEE(); |
2834 | | |
2835 | | // FIXME: The target may have picked a non-IEEE default mode here based on |
2836 | | // -cl-denorms-are-zero. Should the target consider -fp-model interaction? |
2837 | 47 | DenormalFP32Math = llvm::DenormalMode::getIEEE(); |
2838 | | |
2839 | 47 | StringRef Val = A->getValue(); |
2840 | 47 | if (OFastEnabled && !Val.equals("fast")3 ) { |
2841 | | // Only -ffp-model=fast is compatible with OFast, ignore. |
2842 | 3 | D.Diag(clang::diag::warn_drv_overriding_option) |
2843 | 3 | << Args.MakeArgString("-ffp-model=" + Val) << "-Ofast"; |
2844 | 3 | break; |
2845 | 3 | } |
2846 | 44 | StrictFPModel = false; |
2847 | 44 | PreciseFPModel = true; |
2848 | | // ffp-model= is a Driver option, it is entirely rewritten into more |
2849 | | // granular options before being passed into cc1. |
2850 | | // Use the gcc option in the switch below. |
2851 | 44 | if (!FPModel.empty() && !FPModel.equals(Val)2 ) |
2852 | 2 | D.Diag(clang::diag::warn_drv_overriding_option) |
2853 | 2 | << Args.MakeArgString("-ffp-model=" + FPModel) |
2854 | 2 | << Args.MakeArgString("-ffp-model=" + Val); |
2855 | 44 | if (Val.equals("fast")) { |
2856 | 9 | optID = options::OPT_ffast_math; |
2857 | 9 | FPModel = Val; |
2858 | 9 | FPContract = "fast"; |
2859 | 35 | } else if (Val.equals("precise")) { |
2860 | 8 | optID = options::OPT_ffp_contract; |
2861 | 8 | FPModel = Val; |
2862 | 8 | FPContract = "on"; |
2863 | 8 | PreciseFPModel = true; |
2864 | 27 | } else if (Val.equals("strict")) { |
2865 | 26 | StrictFPModel = true; |
2866 | 26 | optID = options::OPT_frounding_math; |
2867 | 26 | FPExceptionBehavior = "strict"; |
2868 | 26 | FPModel = Val; |
2869 | 26 | FPContract = "off"; |
2870 | 26 | TrappingMath = true; |
2871 | 26 | } else |
2872 | 1 | D.Diag(diag::err_drv_unsupported_option_argument) |
2873 | 1 | << A->getSpelling() << Val; |
2874 | 44 | break; |
2875 | 47 | } |
2876 | 776k | } |
2877 | | |
2878 | 776k | switch (optID) { |
2879 | | // If this isn't an FP option skip the claim below |
2880 | 776k | default: continue; |
2881 | | |
2882 | | // Options controlling individual features |
2883 | 776k | case options::OPT_fhonor_infinities: HonorINFs = true; break3 ; |
2884 | 7 | case options::OPT_fno_honor_infinities: HonorINFs = false; break; |
2885 | 3 | case options::OPT_fhonor_nans: HonorNaNs = true; break; |
2886 | 6 | case options::OPT_fno_honor_nans: HonorNaNs = false; break; |
2887 | 11 | case options::OPT_fapprox_func: ApproxFunc = true; break; |
2888 | 2 | case options::OPT_fno_approx_func: ApproxFunc = false; break; |
2889 | 8 | case options::OPT_fmath_errno: MathErrno = true; break; |
2890 | 15 | case options::OPT_fno_math_errno: MathErrno = false; break; |
2891 | 11 | case options::OPT_fassociative_math: AssociativeMath = true; break; |
2892 | 4 | case options::OPT_fno_associative_math: AssociativeMath = false; break; |
2893 | 14 | case options::OPT_freciprocal_math: ReciprocalMath = true; break; |
2894 | 3 | case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break; |
2895 | 3 | case options::OPT_fsigned_zeros: SignedZeros = true; break; |
2896 | 14 | case options::OPT_fno_signed_zeros: SignedZeros = false; break; |
2897 | 4 | case options::OPT_ftrapping_math: |
2898 | 4 | if (!TrappingMathPresent && !FPExceptionBehavior.empty()3 && |
2899 | 4 | !FPExceptionBehavior.equals("strict")0 ) |
2900 | | // Warn that previous value of option is overridden. |
2901 | 0 | D.Diag(clang::diag::warn_drv_overriding_option) |
2902 | 0 | << Args.MakeArgString("-ffp-exception-behavior=" + |
2903 | 0 | FPExceptionBehavior) |
2904 | 0 | << "-ftrapping-math"; |
2905 | 4 | TrappingMath = true; |
2906 | 4 | TrappingMathPresent = true; |
2907 | 4 | FPExceptionBehavior = "strict"; |
2908 | 4 | break; |
2909 | 11 | case options::OPT_fno_trapping_math: |
2910 | 11 | if (!TrappingMathPresent && !FPExceptionBehavior.empty() && |
2911 | 11 | !FPExceptionBehavior.equals("ignore")1 ) |
2912 | | // Warn that previous value of option is overridden. |
2913 | 1 | D.Diag(clang::diag::warn_drv_overriding_option) |
2914 | 1 | << Args.MakeArgString("-ffp-exception-behavior=" + |
2915 | 1 | FPExceptionBehavior) |
2916 | 1 | << "-fno-trapping-math"; |
2917 | 11 | TrappingMath = false; |
2918 | 11 | TrappingMathPresent = true; |
2919 | 11 | FPExceptionBehavior = "ignore"; |
2920 | 11 | break; |
2921 | | |
2922 | 29 | case options::OPT_frounding_math: |
2923 | 29 | RoundingFPMath = true; |
2924 | 29 | RoundingMathPresent = true; |
2925 | 29 | break; |
2926 | | |
2927 | 4 | case options::OPT_fno_rounding_math: |
2928 | 4 | RoundingFPMath = false; |
2929 | 4 | RoundingMathPresent = false; |
2930 | 4 | break; |
2931 | | |
2932 | 11 | case options::OPT_fdenormal_fp_math_EQ: |
2933 | 11 | DenormalFPMath = llvm::parseDenormalFPAttribute(A->getValue()); |
2934 | 11 | DenormalFP32Math = DenormalFPMath; |
2935 | 11 | if (!DenormalFPMath.isValid()) { |
2936 | 4 | D.Diag(diag::err_drv_invalid_value) |
2937 | 4 | << A->getAsString(Args) << A->getValue(); |
2938 | 4 | } |
2939 | 11 | break; |
2940 | | |
2941 | 0 | case options::OPT_fdenormal_fp_math_f32_EQ: |
2942 | 0 | DenormalFP32Math = llvm::parseDenormalFPAttribute(A->getValue()); |
2943 | 0 | if (!DenormalFP32Math.isValid()) { |
2944 | 0 | D.Diag(diag::err_drv_invalid_value) |
2945 | 0 | << A->getAsString(Args) << A->getValue(); |
2946 | 0 | } |
2947 | 0 | break; |
2948 | | |
2949 | | // Validate and pass through -ffp-contract option. |
2950 | 105 | case options::OPT_ffp_contract: { |
2951 | 105 | StringRef Val = A->getValue(); |
2952 | 105 | if (PreciseFPModel) { |
2953 | | // -ffp-model=precise enables ffp-contract=on. |
2954 | | // -ffp-model=precise sets PreciseFPModel to on and Val to |
2955 | | // "precise". FPContract is set. |
2956 | 8 | ; |
2957 | 97 | } else if (Val.equals("fast") || Val.equals("on")64 || Val.equals("off")32 || |
2958 | 97 | Val.equals("fast-honor-pragmas")1 ) { |
2959 | 97 | FPContract = Val; |
2960 | 97 | LastSeenFfpContractOption = Val; |
2961 | 97 | } else |
2962 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
2963 | 0 | << A->getSpelling() << Val; |
2964 | 105 | break; |
2965 | 0 | } |
2966 | | |
2967 | | // Validate and pass through -ffp-model option. |
2968 | 4 | case options::OPT_ffp_model_EQ: |
2969 | | // This should only occur in the error case |
2970 | | // since the optID has been replaced by a more granular |
2971 | | // floating point option. |
2972 | 4 | break; |
2973 | | |
2974 | | // Validate and pass through -ffp-exception-behavior option. |
2975 | 10 | case options::OPT_ffp_exception_behavior_EQ: { |
2976 | 10 | StringRef Val = A->getValue(); |
2977 | 10 | if (!TrappingMathPresent && !FPExceptionBehavior.empty()9 && |
2978 | 10 | !FPExceptionBehavior.equals(Val)0 ) |
2979 | | // Warn that previous value of option is overridden. |
2980 | 0 | D.Diag(clang::diag::warn_drv_overriding_option) |
2981 | 0 | << Args.MakeArgString("-ffp-exception-behavior=" + |
2982 | 0 | FPExceptionBehavior) |
2983 | 0 | << Args.MakeArgString("-ffp-exception-behavior=" + Val); |
2984 | 10 | TrappingMath = TrappingMathPresent = false; |
2985 | 10 | if (Val.equals("ignore") || Val.equals("maytrap")7 ) |
2986 | 5 | FPExceptionBehavior = Val; |
2987 | 5 | else if (Val.equals("strict")) { |
2988 | 4 | FPExceptionBehavior = Val; |
2989 | 4 | TrappingMath = TrappingMathPresent = true; |
2990 | 4 | } else |
2991 | 1 | D.Diag(diag::err_drv_unsupported_option_argument) |
2992 | 1 | << A->getSpelling() << Val; |
2993 | 10 | break; |
2994 | 0 | } |
2995 | | |
2996 | | // Validate and pass through -ffp-eval-method option. |
2997 | 5 | case options::OPT_ffp_eval_method_EQ: { |
2998 | 5 | StringRef Val = A->getValue(); |
2999 | 5 | if (Val.equals("double") || Val.equals("extended") || |
3000 | 5 | Val.equals("source")) |
3001 | 5 | FPEvalMethod = Val; |
3002 | 0 | else |
3003 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
3004 | 0 | << A->getSpelling() << Val; |
3005 | 5 | break; |
3006 | 0 | } |
3007 | | |
3008 | 26 | case options::OPT_fexcess_precision_EQ: { |
3009 | 26 | StringRef Val = A->getValue(); |
3010 | 26 | const llvm::Triple::ArchType Arch = TC.getArch(); |
3011 | 26 | if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_6418 ) { |
3012 | 18 | if (Val.equals("standard") || Val.equals("fast")14 ) |
3013 | 8 | Float16ExcessPrecision = Val; |
3014 | | // To make it GCC compatible, allow the value of "16" which |
3015 | | // means disable excess precision, the same meaning than clang's |
3016 | | // equivalent value "none". |
3017 | 10 | else if (Val.equals("16")) |
3018 | 4 | Float16ExcessPrecision = "none"; |
3019 | 6 | else |
3020 | 6 | D.Diag(diag::err_drv_unsupported_option_argument) |
3021 | 6 | << A->getSpelling() << Val; |
3022 | 18 | } else { |
3023 | 8 | if (!(Val.equals("standard") || Val.equals("fast")6 )) |
3024 | 4 | D.Diag(diag::err_drv_unsupported_option_argument) |
3025 | 4 | << A->getSpelling() << Val; |
3026 | 8 | } |
3027 | 26 | BFloat16ExcessPrecision = Float16ExcessPrecision; |
3028 | 26 | break; |
3029 | 0 | } |
3030 | 10 | case options::OPT_ffinite_math_only: |
3031 | 10 | HonorINFs = false; |
3032 | 10 | HonorNaNs = false; |
3033 | 10 | break; |
3034 | 6 | case options::OPT_fno_finite_math_only: |
3035 | 6 | HonorINFs = true; |
3036 | 6 | HonorNaNs = true; |
3037 | 6 | break; |
3038 | | |
3039 | 37 | case options::OPT_funsafe_math_optimizations: |
3040 | 37 | AssociativeMath = true; |
3041 | 37 | ReciprocalMath = true; |
3042 | 37 | SignedZeros = false; |
3043 | 37 | ApproxFunc = true; |
3044 | 37 | TrappingMath = false; |
3045 | 37 | FPExceptionBehavior = ""; |
3046 | 37 | FPContract = "fast"; |
3047 | 37 | SeenUnsafeMathModeOption = true; |
3048 | 37 | break; |
3049 | 28 | case options::OPT_fno_unsafe_math_optimizations: |
3050 | 28 | AssociativeMath = false; |
3051 | 28 | ReciprocalMath = false; |
3052 | 28 | SignedZeros = true; |
3053 | 28 | ApproxFunc = false; |
3054 | 28 | TrappingMath = true; |
3055 | 28 | FPExceptionBehavior = "strict"; |
3056 | | |
3057 | | // The target may have opted to flush by default, so force IEEE. |
3058 | 28 | DenormalFPMath = llvm::DenormalMode::getIEEE(); |
3059 | 28 | DenormalFP32Math = llvm::DenormalMode::getIEEE(); |
3060 | 28 | if (!JA.isDeviceOffloading(Action::OFK_Cuda) && |
3061 | 28 | !JA.isOffloading(Action::OFK_HIP)) { |
3062 | 28 | if (LastSeenFfpContractOption != "") { |
3063 | 13 | FPContract = LastSeenFfpContractOption; |
3064 | 15 | } else if (SeenUnsafeMathModeOption) |
3065 | 5 | FPContract = "on"; |
3066 | 28 | } |
3067 | 28 | break; |
3068 | | |
3069 | 27 | case options::OPT_Ofast: |
3070 | | // If -Ofast is the optimization level, then -ffast-math should be enabled |
3071 | 27 | if (!OFastEnabled) |
3072 | 2 | continue; |
3073 | 27 | [[fallthrough]];25 |
3074 | 131 | case options::OPT_ffast_math: |
3075 | 131 | HonorINFs = false; |
3076 | 131 | HonorNaNs = false; |
3077 | 131 | MathErrno = false; |
3078 | 131 | AssociativeMath = true; |
3079 | 131 | ReciprocalMath = true; |
3080 | 131 | ApproxFunc = true; |
3081 | 131 | SignedZeros = false; |
3082 | 131 | TrappingMath = false; |
3083 | 131 | RoundingFPMath = false; |
3084 | 131 | FPExceptionBehavior = ""; |
3085 | | // If fast-math is set then set the fp-contract mode to fast. |
3086 | 131 | FPContract = "fast"; |
3087 | 131 | SeenUnsafeMathModeOption = true; |
3088 | 131 | break; |
3089 | 63 | case options::OPT_fno_fast_math: |
3090 | 63 | HonorINFs = true; |
3091 | 63 | HonorNaNs = true; |
3092 | | // Turning on -ffast-math (with either flag) removes the need for |
3093 | | // MathErrno. However, turning *off* -ffast-math merely restores the |
3094 | | // toolchain default (which may be false). |
3095 | 63 | MathErrno = TC.IsMathErrnoDefault(); |
3096 | 63 | AssociativeMath = false; |
3097 | 63 | ReciprocalMath = false; |
3098 | 63 | ApproxFunc = false; |
3099 | 63 | SignedZeros = true; |
3100 | | // -fno_fast_math restores default denormal and fpcontract handling |
3101 | 63 | DenormalFPMath = DefaultDenormalFPMath; |
3102 | 63 | DenormalFP32Math = llvm::DenormalMode::getIEEE(); |
3103 | 63 | if (!JA.isDeviceOffloading(Action::OFK_Cuda) && |
3104 | 63 | !JA.isOffloading(Action::OFK_HIP)) { |
3105 | 60 | if (LastSeenFfpContractOption != "") { |
3106 | 16 | FPContract = LastSeenFfpContractOption; |
3107 | 44 | } else if (SeenUnsafeMathModeOption) |
3108 | 7 | FPContract = "on"; |
3109 | 60 | } |
3110 | 63 | break; |
3111 | 776k | } |
3112 | 588 | if (StrictFPModel) { |
3113 | | // If -ffp-model=strict has been specified on command line but |
3114 | | // subsequent options conflict then emit warning diagnostic. |
3115 | 44 | if (HonorINFs && HonorNaNs39 && !AssociativeMath38 && !ReciprocalMath36 && |
3116 | 44 | SignedZeros35 && TrappingMath34 && RoundingFPMath33 && !ApproxFunc32 && |
3117 | 44 | DenormalFPMath == llvm::DenormalMode::getIEEE()31 && |
3118 | 44 | DenormalFP32Math == llvm::DenormalMode::getIEEE()30 && |
3119 | 44 | FPContract.equals("off")30 ) |
3120 | | // OK: Current Arg doesn't conflict with -ffp-model=strict |
3121 | 27 | ; |
3122 | 17 | else { |
3123 | 17 | StrictFPModel = false; |
3124 | 17 | FPModel = ""; |
3125 | 17 | auto RHS = (A->getNumValues() == 0) |
3126 | 17 | ? A->getSpelling()13 |
3127 | 17 | : Args.MakeArgString(A->getSpelling() + A->getValue())4 ; |
3128 | 17 | if (RHS != "-ffp-model=strict") |
3129 | 17 | D.Diag(clang::diag::warn_drv_overriding_option) |
3130 | 17 | << "-ffp-model=strict" << RHS; |
3131 | 17 | } |
3132 | 44 | } |
3133 | | |
3134 | | // If we handled this option claim it |
3135 | 588 | A->claim(); |
3136 | 588 | } |
3137 | | |
3138 | 47.7k | if (!HonorINFs) |
3139 | 112 | CmdArgs.push_back("-menable-no-infs"); |
3140 | | |
3141 | 47.7k | if (!HonorNaNs) |
3142 | 111 | CmdArgs.push_back("-menable-no-nans"); |
3143 | | |
3144 | 47.7k | if (ApproxFunc) |
3145 | 139 | CmdArgs.push_back("-fapprox-func"); |
3146 | | |
3147 | 47.7k | if (MathErrno) |
3148 | 28.0k | CmdArgs.push_back("-fmath-errno"); |
3149 | | |
3150 | 47.7k | if (AssociativeMath && ReciprocalMath136 && !SignedZeros132 && ApproxFunc129 && |
3151 | 47.7k | !TrappingMath127 ) |
3152 | 124 | CmdArgs.push_back("-funsafe-math-optimizations"); |
3153 | | |
3154 | 47.7k | if (!SignedZeros) |
3155 | 140 | CmdArgs.push_back("-fno-signed-zeros"); |
3156 | | |
3157 | 47.7k | if (AssociativeMath && !SignedZeros136 && !TrappingMath132 ) |
3158 | 128 | CmdArgs.push_back("-mreassociate"); |
3159 | | |
3160 | 47.7k | if (ReciprocalMath) |
3161 | 139 | CmdArgs.push_back("-freciprocal-math"); |
3162 | | |
3163 | 47.7k | if (TrappingMath) { |
3164 | | // FP Exception Behavior is also set to strict |
3165 | 50 | assert(FPExceptionBehavior.equals("strict")); |
3166 | 50 | } |
3167 | | |
3168 | | // The default is IEEE. |
3169 | 47.7k | if (DenormalFPMath != llvm::DenormalMode::getIEEE()) { |
3170 | 300 | llvm::SmallString<64> DenormFlag; |
3171 | 300 | llvm::raw_svector_ostream ArgStr(DenormFlag); |
3172 | 300 | ArgStr << "-fdenormal-fp-math=" << DenormalFPMath; |
3173 | 300 | CmdArgs.push_back(Args.MakeArgString(ArgStr.str())); |
3174 | 300 | } |
3175 | | |
3176 | | // Add f32 specific denormal mode flag if it's different. |
3177 | 47.7k | if (DenormalFP32Math != DenormalFPMath) { |
3178 | 123 | llvm::SmallString<64> DenormFlag; |
3179 | 123 | llvm::raw_svector_ostream ArgStr(DenormFlag); |
3180 | 123 | ArgStr << "-fdenormal-fp-math-f32=" << DenormalFP32Math; |
3181 | 123 | CmdArgs.push_back(Args.MakeArgString(ArgStr.str())); |
3182 | 123 | } |
3183 | | |
3184 | 47.7k | if (!FPContract.empty()) |
3185 | 46.9k | CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract)); |
3186 | | |
3187 | 47.7k | if (!RoundingFPMath) |
3188 | 47.7k | CmdArgs.push_back(Args.MakeArgString("-fno-rounding-math")); |
3189 | | |
3190 | 47.7k | if (RoundingFPMath && RoundingMathPresent23 ) |
3191 | 23 | CmdArgs.push_back(Args.MakeArgString("-frounding-math")); |
3192 | | |
3193 | 47.7k | if (!FPExceptionBehavior.empty()) |
3194 | 65 | CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" + |
3195 | 65 | FPExceptionBehavior)); |
3196 | | |
3197 | 47.7k | if (!FPEvalMethod.empty()) |
3198 | 5 | CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + FPEvalMethod)); |
3199 | | |
3200 | 47.7k | if (!Float16ExcessPrecision.empty()) |
3201 | 12 | CmdArgs.push_back(Args.MakeArgString("-ffloat16-excess-precision=" + |
3202 | 12 | Float16ExcessPrecision)); |
3203 | 47.7k | if (!BFloat16ExcessPrecision.empty()) |
3204 | 12 | CmdArgs.push_back(Args.MakeArgString("-fbfloat16-excess-precision=" + |
3205 | 12 | BFloat16ExcessPrecision)); |
3206 | | |
3207 | 47.7k | ParseMRecip(D, Args, CmdArgs); |
3208 | | |
3209 | | // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the |
3210 | | // individual features enabled by -ffast-math instead of the option itself as |
3211 | | // that's consistent with gcc's behaviour. |
3212 | 47.7k | if (!HonorINFs && !HonorNaNs112 && !MathErrno106 && AssociativeMath103 && ApproxFunc94 && |
3213 | 47.7k | ReciprocalMath93 && !SignedZeros92 && !TrappingMath91 && !RoundingFPMath89 ) { |
3214 | 89 | CmdArgs.push_back("-ffast-math"); |
3215 | 89 | if (FPModel.equals("fast")) { |
3216 | 7 | if (FPContract.equals("fast")) |
3217 | | // All set, do nothing. |
3218 | 5 | ; |
3219 | 2 | else if (FPContract.empty()) |
3220 | | // Enable -ffp-contract=fast |
3221 | 0 | CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast")); |
3222 | 2 | else |
3223 | 2 | D.Diag(clang::diag::warn_drv_overriding_option) |
3224 | 2 | << "-ffp-model=fast" |
3225 | 2 | << Args.MakeArgString("-ffp-contract=" + FPContract); |
3226 | 7 | } |
3227 | 89 | } |
3228 | | |
3229 | | // Handle __FINITE_MATH_ONLY__ similarly. |
3230 | 47.7k | if (!HonorINFs && !HonorNaNs112 ) |
3231 | 106 | CmdArgs.push_back("-ffinite-math-only"); |
3232 | | |
3233 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) { |
3234 | 1 | CmdArgs.push_back("-mfpmath"); |
3235 | 1 | CmdArgs.push_back(A->getValue()); |
3236 | 1 | } |
3237 | | |
3238 | | // Disable a codegen optimization for floating-point casts. |
3239 | 47.7k | if (Args.hasFlag(options::OPT_fno_strict_float_cast_overflow, |
3240 | 47.7k | options::OPT_fstrict_float_cast_overflow, false)) |
3241 | 1 | CmdArgs.push_back("-fno-strict-float-cast-overflow"); |
3242 | 47.7k | } |
3243 | | |
3244 | | static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, |
3245 | | const llvm::Triple &Triple, |
3246 | 56 | const InputInfo &Input) { |
3247 | | // Add default argument set. |
3248 | 56 | if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { |
3249 | 56 | CmdArgs.push_back("-analyzer-checker=core"); |
3250 | 56 | CmdArgs.push_back("-analyzer-checker=apiModeling"); |
3251 | | |
3252 | 56 | if (!Triple.isWindowsMSVCEnvironment()) { |
3253 | 53 | CmdArgs.push_back("-analyzer-checker=unix"); |
3254 | 53 | } else { |
3255 | | // Enable "unix" checkers that also work on Windows. |
3256 | 3 | CmdArgs.push_back("-analyzer-checker=unix.API"); |
3257 | 3 | CmdArgs.push_back("-analyzer-checker=unix.Malloc"); |
3258 | 3 | CmdArgs.push_back("-analyzer-checker=unix.MallocSizeof"); |
3259 | 3 | CmdArgs.push_back("-analyzer-checker=unix.MismatchedDeallocator"); |
3260 | 3 | CmdArgs.push_back("-analyzer-checker=unix.cstring.BadSizeArg"); |
3261 | 3 | CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg"); |
3262 | 3 | } |
3263 | | |
3264 | | // Disable some unix checkers for PS4/PS5. |
3265 | 56 | if (Triple.isPS()) { |
3266 | 6 | CmdArgs.push_back("-analyzer-disable-checker=unix.API"); |
3267 | 6 | CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork"); |
3268 | 6 | } |
3269 | | |
3270 | 56 | if (Triple.isOSDarwin()) { |
3271 | 44 | CmdArgs.push_back("-analyzer-checker=osx"); |
3272 | 44 | CmdArgs.push_back( |
3273 | 44 | "-analyzer-checker=security.insecureAPI.decodeValueOfObjCType"); |
3274 | 44 | } |
3275 | 12 | else if (Triple.isOSFuchsia()) |
3276 | 0 | CmdArgs.push_back("-analyzer-checker=fuchsia"); |
3277 | | |
3278 | 56 | CmdArgs.push_back("-analyzer-checker=deadcode"); |
3279 | | |
3280 | 56 | if (types::isCXX(Input.getType())) |
3281 | 21 | CmdArgs.push_back("-analyzer-checker=cplusplus"); |
3282 | | |
3283 | 56 | if (!Triple.isPS()) { |
3284 | 50 | CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn"); |
3285 | 50 | CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); |
3286 | 50 | CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); |
3287 | 50 | CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); |
3288 | 50 | CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp"); |
3289 | 50 | CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork"); |
3290 | 50 | } |
3291 | | |
3292 | | // Default nullability checks. |
3293 | 56 | CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull"); |
3294 | 56 | CmdArgs.push_back("-analyzer-checker=nullability.NullReturnedFromNonnull"); |
3295 | 56 | } |
3296 | | |
3297 | | // Set the output format. The default is plist, for (lame) historical reasons. |
3298 | 56 | CmdArgs.push_back("-analyzer-output"); |
3299 | 56 | if (Arg *A = Args.getLastArg(options::OPT__analyzer_output)) |
3300 | 0 | CmdArgs.push_back(A->getValue()); |
3301 | 56 | else |
3302 | 56 | CmdArgs.push_back("plist"); |
3303 | | |
3304 | | // Disable the presentation of standard compiler warnings when using |
3305 | | // --analyze. We only want to show static analyzer diagnostics or frontend |
3306 | | // errors. |
3307 | 56 | CmdArgs.push_back("-w"); |
3308 | | |
3309 | | // Add -Xanalyzer arguments when running as analyzer. |
3310 | 56 | Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer); |
3311 | 56 | } |
3312 | | |
3313 | 3 | static bool isValidSymbolName(StringRef S) { |
3314 | 3 | if (S.empty()) |
3315 | 1 | return false; |
3316 | | |
3317 | 2 | if (std::isdigit(S[0])) |
3318 | 1 | return false; |
3319 | | |
3320 | 3 | return llvm::all_of(S, [](char C) 1 { return std::isalnum(C) || C == '_'0 ; }); |
3321 | 2 | } |
3322 | | |
3323 | | static void RenderSSPOptions(const Driver &D, const ToolChain &TC, |
3324 | | const ArgList &Args, ArgStringList &CmdArgs, |
3325 | 47.7k | bool KernelOrKext) { |
3326 | 47.7k | const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple(); |
3327 | | |
3328 | | // NVPTX doesn't support stack protectors; from the compiler's perspective, it |
3329 | | // doesn't even have a stack! |
3330 | 47.7k | if (EffectiveTriple.isNVPTX()) |
3331 | 63 | return; |
3332 | | |
3333 | | // -stack-protector=0 is default. |
3334 | 47.6k | LangOptions::StackProtectorMode StackProtectorLevel = LangOptions::SSPOff; |
3335 | 47.6k | LangOptions::StackProtectorMode DefaultStackProtectorLevel = |
3336 | 47.6k | TC.GetDefaultStackProtectorLevel(KernelOrKext); |
3337 | | |
3338 | 47.6k | if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, |
3339 | 47.6k | options::OPT_fstack_protector_all, |
3340 | 47.6k | options::OPT_fstack_protector_strong, |
3341 | 47.6k | options::OPT_fstack_protector)) { |
3342 | 15 | if (A->getOption().matches(options::OPT_fstack_protector)) |
3343 | 9 | StackProtectorLevel = |
3344 | 9 | std::max<>(LangOptions::SSPOn, DefaultStackProtectorLevel); |
3345 | 6 | else if (A->getOption().matches(options::OPT_fstack_protector_strong)) |
3346 | 2 | StackProtectorLevel = LangOptions::SSPStrong; |
3347 | 4 | else if (A->getOption().matches(options::OPT_fstack_protector_all)) |
3348 | 3 | StackProtectorLevel = LangOptions::SSPReq; |
3349 | | |
3350 | 15 | if (EffectiveTriple.isBPF() && StackProtectorLevel != LangOptions::SSPOff0 ) { |
3351 | 0 | D.Diag(diag::warn_drv_unsupported_option_for_target) |
3352 | 0 | << A->getSpelling() << EffectiveTriple.getTriple(); |
3353 | 0 | StackProtectorLevel = DefaultStackProtectorLevel; |
3354 | 0 | } |
3355 | 47.6k | } else { |
3356 | 47.6k | StackProtectorLevel = DefaultStackProtectorLevel; |
3357 | 47.6k | } |
3358 | | |
3359 | 47.6k | if (StackProtectorLevel) { |
3360 | 18.2k | CmdArgs.push_back("-stack-protector"); |
3361 | 18.2k | CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel))); |
3362 | 18.2k | } |
3363 | | |
3364 | | // --param ssp-buffer-size= |
3365 | 47.6k | for (const Arg *A : Args.filtered(options::OPT__param)) { |
3366 | 5 | StringRef Str(A->getValue()); |
3367 | 5 | if (Str.startswith("ssp-buffer-size=")) { |
3368 | 2 | if (StackProtectorLevel) { |
3369 | 2 | CmdArgs.push_back("-stack-protector-buffer-size"); |
3370 | | // FIXME: Verify the argument is a valid integer. |
3371 | 2 | CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16))); |
3372 | 2 | } |
3373 | 2 | A->claim(); |
3374 | 2 | } |
3375 | 5 | } |
3376 | | |
3377 | 47.6k | const std::string &TripleStr = EffectiveTriple.getTriple(); |
3378 | 47.6k | if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) { |
3379 | 11 | StringRef Value = A->getValue(); |
3380 | 11 | if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64()8 && |
3381 | 11 | !EffectiveTriple.isARM()5 && !EffectiveTriple.isThumb()2 ) |
3382 | 1 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
3383 | 1 | << A->getAsString(Args) << TripleStr; |
3384 | 11 | if ((EffectiveTriple.isX86() || EffectiveTriple.isARM()8 || |
3385 | 11 | EffectiveTriple.isThumb()5 ) && |
3386 | 11 | Value != "tls"7 && Value != "global"3 ) { |
3387 | 2 | D.Diag(diag::err_drv_invalid_value_with_suggestion) |
3388 | 2 | << A->getOption().getName() << Value << "tls global"; |
3389 | 2 | return; |
3390 | 2 | } |
3391 | 9 | if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()7 ) && |
3392 | 9 | Value == "tls"3 ) { |
3393 | 3 | if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) { |
3394 | 1 | D.Diag(diag::err_drv_ssp_missing_offset_argument) |
3395 | 1 | << A->getAsString(Args); |
3396 | 1 | return; |
3397 | 1 | } |
3398 | | // Check whether the target subarch supports the hardware TLS register |
3399 | 2 | if (!arm::isHardTPSupported(EffectiveTriple)) { |
3400 | 1 | D.Diag(diag::err_target_unsupported_tp_hard) |
3401 | 1 | << EffectiveTriple.getArchName(); |
3402 | 1 | return; |
3403 | 1 | } |
3404 | | // Check whether the user asked for something other than -mtp=cp15 |
3405 | 1 | if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) { |
3406 | 1 | StringRef Value = A->getValue(); |
3407 | 1 | if (Value != "cp15") { |
3408 | 1 | D.Diag(diag::err_drv_argument_not_allowed_with) |
3409 | 1 | << A->getAsString(Args) << "-mstack-protector-guard=tls"; |
3410 | 1 | return; |
3411 | 1 | } |
3412 | 1 | } |
3413 | 0 | CmdArgs.push_back("-target-feature"); |
3414 | 0 | CmdArgs.push_back("+read-tp-tpidruro"); |
3415 | 0 | } |
3416 | 6 | if (EffectiveTriple.isAArch64() && Value != "sysreg"3 && Value != "global"1 ) { |
3417 | 1 | D.Diag(diag::err_drv_invalid_value_with_suggestion) |
3418 | 1 | << A->getOption().getName() << Value << "sysreg global"; |
3419 | 1 | return; |
3420 | 1 | } |
3421 | 5 | A->render(Args, CmdArgs); |
3422 | 5 | } |
3423 | | |
3424 | 47.6k | if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) { |
3425 | 5 | StringRef Value = A->getValue(); |
3426 | 5 | if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64()4 && |
3427 | 5 | !EffectiveTriple.isARM()2 && !EffectiveTriple.isThumb()1 ) |
3428 | 1 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
3429 | 1 | << A->getAsString(Args) << TripleStr; |
3430 | 5 | int Offset; |
3431 | 5 | if (Value.getAsInteger(10, Offset)) { |
3432 | 0 | D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value; |
3433 | 0 | return; |
3434 | 0 | } |
3435 | 5 | if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()4 ) && |
3436 | 5 | (1 Offset < 01 || Offset > 0xfffff1 )) { |
3437 | 1 | D.Diag(diag::err_drv_invalid_int_value) |
3438 | 1 | << A->getOption().getName() << Value; |
3439 | 1 | return; |
3440 | 1 | } |
3441 | 4 | A->render(Args, CmdArgs); |
3442 | 4 | } |
3443 | | |
3444 | 47.6k | if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) { |
3445 | 7 | StringRef Value = A->getValue(); |
3446 | 7 | if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64()3 ) |
3447 | 1 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
3448 | 1 | << A->getAsString(Args) << TripleStr; |
3449 | 7 | if (EffectiveTriple.isX86() && (4 Value != "fs"4 && Value != "gs"3 )) { |
3450 | 2 | D.Diag(diag::err_drv_invalid_value_with_suggestion) |
3451 | 2 | << A->getOption().getName() << Value << "fs gs"; |
3452 | 2 | return; |
3453 | 2 | } |
3454 | 5 | if (EffectiveTriple.isAArch64() && Value != "sp_el0"2 ) { |
3455 | 1 | D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value; |
3456 | 1 | return; |
3457 | 1 | } |
3458 | 4 | A->render(Args, CmdArgs); |
3459 | 4 | } |
3460 | | |
3461 | 47.6k | if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_symbol_EQ)) { |
3462 | 3 | StringRef Value = A->getValue(); |
3463 | 3 | if (!isValidSymbolName(Value)) { |
3464 | 2 | D.Diag(diag::err_drv_argument_only_allowed_with) |
3465 | 2 | << A->getOption().getName() << "legal symbol name"; |
3466 | 2 | return; |
3467 | 2 | } |
3468 | 1 | A->render(Args, CmdArgs); |
3469 | 1 | } |
3470 | 47.6k | } |
3471 | | |
3472 | | static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args, |
3473 | 47.7k | ArgStringList &CmdArgs) { |
3474 | 47.7k | const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple(); |
3475 | | |
3476 | 47.7k | if (!EffectiveTriple.isOSFreeBSD() && !EffectiveTriple.isOSLinux()47.6k ) |
3477 | 42.7k | return; |
3478 | | |
3479 | 4.98k | if (!EffectiveTriple.isX86() && !EffectiveTriple.isSystemZ()2.11k && |
3480 | 4.98k | !EffectiveTriple.isPPC64()2.07k ) |
3481 | 1.85k | return; |
3482 | | |
3483 | 3.13k | Args.addOptInFlag(CmdArgs, options::OPT_fstack_clash_protection, |
3484 | 3.13k | options::OPT_fno_stack_clash_protection); |
3485 | 3.13k | } |
3486 | | |
3487 | | static void RenderTrivialAutoVarInitOptions(const Driver &D, |
3488 | | const ToolChain &TC, |
3489 | | const ArgList &Args, |
3490 | 47.7k | ArgStringList &CmdArgs) { |
3491 | 47.7k | auto DefaultTrivialAutoVarInit = TC.GetDefaultTrivialAutoVarInit(); |
3492 | 47.7k | StringRef TrivialAutoVarInit = ""; |
3493 | | |
3494 | 776k | for (const Arg *A : Args) { |
3495 | 776k | switch (A->getOption().getID()) { |
3496 | 776k | default: |
3497 | 776k | continue; |
3498 | 776k | case options::OPT_ftrivial_auto_var_init: { |
3499 | 7 | A->claim(); |
3500 | 7 | StringRef Val = A->getValue(); |
3501 | 7 | if (Val == "uninitialized" || Val == "zero"6 || Val == "pattern"3 ) |
3502 | 7 | TrivialAutoVarInit = Val; |
3503 | 0 | else |
3504 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
3505 | 0 | << A->getSpelling() << Val; |
3506 | 7 | break; |
3507 | 0 | } |
3508 | 776k | } |
3509 | 776k | } |
3510 | | |
3511 | 47.7k | if (TrivialAutoVarInit.empty()) |
3512 | 47.7k | switch (DefaultTrivialAutoVarInit) { |
3513 | 47.7k | case LangOptions::TrivialAutoVarInitKind::Uninitialized: |
3514 | 47.7k | break; |
3515 | 0 | case LangOptions::TrivialAutoVarInitKind::Pattern: |
3516 | 0 | TrivialAutoVarInit = "pattern"; |
3517 | 0 | break; |
3518 | 0 | case LangOptions::TrivialAutoVarInitKind::Zero: |
3519 | 0 | TrivialAutoVarInit = "zero"; |
3520 | 0 | break; |
3521 | 47.7k | } |
3522 | | |
3523 | 47.7k | if (!TrivialAutoVarInit.empty()) { |
3524 | 7 | CmdArgs.push_back( |
3525 | 7 | Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit)); |
3526 | 7 | } |
3527 | | |
3528 | 47.7k | if (Arg *A = |
3529 | 47.7k | Args.getLastArg(options::OPT_ftrivial_auto_var_init_stop_after)) { |
3530 | 5 | if (!Args.hasArg(options::OPT_ftrivial_auto_var_init) || |
3531 | 5 | StringRef( |
3532 | 4 | Args.getLastArg(options::OPT_ftrivial_auto_var_init)->getValue()) == |
3533 | 4 | "uninitialized") |
3534 | 1 | D.Diag(diag::err_drv_trivial_auto_var_init_stop_after_missing_dependency); |
3535 | 5 | A->claim(); |
3536 | 5 | StringRef Val = A->getValue(); |
3537 | 5 | if (std::stoi(Val.str()) <= 0) |
3538 | 3 | D.Diag(diag::err_drv_trivial_auto_var_init_stop_after_invalid_value); |
3539 | 5 | CmdArgs.push_back( |
3540 | 5 | Args.MakeArgString("-ftrivial-auto-var-init-stop-after=" + Val)); |
3541 | 5 | } |
3542 | 47.7k | } |
3543 | | |
3544 | | static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs, |
3545 | 47.7k | types::ID InputType) { |
3546 | | // cl-denorms-are-zero is not forwarded. It is translated into a generic flag |
3547 | | // for denormal flushing handling based on the target. |
3548 | 47.7k | const unsigned ForwardedArguments[] = { |
3549 | 47.7k | options::OPT_cl_opt_disable, |
3550 | 47.7k | options::OPT_cl_strict_aliasing, |
3551 | 47.7k | options::OPT_cl_single_precision_constant, |
3552 | 47.7k | options::OPT_cl_finite_math_only, |
3553 | 47.7k | options::OPT_cl_kernel_arg_info, |
3554 | 47.7k | options::OPT_cl_unsafe_math_optimizations, |
3555 | 47.7k | options::OPT_cl_fast_relaxed_math, |
3556 | 47.7k | options::OPT_cl_mad_enable, |
3557 | 47.7k | options::OPT_cl_no_signed_zeros, |
3558 | 47.7k | options::OPT_cl_fp32_correctly_rounded_divide_sqrt, |
3559 | 47.7k | options::OPT_cl_uniform_work_group_size |
3560 | 47.7k | }; |
3561 | | |
3562 | 47.7k | if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) { |
3563 | 17 | std::string CLStdStr = std::string("-cl-std=") + A->getValue(); |
3564 | 17 | CmdArgs.push_back(Args.MakeArgString(CLStdStr)); |
3565 | 47.7k | } else if (Arg *A = Args.getLastArg(options::OPT_cl_ext_EQ)) { |
3566 | 1 | std::string CLExtStr = std::string("-cl-ext=") + A->getValue(); |
3567 | 1 | CmdArgs.push_back(Args.MakeArgString(CLExtStr)); |
3568 | 1 | } |
3569 | | |
3570 | 47.7k | for (const auto &Arg : ForwardedArguments) |
3571 | 525k | if (const auto *A = Args.getLastArg(Arg)) |
3572 | 15 | CmdArgs.push_back(Args.MakeArgString(A->getOption().getPrefixedName())); |
3573 | | |
3574 | | // Only add the default headers if we are compiling OpenCL sources. |
3575 | 47.7k | if ((types::isOpenCL(InputType) || |
3576 | 47.7k | (47.4k Args.hasArg(options::OPT_cl_std_EQ)47.4k && types::isSrcFile(InputType)0 )) && |
3577 | 47.7k | !Args.hasArg(options::OPT_cl_no_stdinc)325 ) { |
3578 | 322 | CmdArgs.push_back("-finclude-default-header"); |
3579 | 322 | CmdArgs.push_back("-fdeclare-opencl-builtins"); |
3580 | 322 | } |
3581 | 47.7k | } |
3582 | | |
3583 | | static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs, |
3584 | 47.7k | types::ID InputType) { |
3585 | 47.7k | const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version, |
3586 | 47.7k | options::OPT_D, |
3587 | 47.7k | options::OPT_I, |
3588 | 47.7k | options::OPT_S, |
3589 | 47.7k | options::OPT_O, |
3590 | 47.7k | options::OPT_emit_llvm, |
3591 | 47.7k | options::OPT_emit_obj, |
3592 | 47.7k | options::OPT_disable_llvm_passes, |
3593 | 47.7k | options::OPT_fnative_half_type, |
3594 | 47.7k | options::OPT_hlsl_entrypoint}; |
3595 | 47.7k | if (!types::isHLSL(InputType)) |
3596 | 47.6k | return; |
3597 | 62 | for (const auto &Arg : ForwardedArguments) |
3598 | 620 | if (const auto *A = Args.getLastArg(Arg)) |
3599 | 176 | A->renderAsInput(Args, CmdArgs); |
3600 | | // Add the default headers if dxc_no_stdinc is not set. |
3601 | 62 | if (!Args.hasArg(options::OPT_dxc_no_stdinc) && |
3602 | 62 | !Args.hasArg(options::OPT_nostdinc)61 ) |
3603 | 60 | CmdArgs.push_back("-finclude-default-header"); |
3604 | 62 | } |
3605 | | |
3606 | | static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args, |
3607 | 47.7k | ArgStringList &CmdArgs) { |
3608 | 47.7k | bool ARCMTEnabled = false; |
3609 | 47.7k | if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) { |
3610 | 46.5k | if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check, |
3611 | 46.5k | options::OPT_ccc_arcmt_modify, |
3612 | 46.5k | options::OPT_ccc_arcmt_migrate)) { |
3613 | 2 | ARCMTEnabled = true; |
3614 | 2 | switch (A->getOption().getID()) { |
3615 | 0 | default: llvm_unreachable("missed a case"); |
3616 | 1 | case options::OPT_ccc_arcmt_check: |
3617 | 1 | CmdArgs.push_back("-arcmt-action=check"); |
3618 | 1 | break; |
3619 | 0 | case options::OPT_ccc_arcmt_modify: |
3620 | 0 | CmdArgs.push_back("-arcmt-action=modify"); |
3621 | 0 | break; |
3622 | 1 | case options::OPT_ccc_arcmt_migrate: |
3623 | 1 | CmdArgs.push_back("-arcmt-action=migrate"); |
3624 | 1 | CmdArgs.push_back("-mt-migrate-directory"); |
3625 | 1 | CmdArgs.push_back(A->getValue()); |
3626 | | |
3627 | 1 | Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output); |
3628 | 1 | Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors); |
3629 | 1 | break; |
3630 | 2 | } |
3631 | 2 | } |
3632 | 46.5k | } else { |
3633 | 1.18k | Args.ClaimAllArgs(options::OPT_ccc_arcmt_check); |
3634 | 1.18k | Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify); |
3635 | 1.18k | Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate); |
3636 | 1.18k | } |
3637 | | |
3638 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) { |
3639 | 1 | if (ARCMTEnabled) |
3640 | 0 | D.Diag(diag::err_drv_argument_not_allowed_with) |
3641 | 0 | << A->getAsString(Args) << "-ccc-arcmt-migrate"; |
3642 | | |
3643 | 1 | CmdArgs.push_back("-mt-migrate-directory"); |
3644 | 1 | CmdArgs.push_back(A->getValue()); |
3645 | | |
3646 | 1 | if (!Args.hasArg(options::OPT_objcmt_migrate_literals, |
3647 | 1 | options::OPT_objcmt_migrate_subscripting, |
3648 | 1 | options::OPT_objcmt_migrate_property)) { |
3649 | | // None specified, means enable them all. |
3650 | 1 | CmdArgs.push_back("-objcmt-migrate-literals"); |
3651 | 1 | CmdArgs.push_back("-objcmt-migrate-subscripting"); |
3652 | 1 | CmdArgs.push_back("-objcmt-migrate-property"); |
3653 | 1 | } else { |
3654 | 0 | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals); |
3655 | 0 | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting); |
3656 | 0 | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property); |
3657 | 0 | } |
3658 | 47.7k | } else { |
3659 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals); |
3660 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting); |
3661 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property); |
3662 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all); |
3663 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property); |
3664 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property); |
3665 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax); |
3666 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation); |
3667 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype); |
3668 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros); |
3669 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance); |
3670 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property); |
3671 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property); |
3672 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly); |
3673 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init); |
3674 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_objcmt_allowlist_dir_path); |
3675 | 47.7k | } |
3676 | 47.7k | } |
3677 | | |
3678 | | static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T, |
3679 | 47.7k | const ArgList &Args, ArgStringList &CmdArgs) { |
3680 | | // -fbuiltin is default unless -mkernel is used. |
3681 | 47.7k | bool UseBuiltins = |
3682 | 47.7k | Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin, |
3683 | 47.7k | !Args.hasArg(options::OPT_mkernel)); |
3684 | 47.7k | if (!UseBuiltins) |
3685 | 24 | CmdArgs.push_back("-fno-builtin"); |
3686 | | |
3687 | | // -ffreestanding implies -fno-builtin. |
3688 | 47.7k | if (Args.hasArg(options::OPT_ffreestanding)) |
3689 | 46 | UseBuiltins = false; |
3690 | | |
3691 | | // Process the -fno-builtin-* options. |
3692 | 47.7k | for (const Arg *A : Args.filtered(options::OPT_fno_builtin_)) { |
3693 | 3 | A->claim(); |
3694 | | |
3695 | | // If -fno-builtin is specified, then there's no need to pass the option to |
3696 | | // the frontend. |
3697 | 3 | if (UseBuiltins) |
3698 | 0 | A->render(Args, CmdArgs); |
3699 | 3 | } |
3700 | | |
3701 | | // le32-specific flags: |
3702 | | // -fno-math-builtin: clang should not convert math builtins to intrinsics |
3703 | | // by default. |
3704 | 47.7k | if (TC.getArch() == llvm::Triple::le32) |
3705 | 0 | CmdArgs.push_back("-fno-math-builtin"); |
3706 | 47.7k | } |
3707 | | |
3708 | 4.08k | bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) { |
3709 | 4.08k | if (const char *Str = std::getenv("CLANG_MODULE_CACHE_PATH")) { |
3710 | 2 | Twine Path{Str}; |
3711 | 2 | Path.toVector(Result); |
3712 | 2 | return Path.getSingleStringRef() != ""; |
3713 | 2 | } |
3714 | 4.08k | if (4.08k llvm::sys::path::cache_directory(Result)4.08k ) { |
3715 | 4.08k | llvm::sys::path::append(Result, "clang"); |
3716 | 4.08k | llvm::sys::path::append(Result, "ModuleCache"); |
3717 | 4.08k | return true; |
3718 | 4.08k | } |
3719 | 18.4E | return false; |
3720 | 4.08k | } |
3721 | | |
3722 | | static bool RenderModulesOptions(Compilation &C, const Driver &D, |
3723 | | const ArgList &Args, const InputInfo &Input, |
3724 | | const InputInfo &Output, const Arg *Std, |
3725 | 47.7k | ArgStringList &CmdArgs) { |
3726 | 47.7k | bool IsCXX = types::isCXX(Input.getType()); |
3727 | | // FIXME: Find a better way to determine whether the input has standard c++ |
3728 | | // modules support by default. |
3729 | 47.7k | bool HaveStdCXXModules = |
3730 | 47.7k | IsCXX && Std31.4k && |
3731 | 47.7k | (25.8k Std->containsValue("c++2a")25.8k || Std->containsValue("gnu++2a")25.8k || |
3732 | 25.8k | Std->containsValue("c++20")25.8k || Std->containsValue("gnu++20")22.6k || |
3733 | 25.8k | Std->containsValue("c++2b")22.6k || Std->containsValue("gnu++2b")22.6k || |
3734 | 25.8k | Std->containsValue("c++23")22.6k || Std->containsValue("gnu++23")22.6k || |
3735 | 25.8k | Std->containsValue("c++2c")22.6k || Std->containsValue("gnu++2c")22.6k || |
3736 | 25.8k | Std->containsValue("c++26")22.6k || Std->containsValue("gnu++26")22.6k || |
3737 | 25.8k | Std->containsValue("c++latest")22.6k || Std->containsValue("gnu++latest")22.6k ); |
3738 | 47.7k | bool HaveModules = HaveStdCXXModules; |
3739 | | |
3740 | | // -fmodules enables the use of precompiled modules (off by default). |
3741 | | // Users can pass -fno-cxx-modules to turn off modules support for |
3742 | | // C++/Objective-C++ programs. |
3743 | 47.7k | bool HaveClangModules = false; |
3744 | 47.7k | if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { |
3745 | 1.43k | bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, |
3746 | 1.43k | options::OPT_fno_cxx_modules, true); |
3747 | 1.43k | if (AllowedInCXX || !IsCXX1 ) { |
3748 | 1.43k | CmdArgs.push_back("-fmodules"); |
3749 | 1.43k | HaveClangModules = true; |
3750 | 1.43k | } |
3751 | 1.43k | } |
3752 | | |
3753 | 47.7k | HaveModules |= HaveClangModules; |
3754 | | |
3755 | | // -fmodule-maps enables implicit reading of module map files. By default, |
3756 | | // this is enabled if we are using Clang's flavor of precompiled modules. |
3757 | 47.7k | if (Args.hasFlag(options::OPT_fimplicit_module_maps, |
3758 | 47.7k | options::OPT_fno_implicit_module_maps, HaveClangModules)) |
3759 | 1.43k | CmdArgs.push_back("-fimplicit-module-maps"); |
3760 | | |
3761 | | // -fmodules-decluse checks that modules used are declared so (off by default) |
3762 | 47.7k | Args.addOptInFlag(CmdArgs, options::OPT_fmodules_decluse, |
3763 | 47.7k | options::OPT_fno_modules_decluse); |
3764 | | |
3765 | | // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that |
3766 | | // all #included headers are part of modules. |
3767 | 47.7k | if (Args.hasFlag(options::OPT_fmodules_strict_decluse, |
3768 | 47.7k | options::OPT_fno_modules_strict_decluse, false)) |
3769 | 0 | CmdArgs.push_back("-fmodules-strict-decluse"); |
3770 | | |
3771 | | // -fno-implicit-modules turns off implicitly compiling modules on demand. |
3772 | 47.7k | bool ImplicitModules = false; |
3773 | 47.7k | if (!Args.hasFlag(options::OPT_fimplicit_modules, |
3774 | 47.7k | options::OPT_fno_implicit_modules, HaveClangModules)) { |
3775 | 46.3k | if (HaveModules) |
3776 | 3.25k | CmdArgs.push_back("-fno-implicit-modules"); |
3777 | 46.3k | } else if (1.43k HaveModules1.43k ) { |
3778 | 1.43k | ImplicitModules = true; |
3779 | | // -fmodule-cache-path specifies where our implicitly-built module files |
3780 | | // should be written. |
3781 | 1.43k | SmallString<128> Path; |
3782 | 1.43k | if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) |
3783 | 1.39k | Path = A->getValue(); |
3784 | | |
3785 | 1.43k | bool HasPath = true; |
3786 | 1.43k | if (C.isForDiagnostics()) { |
3787 | | // When generating crash reports, we want to emit the modules along with |
3788 | | // the reproduction sources, so we ignore any provided module path. |
3789 | 14 | Path = Output.getFilename(); |
3790 | 14 | llvm::sys::path::replace_extension(Path, ".cache"); |
3791 | 14 | llvm::sys::path::append(Path, "modules"); |
3792 | 1.41k | } else if (Path.empty()) { |
3793 | | // No module path was provided: use the default. |
3794 | 32 | HasPath = Driver::getDefaultModuleCachePath(Path); |
3795 | 32 | } |
3796 | | |
3797 | | // `HasPath` will only be false if getDefaultModuleCachePath() fails. |
3798 | | // That being said, that failure is unlikely and not caching is harmless. |
3799 | 1.43k | if (HasPath) { |
3800 | 1.43k | const char Arg[] = "-fmodules-cache-path="; |
3801 | 1.43k | Path.insert(Path.begin(), Arg, Arg + strlen(Arg)); |
3802 | 1.43k | CmdArgs.push_back(Args.MakeArgString(Path)); |
3803 | 1.43k | } |
3804 | 1.43k | } |
3805 | | |
3806 | 47.7k | if (HaveModules) { |
3807 | 4.68k | if (Args.hasFlag(options::OPT_fprebuilt_implicit_modules, |
3808 | 4.68k | options::OPT_fno_prebuilt_implicit_modules, false)) |
3809 | 0 | CmdArgs.push_back("-fprebuilt-implicit-modules"); |
3810 | 4.68k | if (Args.hasFlag(options::OPT_fmodules_validate_input_files_content, |
3811 | 4.68k | options::OPT_fno_modules_validate_input_files_content, |
3812 | 4.68k | false)) |
3813 | 1 | CmdArgs.push_back("-fvalidate-ast-input-files-content"); |
3814 | 4.68k | } |
3815 | | |
3816 | | // -fmodule-name specifies the module that is currently being built (or |
3817 | | // used for header checking by -fmodule-maps). |
3818 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ); |
3819 | | |
3820 | | // -fmodule-map-file can be used to specify files containing module |
3821 | | // definitions. |
3822 | 47.7k | Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file); |
3823 | | |
3824 | | // -fbuiltin-module-map can be used to load the clang |
3825 | | // builtin headers modulemap file. |
3826 | 47.7k | if (Args.hasArg(options::OPT_fbuiltin_module_map)) { |
3827 | 1 | SmallString<128> BuiltinModuleMap(D.ResourceDir); |
3828 | 1 | llvm::sys::path::append(BuiltinModuleMap, "include"); |
3829 | 1 | llvm::sys::path::append(BuiltinModuleMap, "module.modulemap"); |
3830 | 1 | if (llvm::sys::fs::exists(BuiltinModuleMap)) |
3831 | 1 | CmdArgs.push_back( |
3832 | 1 | Args.MakeArgString("-fmodule-map-file=" + BuiltinModuleMap)); |
3833 | 1 | } |
3834 | | |
3835 | | // The -fmodule-file=<name>=<file> form specifies the mapping of module |
3836 | | // names to precompiled module files (the module is loaded only if used). |
3837 | | // The -fmodule-file=<file> form can be used to unconditionally load |
3838 | | // precompiled module files (whether used or not). |
3839 | 47.7k | if (HaveModules || Input.getType() == clang::driver::types::TY_ModuleFile43.0k ) { |
3840 | 4.70k | Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file); |
3841 | | |
3842 | | // -fprebuilt-module-path specifies where to load the prebuilt module files. |
3843 | 4.70k | for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path)) { |
3844 | 32 | CmdArgs.push_back(Args.MakeArgString( |
3845 | 32 | std::string("-fprebuilt-module-path=") + A->getValue())); |
3846 | 32 | A->claim(); |
3847 | 32 | } |
3848 | 4.70k | } else |
3849 | 43.0k | Args.ClaimAllArgs(options::OPT_fmodule_file); |
3850 | | |
3851 | | // When building modules and generating crashdumps, we need to dump a module |
3852 | | // dependency VFS alongside the output. |
3853 | 47.7k | if (HaveClangModules && C.isForDiagnostics()1.43k ) { |
3854 | 14 | SmallString<128> VFSDir(Output.getFilename()); |
3855 | 14 | llvm::sys::path::replace_extension(VFSDir, ".cache"); |
3856 | | // Add the cache directory as a temp so the crash diagnostics pick it up. |
3857 | 14 | C.addTempFile(Args.MakeArgString(VFSDir)); |
3858 | | |
3859 | 14 | llvm::sys::path::append(VFSDir, "vfs"); |
3860 | 14 | CmdArgs.push_back("-module-dependency-dir"); |
3861 | 14 | CmdArgs.push_back(Args.MakeArgString(VFSDir)); |
3862 | 14 | } |
3863 | | |
3864 | 47.7k | if (HaveClangModules) |
3865 | 1.43k | Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path); |
3866 | | |
3867 | | // Pass through all -fmodules-ignore-macro arguments. |
3868 | 47.7k | Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro); |
3869 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval); |
3870 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after); |
3871 | | |
3872 | 47.7k | if (HaveClangModules) { |
3873 | 1.43k | Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp); |
3874 | | |
3875 | 1.43k | if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) { |
3876 | 5 | if (Args.hasArg(options::OPT_fbuild_session_timestamp)) |
3877 | 1 | D.Diag(diag::err_drv_argument_not_allowed_with) |
3878 | 1 | << A->getAsString(Args) << "-fbuild-session-timestamp"; |
3879 | | |
3880 | 5 | llvm::sys::fs::file_status Status; |
3881 | 5 | if (llvm::sys::fs::status(A->getValue(), Status)) |
3882 | 1 | D.Diag(diag::err_drv_no_such_file) << A->getValue(); |
3883 | 5 | CmdArgs.push_back(Args.MakeArgString( |
3884 | 5 | "-fbuild-session-timestamp=" + |
3885 | 5 | Twine((uint64_t)std::chrono::duration_cast<std::chrono::seconds>( |
3886 | 5 | Status.getLastModificationTime().time_since_epoch()) |
3887 | 5 | .count()))); |
3888 | 5 | } |
3889 | | |
3890 | 1.43k | if (Args.getLastArg( |
3891 | 1.43k | options::OPT_fmodules_validate_once_per_build_session)) { |
3892 | 4 | if (!Args.getLastArg(options::OPT_fbuild_session_timestamp, |
3893 | 4 | options::OPT_fbuild_session_file)) |
3894 | 1 | D.Diag(diag::err_drv_modules_validate_once_requires_timestamp); |
3895 | | |
3896 | 4 | Args.AddLastArg(CmdArgs, |
3897 | 4 | options::OPT_fmodules_validate_once_per_build_session); |
3898 | 4 | } |
3899 | | |
3900 | 1.43k | if (Args.hasFlag(options::OPT_fmodules_validate_system_headers, |
3901 | 1.43k | options::OPT_fno_modules_validate_system_headers, |
3902 | 1.43k | ImplicitModules)) |
3903 | 1.42k | CmdArgs.push_back("-fmodules-validate-system-headers"); |
3904 | | |
3905 | 1.43k | Args.AddLastArg(CmdArgs, |
3906 | 1.43k | options::OPT_fmodules_disable_diagnostic_validation); |
3907 | 46.3k | } else { |
3908 | 46.3k | Args.ClaimAllArgs(options::OPT_fbuild_session_timestamp); |
3909 | 46.3k | Args.ClaimAllArgs(options::OPT_fbuild_session_file); |
3910 | 46.3k | Args.ClaimAllArgs(options::OPT_fmodules_validate_once_per_build_session); |
3911 | 46.3k | Args.ClaimAllArgs(options::OPT_fmodules_validate_system_headers); |
3912 | 46.3k | Args.ClaimAllArgs(options::OPT_fno_modules_validate_system_headers); |
3913 | 46.3k | Args.ClaimAllArgs(options::OPT_fmodules_disable_diagnostic_validation); |
3914 | 46.3k | } |
3915 | | |
3916 | | // Claim `-fmodule-output` and `-fmodule-output=` to avoid unused warnings. |
3917 | 47.7k | Args.ClaimAllArgs(options::OPT_fmodule_output); |
3918 | 47.7k | Args.ClaimAllArgs(options::OPT_fmodule_output_EQ); |
3919 | | |
3920 | 47.7k | return HaveModules; |
3921 | 47.7k | } |
3922 | | |
3923 | | static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, |
3924 | 47.7k | ArgStringList &CmdArgs) { |
3925 | | // -fsigned-char is default. |
3926 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_fsigned_char, |
3927 | 47.7k | options::OPT_fno_signed_char, |
3928 | 47.7k | options::OPT_funsigned_char, |
3929 | 47.7k | options::OPT_fno_unsigned_char)) { |
3930 | 10 | if (A->getOption().matches(options::OPT_funsigned_char) || |
3931 | 10 | A->getOption().matches(options::OPT_fno_signed_char)6 ) { |
3932 | 6 | CmdArgs.push_back("-fno-signed-char"); |
3933 | 6 | } |
3934 | 47.7k | } else if (!isSignedCharDefault(T)) { |
3935 | 5.03k | CmdArgs.push_back("-fno-signed-char"); |
3936 | 5.03k | } |
3937 | | |
3938 | | // The default depends on the language standard. |
3939 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_fchar8__t, options::OPT_fno_char8__t); |
3940 | | |
3941 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar, |
3942 | 47.7k | options::OPT_fno_short_wchar)) { |
3943 | 26 | if (A->getOption().matches(options::OPT_fshort_wchar)) { |
3944 | 4 | CmdArgs.push_back("-fwchar-type=short"); |
3945 | 4 | CmdArgs.push_back("-fno-signed-wchar"); |
3946 | 22 | } else { |
3947 | 22 | bool IsARM = T.isARM() || T.isThumb()9 || T.isAArch64()9 ; |
3948 | 22 | CmdArgs.push_back("-fwchar-type=int"); |
3949 | 22 | if (T.isOSzOS() || |
3950 | 22 | (IsARM && !(20 T.isOSWindows()20 || T.isOSNetBSD()18 || T.isOSOpenBSD()12 ))) |
3951 | 6 | CmdArgs.push_back("-fno-signed-wchar"); |
3952 | 16 | else |
3953 | 16 | CmdArgs.push_back("-fsigned-wchar"); |
3954 | 22 | } |
3955 | 47.7k | } else if (T.isOSzOS()) |
3956 | 37 | CmdArgs.push_back("-fno-signed-wchar"); |
3957 | 47.7k | } |
3958 | | |
3959 | | static void RenderObjCOptions(const ToolChain &TC, const Driver &D, |
3960 | | const llvm::Triple &T, const ArgList &Args, |
3961 | | ObjCRuntime &Runtime, bool InferCovariantReturns, |
3962 | 47.7k | const InputInfo &Input, ArgStringList &CmdArgs) { |
3963 | 47.7k | const llvm::Triple::ArchType Arch = TC.getArch(); |
3964 | | |
3965 | | // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and legacy |
3966 | | // is the default. Except for deployment target of 10.5, next runtime is |
3967 | | // always legacy dispatch and -fno-objc-legacy-dispatch gets ignored silently. |
3968 | 47.7k | if (Runtime.isNonFragile()) { |
3969 | 19.3k | if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch, |
3970 | 19.3k | options::OPT_fno_objc_legacy_dispatch, |
3971 | 19.3k | Runtime.isLegacyDispatchDefaultForArch(Arch))) { |
3972 | 35 | if (TC.UseObjCMixedDispatch()) |
3973 | 2 | CmdArgs.push_back("-fobjc-dispatch-method=mixed"); |
3974 | 33 | else |
3975 | 33 | CmdArgs.push_back("-fobjc-dispatch-method=non-legacy"); |
3976 | 35 | } |
3977 | 19.3k | } |
3978 | | |
3979 | | // When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option |
3980 | | // to do Array/Dictionary subscripting by default. |
3981 | 47.7k | if (Arch == llvm::Triple::x86 && T.isMacOSX()11.2k && |
3982 | 47.7k | Runtime.getKind() == ObjCRuntime::FragileMacOSX116 && Runtime.isNeXTFamily()102 ) |
3983 | 102 | CmdArgs.push_back("-fobjc-subscripting-legacy-runtime"); |
3984 | | |
3985 | | // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc. |
3986 | | // NOTE: This logic is duplicated in ToolChains.cpp. |
3987 | 47.7k | if (isObjCAutoRefCount(Args)) { |
3988 | 1.17k | TC.CheckObjCARC(); |
3989 | | |
3990 | 1.17k | CmdArgs.push_back("-fobjc-arc"); |
3991 | | |
3992 | | // FIXME: It seems like this entire block, and several around it should be |
3993 | | // wrapped in isObjC, but for now we just use it here as this is where it |
3994 | | // was being used previously. |
3995 | 1.17k | if (types::isCXX(Input.getType()) && types::isObjC(Input.getType())1.14k ) { |
3996 | 1.14k | if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) |
3997 | 1.04k | CmdArgs.push_back("-fobjc-arc-cxxlib=libc++"); |
3998 | 103 | else |
3999 | 103 | CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++"); |
4000 | 1.14k | } |
4001 | | |
4002 | | // Allow the user to enable full exceptions code emission. |
4003 | | // We default off for Objective-C, on for Objective-C++. |
4004 | 1.17k | if (Args.hasFlag(options::OPT_fobjc_arc_exceptions, |
4005 | 1.17k | options::OPT_fno_objc_arc_exceptions, |
4006 | 1.17k | /*Default=*/types::isCXX(Input.getType()))) |
4007 | 1.14k | CmdArgs.push_back("-fobjc-arc-exceptions"); |
4008 | 1.17k | } |
4009 | | |
4010 | | // Silence warning for full exception code emission options when explicitly |
4011 | | // set to use no ARC. |
4012 | 47.7k | if (Args.hasArg(options::OPT_fno_objc_arc)) { |
4013 | 11 | Args.ClaimAllArgs(options::OPT_fobjc_arc_exceptions); |
4014 | 11 | Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions); |
4015 | 11 | } |
4016 | | |
4017 | | // Allow the user to control whether messages can be converted to runtime |
4018 | | // functions. |
4019 | 47.7k | if (types::isObjC(Input.getType())) { |
4020 | 3.03k | auto *Arg = Args.getLastArg( |
4021 | 3.03k | options::OPT_fobjc_convert_messages_to_runtime_calls, |
4022 | 3.03k | options::OPT_fno_objc_convert_messages_to_runtime_calls); |
4023 | 3.03k | if (Arg && |
4024 | 3.03k | Arg->getOption().matches( |
4025 | 2 | options::OPT_fno_objc_convert_messages_to_runtime_calls)) |
4026 | 1 | CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls"); |
4027 | 3.03k | } |
4028 | | |
4029 | | // -fobjc-infer-related-result-type is the default, except in the Objective-C |
4030 | | // rewriter. |
4031 | 47.7k | if (InferCovariantReturns) |
4032 | 8 | CmdArgs.push_back("-fno-objc-infer-related-result-type"); |
4033 | | |
4034 | | // Pass down -fobjc-weak or -fno-objc-weak if present. |
4035 | 47.7k | if (types::isObjC(Input.getType())) { |
4036 | 3.03k | auto WeakArg = |
4037 | 3.03k | Args.getLastArg(options::OPT_fobjc_weak, options::OPT_fno_objc_weak); |
4038 | 3.03k | if (!WeakArg) { |
4039 | | // nothing to do |
4040 | 3.01k | } else if (12 !Runtime.allowsWeak()12 ) { |
4041 | 4 | if (WeakArg->getOption().matches(options::OPT_fobjc_weak)) |
4042 | 4 | D.Diag(diag::err_objc_weak_unsupported); |
4043 | 8 | } else { |
4044 | 8 | WeakArg->render(Args, CmdArgs); |
4045 | 8 | } |
4046 | 3.03k | } |
4047 | | |
4048 | 47.7k | if (Args.hasArg(options::OPT_fobjc_disable_direct_methods_for_testing)) |
4049 | 1 | CmdArgs.push_back("-fobjc-disable-direct-methods-for-testing"); |
4050 | 47.7k | } |
4051 | | |
4052 | | static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args, |
4053 | 47.7k | ArgStringList &CmdArgs) { |
4054 | 47.7k | bool CaretDefault = true; |
4055 | 47.7k | bool ColumnDefault = true; |
4056 | | |
4057 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diagnostics_classic, |
4058 | 47.7k | options::OPT__SLASH_diagnostics_column, |
4059 | 47.7k | options::OPT__SLASH_diagnostics_caret)) { |
4060 | 5 | switch (A->getOption().getID()) { |
4061 | 2 | case options::OPT__SLASH_diagnostics_caret: |
4062 | 2 | CaretDefault = true; |
4063 | 2 | ColumnDefault = true; |
4064 | 2 | break; |
4065 | 1 | case options::OPT__SLASH_diagnostics_column: |
4066 | 1 | CaretDefault = false; |
4067 | 1 | ColumnDefault = true; |
4068 | 1 | break; |
4069 | 2 | case options::OPT__SLASH_diagnostics_classic: |
4070 | 2 | CaretDefault = false; |
4071 | 2 | ColumnDefault = false; |
4072 | 2 | break; |
4073 | 5 | } |
4074 | 5 | } |
4075 | | |
4076 | | // -fcaret-diagnostics is default. |
4077 | 47.7k | if (!Args.hasFlag(options::OPT_fcaret_diagnostics, |
4078 | 47.7k | options::OPT_fno_caret_diagnostics, CaretDefault)) |
4079 | 3 | CmdArgs.push_back("-fno-caret-diagnostics"); |
4080 | | |
4081 | 47.7k | Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_fixit_info, |
4082 | 47.7k | options::OPT_fno_diagnostics_fixit_info); |
4083 | 47.7k | Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_show_option, |
4084 | 47.7k | options::OPT_fno_diagnostics_show_option); |
4085 | | |
4086 | 47.7k | if (const Arg *A = |
4087 | 47.7k | Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) { |
4088 | 0 | CmdArgs.push_back("-fdiagnostics-show-category"); |
4089 | 0 | CmdArgs.push_back(A->getValue()); |
4090 | 0 | } |
4091 | | |
4092 | 47.7k | Args.addOptInFlag(CmdArgs, options::OPT_fdiagnostics_show_hotness, |
4093 | 47.7k | options::OPT_fno_diagnostics_show_hotness); |
4094 | | |
4095 | 47.7k | if (const Arg *A = |
4096 | 47.7k | Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) { |
4097 | 6 | std::string Opt = |
4098 | 6 | std::string("-fdiagnostics-hotness-threshold=") + A->getValue(); |
4099 | 6 | CmdArgs.push_back(Args.MakeArgString(Opt)); |
4100 | 6 | } |
4101 | | |
4102 | 47.7k | if (const Arg *A = |
4103 | 47.7k | Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) { |
4104 | 1 | std::string Opt = |
4105 | 1 | std::string("-fdiagnostics-misexpect-tolerance=") + A->getValue(); |
4106 | 1 | CmdArgs.push_back(Args.MakeArgString(Opt)); |
4107 | 1 | } |
4108 | | |
4109 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) { |
4110 | 19 | CmdArgs.push_back("-fdiagnostics-format"); |
4111 | 19 | CmdArgs.push_back(A->getValue()); |
4112 | 19 | if (StringRef(A->getValue()) == "sarif" || |
4113 | 19 | StringRef(A->getValue()) == "SARIF"17 ) |
4114 | 3 | D.Diag(diag::warn_drv_sarif_format_unstable); |
4115 | 19 | } |
4116 | | |
4117 | 47.7k | if (const Arg *A = Args.getLastArg( |
4118 | 47.7k | options::OPT_fdiagnostics_show_note_include_stack, |
4119 | 47.7k | options::OPT_fno_diagnostics_show_note_include_stack)) { |
4120 | 0 | const Option &O = A->getOption(); |
4121 | 0 | if (O.matches(options::OPT_fdiagnostics_show_note_include_stack)) |
4122 | 0 | CmdArgs.push_back("-fdiagnostics-show-note-include-stack"); |
4123 | 0 | else |
4124 | 0 | CmdArgs.push_back("-fno-diagnostics-show-note-include-stack"); |
4125 | 0 | } |
4126 | | |
4127 | | // Color diagnostics are parsed by the driver directly from argv and later |
4128 | | // re-parsed to construct this job; claim any possible color diagnostic here |
4129 | | // to avoid warn_drv_unused_argument and diagnose bad |
4130 | | // OPT_fdiagnostics_color_EQ values. |
4131 | 47.7k | Args.getLastArg(options::OPT_fcolor_diagnostics, |
4132 | 47.7k | options::OPT_fno_color_diagnostics); |
4133 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_color_EQ)) { |
4134 | 9 | StringRef Value(A->getValue()); |
4135 | 9 | if (Value != "always" && Value != "never"6 && Value != "auto"4 ) |
4136 | 1 | D.Diag(diag::err_drv_invalid_argument_to_option) |
4137 | 1 | << Value << A->getOption().getName(); |
4138 | 9 | } |
4139 | | |
4140 | 47.7k | if (D.getDiags().getDiagnosticOptions().ShowColors) |
4141 | 12 | CmdArgs.push_back("-fcolor-diagnostics"); |
4142 | | |
4143 | 47.7k | if (Args.hasArg(options::OPT_fansi_escape_codes)) |
4144 | 1 | CmdArgs.push_back("-fansi-escape-codes"); |
4145 | | |
4146 | 47.7k | Args.addOptOutFlag(CmdArgs, options::OPT_fshow_source_location, |
4147 | 47.7k | options::OPT_fno_show_source_location); |
4148 | | |
4149 | 47.7k | Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_show_line_numbers, |
4150 | 47.7k | options::OPT_fno_diagnostics_show_line_numbers); |
4151 | | |
4152 | 47.7k | if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths)) |
4153 | 0 | CmdArgs.push_back("-fdiagnostics-absolute-paths"); |
4154 | | |
4155 | 47.7k | if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column, |
4156 | 47.7k | ColumnDefault)) |
4157 | 4 | CmdArgs.push_back("-fno-show-column"); |
4158 | | |
4159 | 47.7k | Args.addOptOutFlag(CmdArgs, options::OPT_fspell_checking, |
4160 | 47.7k | options::OPT_fno_spell_checking); |
4161 | 47.7k | } |
4162 | | |
4163 | | DwarfFissionKind tools::getDebugFissionKind(const Driver &D, |
4164 | 4.67k | const ArgList &Args, Arg *&Arg) { |
4165 | 4.67k | Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ, |
4166 | 4.67k | options::OPT_gno_split_dwarf); |
4167 | 4.67k | if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf)62 ) |
4168 | 4.61k | return DwarfFissionKind::None; |
4169 | | |
4170 | 60 | if (Arg->getOption().matches(options::OPT_gsplit_dwarf)) |
4171 | 46 | return DwarfFissionKind::Split; |
4172 | | |
4173 | 14 | StringRef Value = Arg->getValue(); |
4174 | 14 | if (Value == "split") |
4175 | 5 | return DwarfFissionKind::Split; |
4176 | 9 | if (Value == "single") |
4177 | 9 | return DwarfFissionKind::Single; |
4178 | | |
4179 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
4180 | 0 | << Arg->getSpelling() << Arg->getValue(); |
4181 | 0 | return DwarfFissionKind::None; |
4182 | 9 | } |
4183 | | |
4184 | | static void renderDwarfFormat(const Driver &D, const llvm::Triple &T, |
4185 | | const ArgList &Args, ArgStringList &CmdArgs, |
4186 | 48.2k | unsigned DwarfVersion) { |
4187 | 48.2k | auto *DwarfFormatArg = |
4188 | 48.2k | Args.getLastArg(options::OPT_gdwarf64, options::OPT_gdwarf32); |
4189 | 48.2k | if (!DwarfFormatArg) |
4190 | 48.2k | return; |
4191 | | |
4192 | 15 | if (DwarfFormatArg->getOption().matches(options::OPT_gdwarf64)) { |
4193 | 14 | if (DwarfVersion < 3) |
4194 | 2 | D.Diag(diag::err_drv_argument_only_allowed_with) |
4195 | 2 | << DwarfFormatArg->getAsString(Args) << "DWARFv3 or greater"; |
4196 | 12 | else if (!T.isArch64Bit()) |
4197 | 2 | D.Diag(diag::err_drv_argument_only_allowed_with) |
4198 | 2 | << DwarfFormatArg->getAsString(Args) << "64 bit architecture"; |
4199 | 10 | else if (!T.isOSBinFormatELF()) |
4200 | 2 | D.Diag(diag::err_drv_argument_only_allowed_with) |
4201 | 2 | << DwarfFormatArg->getAsString(Args) << "ELF platforms"; |
4202 | 14 | } |
4203 | | |
4204 | 15 | DwarfFormatArg->render(Args, CmdArgs); |
4205 | 15 | } |
4206 | | |
4207 | | static void |
4208 | | renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, |
4209 | | const ArgList &Args, bool IRInput, ArgStringList &CmdArgs, |
4210 | | const InputInfo &Output, |
4211 | | llvm::codegenoptions::DebugInfoKind &DebugInfoKind, |
4212 | 47.7k | DwarfFissionKind &DwarfFission) { |
4213 | 47.7k | if (Args.hasFlag(options::OPT_fdebug_info_for_profiling, |
4214 | 47.7k | options::OPT_fno_debug_info_for_profiling, false) && |
4215 | 47.7k | checkDebugInfoOption( |
4216 | 2 | Args.getLastArg(options::OPT_fdebug_info_for_profiling), Args, D, TC)) |
4217 | 2 | CmdArgs.push_back("-fdebug-info-for-profiling"); |
4218 | | |
4219 | | // The 'g' groups options involve a somewhat intricate sequence of decisions |
4220 | | // about what to pass from the driver to the frontend, but by the time they |
4221 | | // reach cc1 they've been factored into three well-defined orthogonal choices: |
4222 | | // * what level of debug info to generate |
4223 | | // * what dwarf version to write |
4224 | | // * what debugger tuning to use |
4225 | | // This avoids having to monkey around further in cc1 other than to disable |
4226 | | // codeview if not running in a Windows environment. Perhaps even that |
4227 | | // decision should be made in the driver as well though. |
4228 | 47.7k | llvm::DebuggerKind DebuggerTuning = TC.getDefaultDebuggerTuning(); |
4229 | | |
4230 | 47.7k | bool SplitDWARFInlining = |
4231 | 47.7k | Args.hasFlag(options::OPT_fsplit_dwarf_inlining, |
4232 | 47.7k | options::OPT_fno_split_dwarf_inlining, false); |
4233 | | |
4234 | | // Normally -gsplit-dwarf is only useful with -gN. For IR input, Clang does |
4235 | | // object file generation and no IR generation, -gN should not be needed. So |
4236 | | // allow -gsplit-dwarf with either -gN or IR input. |
4237 | 47.7k | if (IRInput || Args.hasArg(options::OPT_g_Group)47.6k ) { |
4238 | 3.50k | Arg *SplitDWARFArg; |
4239 | 3.50k | DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg); |
4240 | 3.50k | if (DwarfFission != DwarfFissionKind::None && |
4241 | 3.50k | !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)53 ) { |
4242 | 0 | DwarfFission = DwarfFissionKind::None; |
4243 | 0 | SplitDWARFInlining = false; |
4244 | 0 | } |
4245 | 3.50k | } |
4246 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) { |
4247 | 3.37k | DebugInfoKind = llvm::codegenoptions::DebugInfoConstructor; |
4248 | | |
4249 | | // If the last option explicitly specified a debug-info level, use it. |
4250 | 3.37k | if (checkDebugInfoOption(A, Args, D, TC) && |
4251 | 3.37k | A->getOption().matches(options::OPT_gN_Group)) { |
4252 | 132 | DebugInfoKind = debugLevelToInfoKind(*A); |
4253 | | // For -g0 or -gline-tables-only, drop -gsplit-dwarf. This gets a bit more |
4254 | | // complicated if you've disabled inline info in the skeleton CUs |
4255 | | // (SplitDWARFInlining) - then there's value in composing split-dwarf and |
4256 | | // line-tables-only, so let those compose naturally in that case. |
4257 | 132 | if (DebugInfoKind == llvm::codegenoptions::NoDebugInfo || |
4258 | 132 | DebugInfoKind == llvm::codegenoptions::DebugDirectivesOnly102 || |
4259 | 132 | (96 DebugInfoKind == llvm::codegenoptions::DebugLineTablesOnly96 && |
4260 | 96 | SplitDWARFInlining22 )) |
4261 | 37 | DwarfFission = DwarfFissionKind::None; |
4262 | 132 | } |
4263 | 3.37k | } |
4264 | | |
4265 | | // If a debugger tuning argument appeared, remember it. |
4266 | 47.7k | bool HasDebuggerTuning = false; |
4267 | 47.7k | if (const Arg *A = |
4268 | 47.7k | Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) { |
4269 | 123 | HasDebuggerTuning = true; |
4270 | 123 | if (checkDebugInfoOption(A, Args, D, TC)) { |
4271 | 123 | if (A->getOption().matches(options::OPT_glldb)) |
4272 | 65 | DebuggerTuning = llvm::DebuggerKind::LLDB; |
4273 | 58 | else if (A->getOption().matches(options::OPT_gsce)) |
4274 | 3 | DebuggerTuning = llvm::DebuggerKind::SCE; |
4275 | 55 | else if (A->getOption().matches(options::OPT_gdbx)) |
4276 | 5 | DebuggerTuning = llvm::DebuggerKind::DBX; |
4277 | 50 | else |
4278 | 50 | DebuggerTuning = llvm::DebuggerKind::GDB; |
4279 | 123 | } |
4280 | 123 | } |
4281 | | |
4282 | | // If a -gdwarf argument appeared, remember it. |
4283 | 47.7k | bool EmitDwarf = false; |
4284 | 47.7k | if (const Arg *A = getDwarfNArg(Args)) |
4285 | 52 | EmitDwarf = checkDebugInfoOption(A, Args, D, TC); |
4286 | | |
4287 | 47.7k | bool EmitCodeView = false; |
4288 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) |
4289 | 19 | EmitCodeView = checkDebugInfoOption(A, Args, D, TC); |
4290 | | |
4291 | | // If the user asked for debug info but did not explicitly specify -gcodeview |
4292 | | // or -gdwarf, ask the toolchain for the default format. |
4293 | 47.7k | if (!EmitCodeView && !EmitDwarf47.7k && |
4294 | 47.7k | DebugInfoKind != llvm::codegenoptions::NoDebugInfo47.6k ) { |
4295 | 3.27k | switch (TC.getDefaultDebugFormat()) { |
4296 | 51 | case llvm::codegenoptions::DIF_CodeView: |
4297 | 51 | EmitCodeView = true; |
4298 | 51 | break; |
4299 | 3.22k | case llvm::codegenoptions::DIF_DWARF: |
4300 | 3.22k | EmitDwarf = true; |
4301 | 3.22k | break; |
4302 | 3.27k | } |
4303 | 3.27k | } |
4304 | | |
4305 | 47.7k | unsigned RequestedDWARFVersion = 0; // DWARF version requested by the user |
4306 | 47.7k | unsigned EffectiveDWARFVersion = 0; // DWARF version TC can generate. It may |
4307 | | // be lower than what the user wanted. |
4308 | 47.7k | if (EmitDwarf) { |
4309 | 3.28k | RequestedDWARFVersion = getDwarfVersion(TC, Args); |
4310 | | // Clamp effective DWARF version to the max supported by the toolchain. |
4311 | 3.28k | EffectiveDWARFVersion = |
4312 | 3.28k | std::min(RequestedDWARFVersion, TC.getMaxDwarfVersion()); |
4313 | 44.4k | } else { |
4314 | 44.4k | Args.ClaimAllArgs(options::OPT_fdebug_default_version); |
4315 | 44.4k | } |
4316 | | |
4317 | | // -gline-directives-only supported only for the DWARF debug info. |
4318 | 47.7k | if (RequestedDWARFVersion == 0 && |
4319 | 47.7k | DebugInfoKind == llvm::codegenoptions::DebugDirectivesOnly44.4k ) |
4320 | 0 | DebugInfoKind = llvm::codegenoptions::NoDebugInfo; |
4321 | | |
4322 | | // strict DWARF is set to false by default. But for DBX, we need it to be set |
4323 | | // as true by default. |
4324 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_gstrict_dwarf)) |
4325 | 2 | (void)checkDebugInfoOption(A, Args, D, TC); |
4326 | 47.7k | if (Args.hasFlag(options::OPT_gstrict_dwarf, options::OPT_gno_strict_dwarf, |
4327 | 47.7k | DebuggerTuning == llvm::DebuggerKind::DBX)) |
4328 | 236 | CmdArgs.push_back("-gstrict-dwarf"); |
4329 | | |
4330 | | // And we handle flag -grecord-gcc-switches later with DWARFDebugFlags. |
4331 | 47.7k | Args.ClaimAllArgs(options::OPT_g_flags_Group); |
4332 | | |
4333 | | // Column info is included by default for everything except SCE and |
4334 | | // CodeView. Clang doesn't track end columns, just starting columns, which, |
4335 | | // in theory, is fine for CodeView (and PDB). In practice, however, the |
4336 | | // Microsoft debuggers don't handle missing end columns well, and the AIX |
4337 | | // debugger DBX also doesn't handle the columns well, so it's better not to |
4338 | | // include any column info. |
4339 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_gcolumn_info)) |
4340 | 16 | (void)checkDebugInfoOption(A, Args, D, TC); |
4341 | 47.7k | if (!Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info, |
4342 | 47.7k | !EmitCodeView && |
4343 | 47.7k | (47.6k DebuggerTuning != llvm::DebuggerKind::SCE47.6k && |
4344 | 47.6k | DebuggerTuning != llvm::DebuggerKind::DBX47.3k ))) |
4345 | 591 | CmdArgs.push_back("-gno-column-info"); |
4346 | | |
4347 | | // FIXME: Move backend command line options to the module. |
4348 | 47.7k | if (Args.hasFlag(options::OPT_gmodules, options::OPT_gno_modules, false)) { |
4349 | | // If -gline-tables-only or -gline-directives-only is the last option it |
4350 | | // wins. |
4351 | 64 | if (checkDebugInfoOption(Args.getLastArg(options::OPT_gmodules), Args, D, |
4352 | 64 | TC)) { |
4353 | 64 | if (DebugInfoKind != llvm::codegenoptions::DebugLineTablesOnly && |
4354 | 64 | DebugInfoKind != llvm::codegenoptions::DebugDirectivesOnly63 ) { |
4355 | 62 | DebugInfoKind = llvm::codegenoptions::DebugInfoConstructor; |
4356 | 62 | CmdArgs.push_back("-dwarf-ext-refs"); |
4357 | 62 | CmdArgs.push_back("-fmodule-format=obj"); |
4358 | 62 | } |
4359 | 64 | } |
4360 | 64 | } |
4361 | | |
4362 | 47.7k | if (T.isOSBinFormatELF() && SplitDWARFInlining20.6k ) |
4363 | 4 | CmdArgs.push_back("-fsplit-dwarf-inlining"); |
4364 | | |
4365 | | // After we've dealt with all combinations of things that could |
4366 | | // make DebugInfoKind be other than None or DebugLineTablesOnly, |
4367 | | // figure out if we need to "upgrade" it to standalone debug info. |
4368 | | // We parse these two '-f' options whether or not they will be used, |
4369 | | // to claim them even if you wrote "-fstandalone-debug -gline-tables-only" |
4370 | 47.7k | bool NeedFullDebug = Args.hasFlag( |
4371 | 47.7k | options::OPT_fstandalone_debug, options::OPT_fno_standalone_debug, |
4372 | 47.7k | DebuggerTuning == llvm::DebuggerKind::LLDB || |
4373 | 47.7k | TC.GetDefaultStandaloneDebug()30.0k ); |
4374 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug)) |
4375 | 2.74k | (void)checkDebugInfoOption(A, Args, D, TC); |
4376 | | |
4377 | 47.7k | if (DebugInfoKind == llvm::codegenoptions::LimitedDebugInfo || |
4378 | 47.7k | DebugInfoKind == llvm::codegenoptions::DebugInfoConstructor) { |
4379 | 3.31k | if (Args.hasFlag(options::OPT_fno_eliminate_unused_debug_types, |
4380 | 3.31k | options::OPT_feliminate_unused_debug_types, false)) |
4381 | 1 | DebugInfoKind = llvm::codegenoptions::UnusedTypeInfo; |
4382 | 3.31k | else if (NeedFullDebug) |
4383 | 2.99k | DebugInfoKind = llvm::codegenoptions::FullDebugInfo; |
4384 | 3.31k | } |
4385 | | |
4386 | 47.7k | if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source, |
4387 | 47.7k | false)) { |
4388 | | // Source embedding is a vendor extension to DWARF v5. By now we have |
4389 | | // checked if a DWARF version was stated explicitly, and have otherwise |
4390 | | // fallen back to the target default, so if this is still not at least 5 |
4391 | | // we emit an error. |
4392 | 2 | const Arg *A = Args.getLastArg(options::OPT_gembed_source); |
4393 | 2 | if (RequestedDWARFVersion < 5) |
4394 | 1 | D.Diag(diag::err_drv_argument_only_allowed_with) |
4395 | 1 | << A->getAsString(Args) << "-gdwarf-5"; |
4396 | 1 | else if (EffectiveDWARFVersion < 5) |
4397 | | // The toolchain has reduced allowed dwarf version, so we can't enable |
4398 | | // -gembed-source. |
4399 | 0 | D.Diag(diag::warn_drv_dwarf_version_limited_by_target) |
4400 | 0 | << A->getAsString(Args) << TC.getTripleString() << 5 |
4401 | 0 | << EffectiveDWARFVersion; |
4402 | 1 | else if (checkDebugInfoOption(A, Args, D, TC)) |
4403 | 1 | CmdArgs.push_back("-gembed-source"); |
4404 | 2 | } |
4405 | | |
4406 | 47.7k | if (EmitCodeView) { |
4407 | 70 | CmdArgs.push_back("-gcodeview"); |
4408 | | |
4409 | 70 | Args.addOptInFlag(CmdArgs, options::OPT_gcodeview_ghash, |
4410 | 70 | options::OPT_gno_codeview_ghash); |
4411 | | |
4412 | 70 | Args.addOptOutFlag(CmdArgs, options::OPT_gcodeview_command_line, |
4413 | 70 | options::OPT_gno_codeview_command_line); |
4414 | 70 | } |
4415 | | |
4416 | 47.7k | Args.addOptOutFlag(CmdArgs, options::OPT_ginline_line_tables, |
4417 | 47.7k | options::OPT_gno_inline_line_tables); |
4418 | | |
4419 | | // When emitting remarks, we need at least debug lines in the output. |
4420 | 47.7k | if (willEmitRemarks(Args) && |
4421 | 47.7k | DebugInfoKind <= llvm::codegenoptions::DebugDirectivesOnly38 ) |
4422 | 37 | DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly; |
4423 | | |
4424 | | // Adjust the debug info kind for the given toolchain. |
4425 | 47.7k | TC.adjustDebugInfoKind(DebugInfoKind, Args); |
4426 | | |
4427 | | // On AIX, the debugger tuning option can be omitted if it is not explicitly |
4428 | | // set. |
4429 | 47.7k | RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, EffectiveDWARFVersion, |
4430 | 47.7k | T.isOSAIX() && !HasDebuggerTuning241 |
4431 | 47.7k | ? llvm::DebuggerKind::Default233 |
4432 | 47.7k | : DebuggerTuning47.5k ); |
4433 | | |
4434 | | // -fdebug-macro turns on macro debug info generation. |
4435 | 47.7k | if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro, |
4436 | 47.7k | false)) |
4437 | 1 | if (checkDebugInfoOption(Args.getLastArg(options::OPT_fdebug_macro), Args, |
4438 | 1 | D, TC)) |
4439 | 1 | CmdArgs.push_back("-debug-info-macro"); |
4440 | | |
4441 | | // -ggnu-pubnames turns on gnu style pubnames in the backend. |
4442 | 47.7k | const auto *PubnamesArg = |
4443 | 47.7k | Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, |
4444 | 47.7k | options::OPT_gpubnames, options::OPT_gno_pubnames); |
4445 | 47.7k | if (DwarfFission != DwarfFissionKind::None || |
4446 | 47.7k | (47.7k PubnamesArg47.7k && checkDebugInfoOption(PubnamesArg, Args, D, TC)7 )) |
4447 | 54 | if (!PubnamesArg || |
4448 | 54 | (10 !PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames)10 && |
4449 | 10 | !PubnamesArg->getOption().matches(options::OPT_gno_pubnames)7 )) |
4450 | 46 | CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches( |
4451 | 2 | options::OPT_gpubnames) |
4452 | 46 | ? "-gpubnames"1 |
4453 | 46 | : "-ggnu-pubnames"45 ); |
4454 | 47.7k | const auto *SimpleTemplateNamesArg = |
4455 | 47.7k | Args.getLastArg(options::OPT_gsimple_template_names, |
4456 | 47.7k | options::OPT_gno_simple_template_names); |
4457 | 47.7k | bool ForwardTemplateParams = DebuggerTuning == llvm::DebuggerKind::SCE; |
4458 | 47.7k | if (SimpleTemplateNamesArg && |
4459 | 47.7k | checkDebugInfoOption(SimpleTemplateNamesArg, Args, D, TC)23 ) { |
4460 | 23 | const auto &Opt = SimpleTemplateNamesArg->getOption(); |
4461 | 23 | if (Opt.matches(options::OPT_gsimple_template_names)) { |
4462 | 13 | ForwardTemplateParams = true; |
4463 | 13 | CmdArgs.push_back("-gsimple-template-names=simple"); |
4464 | 13 | } |
4465 | 23 | } |
4466 | | |
4467 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_gsrc_hash_EQ)) { |
4468 | 3 | StringRef v = A->getValue(); |
4469 | 3 | CmdArgs.push_back(Args.MakeArgString("-gsrc-hash=" + v)); |
4470 | 3 | } |
4471 | | |
4472 | 47.7k | Args.addOptInFlag(CmdArgs, options::OPT_fdebug_ranges_base_address, |
4473 | 47.7k | options::OPT_fno_debug_ranges_base_address); |
4474 | | |
4475 | | // -gdwarf-aranges turns on the emission of the aranges section in the |
4476 | | // backend. |
4477 | | // Always enabled for SCE tuning. |
4478 | 47.7k | bool NeedAranges = DebuggerTuning == llvm::DebuggerKind::SCE; |
4479 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_gdwarf_aranges)) |
4480 | 1 | NeedAranges = checkDebugInfoOption(A, Args, D, TC) || NeedAranges0 ; |
4481 | 47.7k | if (NeedAranges) { |
4482 | 287 | CmdArgs.push_back("-mllvm"); |
4483 | 287 | CmdArgs.push_back("-generate-arange-section"); |
4484 | 287 | } |
4485 | | |
4486 | 47.7k | Args.addOptInFlag(CmdArgs, options::OPT_fforce_dwarf_frame, |
4487 | 47.7k | options::OPT_fno_force_dwarf_frame); |
4488 | | |
4489 | 47.7k | if (Args.hasFlag(options::OPT_fdebug_types_section, |
4490 | 47.7k | options::OPT_fno_debug_types_section, false)) { |
4491 | 4 | if (!(T.isOSBinFormatELF() || T.isOSBinFormatWasm()2 )) { |
4492 | 1 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
4493 | 1 | << Args.getLastArg(options::OPT_fdebug_types_section) |
4494 | 1 | ->getAsString(Args) |
4495 | 1 | << T.getTriple(); |
4496 | 3 | } else if (checkDebugInfoOption( |
4497 | 3 | Args.getLastArg(options::OPT_fdebug_types_section), Args, D, |
4498 | 3 | TC)) { |
4499 | 3 | CmdArgs.push_back("-mllvm"); |
4500 | 3 | CmdArgs.push_back("-generate-type-units"); |
4501 | 3 | } |
4502 | 4 | } |
4503 | | |
4504 | | // To avoid join/split of directory+filename, the integrated assembler prefers |
4505 | | // the directory form of .file on all DWARF versions. GNU as doesn't allow the |
4506 | | // form before DWARF v5. |
4507 | 47.7k | if (!Args.hasFlag(options::OPT_fdwarf_directory_asm, |
4508 | 47.7k | options::OPT_fno_dwarf_directory_asm, |
4509 | 47.7k | TC.useIntegratedAs() || EffectiveDWARFVersion >= 5390 )) |
4510 | 386 | CmdArgs.push_back("-fno-dwarf-directory-asm"); |
4511 | | |
4512 | | // Decide how to render forward declarations of template instantiations. |
4513 | | // SCE wants full descriptions, others just get them in the name. |
4514 | 47.7k | if (ForwardTemplateParams) |
4515 | 299 | CmdArgs.push_back("-debug-forward-template-params"); |
4516 | | |
4517 | | // Do we need to explicitly import anonymous namespaces into the parent |
4518 | | // scope? |
4519 | 47.7k | if (DebuggerTuning == llvm::DebuggerKind::SCE) |
4520 | 286 | CmdArgs.push_back("-dwarf-explicit-import"); |
4521 | | |
4522 | 47.7k | renderDwarfFormat(D, T, Args, CmdArgs, EffectiveDWARFVersion); |
4523 | 47.7k | RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC); |
4524 | | |
4525 | | // This controls whether or not we perform JustMyCode instrumentation. |
4526 | 47.7k | if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) { |
4527 | 13 | if (TC.getTriple().isOSBinFormatELF() || D.IsCLMode()5 ) { |
4528 | 11 | if (DebugInfoKind >= llvm::codegenoptions::DebugInfoConstructor) |
4529 | 3 | CmdArgs.push_back("-fjmc"); |
4530 | 8 | else if (D.IsCLMode()) |
4531 | 2 | D.Diag(clang::diag::warn_drv_jmc_requires_debuginfo) << "/JMC" |
4532 | 2 | << "'/Zi', '/Z7'"; |
4533 | 6 | else |
4534 | 6 | D.Diag(clang::diag::warn_drv_jmc_requires_debuginfo) << "-fjmc" |
4535 | 6 | << "-g"; |
4536 | 11 | } else { |
4537 | 2 | D.Diag(clang::diag::warn_drv_fjmc_for_elf_only); |
4538 | 2 | } |
4539 | 13 | } |
4540 | | |
4541 | | // Add in -fdebug-compilation-dir if necessary. |
4542 | 47.7k | const char *DebugCompilationDir = |
4543 | 47.7k | addDebugCompDirArg(Args, CmdArgs, D.getVFS()); |
4544 | | |
4545 | 47.7k | addDebugPrefixMapArg(D, TC, Args, CmdArgs); |
4546 | | |
4547 | | // Add the output path to the object file for CodeView debug infos. |
4548 | 47.7k | if (EmitCodeView && Output.isFilename()70 ) |
4549 | 69 | addDebugObjectName(Args, CmdArgs, DebugCompilationDir, |
4550 | 69 | Output.getFilename()); |
4551 | 47.7k | } |
4552 | | |
4553 | | static void ProcessVSRuntimeLibrary(const ArgList &Args, |
4554 | 726 | ArgStringList &CmdArgs) { |
4555 | 726 | unsigned RTOptionID = options::OPT__SLASH_MT; |
4556 | | |
4557 | 726 | if (Args.hasArg(options::OPT__SLASH_LDd)) |
4558 | | // The /LDd option implies /MTd. The dependent lib part can be overridden, |
4559 | | // but defining _DEBUG is sticky. |
4560 | 24 | RTOptionID = options::OPT__SLASH_MTd; |
4561 | | |
4562 | 726 | if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group)) |
4563 | 30 | RTOptionID = A->getOption().getID(); |
4564 | | |
4565 | 726 | if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) { |
4566 | 5 | RTOptionID = llvm::StringSwitch<unsigned>(A->getValue()) |
4567 | 5 | .Case("static", options::OPT__SLASH_MT) |
4568 | 5 | .Case("static_dbg", options::OPT__SLASH_MTd) |
4569 | 5 | .Case("dll", options::OPT__SLASH_MD) |
4570 | 5 | .Case("dll_dbg", options::OPT__SLASH_MDd) |
4571 | 5 | .Default(options::OPT__SLASH_MT); |
4572 | 5 | } |
4573 | | |
4574 | 726 | StringRef FlagForCRT; |
4575 | 726 | switch (RTOptionID) { |
4576 | 10 | case options::OPT__SLASH_MD: |
4577 | 10 | if (Args.hasArg(options::OPT__SLASH_LDd)) |
4578 | 2 | CmdArgs.push_back("-D_DEBUG"); |
4579 | 10 | CmdArgs.push_back("-D_MT"); |
4580 | 10 | CmdArgs.push_back("-D_DLL"); |
4581 | 10 | FlagForCRT = "--dependent-lib=msvcrt"; |
4582 | 10 | break; |
4583 | 8 | case options::OPT__SLASH_MDd: |
4584 | 8 | CmdArgs.push_back("-D_DEBUG"); |
4585 | 8 | CmdArgs.push_back("-D_MT"); |
4586 | 8 | CmdArgs.push_back("-D_DLL"); |
4587 | 8 | FlagForCRT = "--dependent-lib=msvcrtd"; |
4588 | 8 | break; |
4589 | 680 | case options::OPT__SLASH_MT: |
4590 | 680 | if (Args.hasArg(options::OPT__SLASH_LDd)) |
4591 | 2 | CmdArgs.push_back("-D_DEBUG"); |
4592 | 680 | CmdArgs.push_back("-D_MT"); |
4593 | 680 | CmdArgs.push_back("-flto-visibility-public-std"); |
4594 | 680 | FlagForCRT = "--dependent-lib=libcmt"; |
4595 | 680 | break; |
4596 | 24 | case options::OPT__SLASH_MTd: |
4597 | 24 | CmdArgs.push_back("-D_DEBUG"); |
4598 | 24 | CmdArgs.push_back("-D_MT"); |
4599 | 24 | CmdArgs.push_back("-flto-visibility-public-std"); |
4600 | 24 | FlagForCRT = "--dependent-lib=libcmtd"; |
4601 | 24 | break; |
4602 | 0 | default: |
4603 | 0 | llvm_unreachable("Unexpected option ID."); |
4604 | 726 | } |
4605 | | |
4606 | 723 | if (Args.hasArg(options::OPT_fms_omit_default_lib)) { |
4607 | 4 | CmdArgs.push_back("-D_VC_NODEFAULTLIB"); |
4608 | 719 | } else { |
4609 | 719 | CmdArgs.push_back(FlagForCRT.data()); |
4610 | | |
4611 | | // This provides POSIX compatibility (maps 'open' to '_open'), which most |
4612 | | // users want. The /Za flag to cl.exe turns this off, but it's not |
4613 | | // implemented in clang. |
4614 | 719 | CmdArgs.push_back("--dependent-lib=oldnames"); |
4615 | 719 | } |
4616 | 723 | } |
4617 | | |
4618 | | void Clang::ConstructJob(Compilation &C, const JobAction &JA, |
4619 | | const InputInfo &Output, const InputInfoList &Inputs, |
4620 | 47.7k | const ArgList &Args, const char *LinkingOutput) const { |
4621 | 47.7k | const auto &TC = getToolChain(); |
4622 | 47.7k | const llvm::Triple &RawTriple = TC.getTriple(); |
4623 | 47.7k | const llvm::Triple &Triple = TC.getEffectiveTriple(); |
4624 | 47.7k | const std::string &TripleStr = Triple.getTriple(); |
4625 | | |
4626 | 47.7k | bool KernelOrKext = |
4627 | 47.7k | Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); |
4628 | 47.7k | const Driver &D = TC.getDriver(); |
4629 | 47.7k | ArgStringList CmdArgs; |
4630 | | |
4631 | 47.7k | assert(Inputs.size() >= 1 && "Must have at least one input."); |
4632 | | // CUDA/HIP compilation may have multiple inputs (source file + results of |
4633 | | // device-side compilations). OpenMP device jobs also take the host IR as a |
4634 | | // second input. Module precompilation accepts a list of header files to |
4635 | | // include as part of the module. API extraction accepts a list of header |
4636 | | // files whose API information is emitted in the output. All other jobs are |
4637 | | // expected to have exactly one input. |
4638 | 47.7k | bool IsCuda = JA.isOffloading(Action::OFK_Cuda); |
4639 | 47.7k | bool IsCudaDevice = JA.isDeviceOffloading(Action::OFK_Cuda); |
4640 | 47.7k | bool IsHIP = JA.isOffloading(Action::OFK_HIP); |
4641 | 47.7k | bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP); |
4642 | 47.7k | bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); |
4643 | 47.7k | bool IsExtractAPI = isa<ExtractAPIJobAction>(JA); |
4644 | 47.7k | bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) || |
4645 | 47.7k | JA.isDeviceOffloading(Action::OFK_Host)519 ); |
4646 | 47.7k | bool IsHostOffloadingAction = |
4647 | 47.7k | JA.isHostOffloading(Action::OFK_OpenMP) || |
4648 | 47.7k | (47.7k JA.isHostOffloading(C.getActiveOffloadKinds())47.7k && |
4649 | 47.7k | Args.hasFlag(options::OPT_offload_new_driver, |
4650 | 338 | options::OPT_no_offload_new_driver, false)); |
4651 | | |
4652 | 47.7k | bool IsRDCMode = |
4653 | 47.7k | Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false); |
4654 | 47.7k | bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction); |
4655 | 47.7k | auto LTOMode = D.getLTOMode(IsDeviceOffloadAction); |
4656 | | |
4657 | | // Extract API doesn't have a main input file, so invent a fake one as a |
4658 | | // placeholder. |
4659 | 47.7k | InputInfo ExtractAPIPlaceholderInput(Inputs[0].getType(), "extract-api", |
4660 | 47.7k | "extract-api"); |
4661 | | |
4662 | 47.7k | const InputInfo &Input = |
4663 | 47.7k | IsExtractAPI ? ExtractAPIPlaceholderInput20 : Inputs[0]47.7k ; |
4664 | | |
4665 | 47.7k | InputInfoList ExtractAPIInputs; |
4666 | 47.7k | InputInfoList HostOffloadingInputs; |
4667 | 47.7k | const InputInfo *CudaDeviceInput = nullptr; |
4668 | 47.7k | const InputInfo *OpenMPDeviceInput = nullptr; |
4669 | 48.0k | for (const InputInfo &I : Inputs) { |
4670 | 48.0k | if (&I == &Input || I.getType() == types::TY_Nothing262 ) { |
4671 | | // This is the primary input or contains nothing. |
4672 | 47.7k | } else if (259 IsExtractAPI259 ) { |
4673 | 24 | auto ExpectedInputType = ExtractAPIPlaceholderInput.getType(); |
4674 | 24 | if (I.getType() != ExpectedInputType) { |
4675 | 1 | D.Diag(diag::err_drv_extract_api_wrong_kind) |
4676 | 1 | << I.getFilename() << types::getTypeName(I.getType()) |
4677 | 1 | << types::getTypeName(ExpectedInputType); |
4678 | 1 | } |
4679 | 24 | ExtractAPIInputs.push_back(I); |
4680 | 235 | } else if (IsHostOffloadingAction) { |
4681 | 10 | HostOffloadingInputs.push_back(I); |
4682 | 225 | } else if ((IsCuda || IsHIP186 ) && !CudaDeviceInput217 ) { |
4683 | 217 | CudaDeviceInput = &I; |
4684 | 217 | } else if (8 IsOpenMPDevice8 && !OpenMPDeviceInput9 ) { |
4685 | 9 | OpenMPDeviceInput = &I; |
4686 | 18.4E | } else { |
4687 | 18.4E | llvm_unreachable("unexpectedly given multiple inputs"); |
4688 | 18.4E | } |
4689 | 48.0k | } |
4690 | | |
4691 | 47.7k | const llvm::Triple *AuxTriple = |
4692 | 47.7k | (IsCuda || IsHIP47.6k ) ? TC.getAuxTriple()848 : nullptr46.9k ; |
4693 | 47.7k | bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment(); |
4694 | 47.7k | bool IsIAMCU = RawTriple.isOSIAMCU(); |
4695 | | |
4696 | | // Adjust IsWindowsXYZ for CUDA/HIP compilations. Even when compiling in |
4697 | | // device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not |
4698 | | // Windows), we need to pass Windows-specific flags to cc1. |
4699 | 47.7k | if (IsCuda || IsHIP47.6k ) |
4700 | 848 | IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment()510 ; |
4701 | | |
4702 | | // C++ is not supported for IAMCU. |
4703 | 47.7k | if (IsIAMCU && types::isCXX(Input.getType())9 ) |
4704 | 1 | D.Diag(diag::err_drv_clang_unsupported) << "C++ for IAMCU"; |
4705 | | |
4706 | | // Invoke ourselves in -cc1 mode. |
4707 | | // |
4708 | | // FIXME: Implement custom jobs for internal actions. |
4709 | 47.7k | CmdArgs.push_back("-cc1"); |
4710 | | |
4711 | | // Add the "effective" target triple. |
4712 | 47.7k | CmdArgs.push_back("-triple"); |
4713 | 47.7k | CmdArgs.push_back(Args.MakeArgString(TripleStr)); |
4714 | | |
4715 | 47.7k | if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) { |
4716 | 9 | DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args); |
4717 | 9 | Args.ClaimAllArgs(options::OPT_MJ); |
4718 | 47.7k | } else if (const Arg *GenCDBFragment = |
4719 | 47.7k | Args.getLastArg(options::OPT_gen_cdb_fragment_path)) { |
4720 | 4 | DumpCompilationDatabaseFragmentToDir(GenCDBFragment->getValue(), C, |
4721 | 4 | TripleStr, Output, Input, Args); |
4722 | 4 | Args.ClaimAllArgs(options::OPT_gen_cdb_fragment_path); |
4723 | 4 | } |
4724 | | |
4725 | 47.7k | if (IsCuda || IsHIP47.6k ) { |
4726 | | // We have to pass the triple of the host if compiling for a CUDA/HIP device |
4727 | | // and vice-versa. |
4728 | 848 | std::string NormalizedTriple; |
4729 | 848 | if (JA.isDeviceOffloading(Action::OFK_Cuda) || |
4730 | 848 | JA.isDeviceOffloading(Action::OFK_HIP)775 ) |
4731 | 510 | NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Host>() |
4732 | 510 | ->getTriple() |
4733 | 510 | .normalize(); |
4734 | 338 | else { |
4735 | | // Host-side compilation. |
4736 | 338 | NormalizedTriple = |
4737 | 338 | (IsCuda ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()70 |
4738 | 338 | : C.getSingleOffloadToolChain<Action::OFK_HIP>()268 ) |
4739 | 338 | ->getTriple() |
4740 | 338 | .normalize(); |
4741 | 338 | if (IsCuda) { |
4742 | | // We need to figure out which CUDA version we're compiling for, as that |
4743 | | // determines how we load and launch GPU kernels. |
4744 | 70 | auto *CTC = static_cast<const toolchains::CudaToolChain *>( |
4745 | 70 | C.getSingleOffloadToolChain<Action::OFK_Cuda>()); |
4746 | 70 | assert(CTC && "Expected valid CUDA Toolchain."); |
4747 | 70 | if (CTC && CTC->CudaInstallation.version() != CudaVersion::UNKNOWN) |
4748 | 19 | CmdArgs.push_back(Args.MakeArgString( |
4749 | 19 | Twine("-target-sdk-version=") + |
4750 | 19 | CudaVersionToString(CTC->CudaInstallation.version()))); |
4751 | | // Unsized function arguments used for variadics were introduced in |
4752 | | // CUDA-9.0. We still do not support generating code that actually uses |
4753 | | // variadic arguments yet, but we do need to allow parsing them as |
4754 | | // recent CUDA headers rely on that. |
4755 | | // https://github.com/llvm/llvm-project/issues/58410 |
4756 | 70 | if (CTC->CudaInstallation.version() >= CudaVersion::CUDA_90) |
4757 | 0 | CmdArgs.push_back("-fcuda-allow-variadic-functions"); |
4758 | 70 | } |
4759 | 338 | } |
4760 | 848 | CmdArgs.push_back("-aux-triple"); |
4761 | 848 | CmdArgs.push_back(Args.MakeArgString(NormalizedTriple)); |
4762 | | |
4763 | 848 | if (JA.isDeviceOffloading(Action::OFK_HIP) && |
4764 | 848 | getToolChain().getTriple().isAMDGPU()437 ) { |
4765 | | // Device side compilation printf |
4766 | 427 | if (Args.getLastArg(options::OPT_mprintf_kind_EQ)) { |
4767 | 6 | CmdArgs.push_back(Args.MakeArgString( |
4768 | 6 | "-mprintf-kind=" + |
4769 | 6 | Args.getLastArgValue(options::OPT_mprintf_kind_EQ))); |
4770 | | // Force compiler error on invalid conversion specifiers |
4771 | 6 | CmdArgs.push_back( |
4772 | 6 | Args.MakeArgString("-Werror=format-invalid-specifier")); |
4773 | 6 | } |
4774 | 427 | } |
4775 | 848 | } |
4776 | | |
4777 | | // Unconditionally claim the printf option now to avoid unused diagnostic. |
4778 | 47.7k | if (const Arg *PF = Args.getLastArg(options::OPT_mprintf_kind_EQ)) |
4779 | 12 | PF->claim(); |
4780 | | |
4781 | 47.7k | if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) { |
4782 | 14 | CmdArgs.push_back("-fsycl-is-device"); |
4783 | | |
4784 | 14 | if (Arg *A = Args.getLastArg(options::OPT_sycl_std_EQ)) { |
4785 | 6 | A->render(Args, CmdArgs); |
4786 | 8 | } else { |
4787 | | // Ensure the default version in SYCL mode is 2020. |
4788 | 8 | CmdArgs.push_back("-sycl-std=2020"); |
4789 | 8 | } |
4790 | 14 | } |
4791 | | |
4792 | 47.7k | if (IsOpenMPDevice) { |
4793 | | // We have to pass the triple of the host if compiling for an OpenMP device. |
4794 | 9 | std::string NormalizedTriple = |
4795 | 9 | C.getSingleOffloadToolChain<Action::OFK_Host>() |
4796 | 9 | ->getTriple() |
4797 | 9 | .normalize(); |
4798 | 9 | CmdArgs.push_back("-aux-triple"); |
4799 | 9 | CmdArgs.push_back(Args.MakeArgString(NormalizedTriple)); |
4800 | 9 | } |
4801 | | |
4802 | 47.7k | if (Triple.isOSWindows() && (8.76k Triple.getArch() == llvm::Triple::arm8.76k || |
4803 | 8.76k | Triple.getArch() == llvm::Triple::thumb)) { |
4804 | 92 | unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 40 : 6; |
4805 | 92 | unsigned Version = 0; |
4806 | 92 | bool Failure = |
4807 | 92 | Triple.getArchName().substr(Offset).consumeInteger(10, Version); |
4808 | 92 | if (Failure || Version < 7) |
4809 | 3 | D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName() |
4810 | 3 | << TripleStr; |
4811 | 92 | } |
4812 | | |
4813 | | // Push all default warning arguments that are specific to |
4814 | | // the given target. These come before user provided warning options |
4815 | | // are provided. |
4816 | 47.7k | TC.addClangWarningOptions(CmdArgs); |
4817 | | |
4818 | | // FIXME: Subclass ToolChain for SPIR and move this to addClangWarningOptions. |
4819 | 47.7k | if (Triple.isSPIR() || Triple.isSPIRV()47.7k ) |
4820 | 49 | CmdArgs.push_back("-Wspir-compat"); |
4821 | | |
4822 | | // Select the appropriate action. |
4823 | 47.7k | RewriteKind rewriteKind = RK_None; |
4824 | | |
4825 | 47.7k | bool UnifiedLTO = false; |
4826 | 47.7k | if (IsUsingLTO) { |
4827 | 294 | UnifiedLTO = Args.hasFlag(options::OPT_funified_lto, |
4828 | 294 | options::OPT_fno_unified_lto, Triple.isPS()); |
4829 | 294 | if (UnifiedLTO) |
4830 | 29 | CmdArgs.push_back("-funified-lto"); |
4831 | 294 | } |
4832 | | |
4833 | | // If CollectArgsForIntegratedAssembler() isn't called below, claim the args |
4834 | | // it claims when not running an assembler. Otherwise, clang would emit |
4835 | | // "argument unused" warnings for assembler flags when e.g. adding "-E" to |
4836 | | // flags while debugging something. That'd be somewhat inconvenient, and it's |
4837 | | // also inconsistent with most other flags -- we don't warn on |
4838 | | // -ffunction-sections not being used in -E mode either for example, even |
4839 | | // though it's not really used either. |
4840 | 47.7k | if (!isa<AssembleJobAction>(JA)) { |
4841 | | // The args claimed here should match the args used in |
4842 | | // CollectArgsForIntegratedAssembler(). |
4843 | 36.5k | if (TC.useIntegratedAs()) { |
4844 | 36.1k | Args.ClaimAllArgs(options::OPT_mrelax_all); |
4845 | 36.1k | Args.ClaimAllArgs(options::OPT_mno_relax_all); |
4846 | 36.1k | Args.ClaimAllArgs(options::OPT_mincremental_linker_compatible); |
4847 | 36.1k | Args.ClaimAllArgs(options::OPT_mno_incremental_linker_compatible); |
4848 | 36.1k | switch (C.getDefaultToolChain().getArch()) { |
4849 | 570 | case llvm::Triple::arm: |
4850 | 571 | case llvm::Triple::armeb: |
4851 | 587 | case llvm::Triple::thumb: |
4852 | 588 | case llvm::Triple::thumbeb: |
4853 | 588 | Args.ClaimAllArgs(options::OPT_mimplicit_it_EQ); |
4854 | 588 | break; |
4855 | 35.5k | default: |
4856 | 35.5k | break; |
4857 | 36.1k | } |
4858 | 36.1k | } |
4859 | 36.5k | Args.ClaimAllArgs(options::OPT_Wa_COMMA); |
4860 | 36.5k | Args.ClaimAllArgs(options::OPT_Xassembler); |
4861 | 36.5k | Args.ClaimAllArgs(options::OPT_femit_dwarf_unwind_EQ); |
4862 | 36.5k | } |
4863 | | |
4864 | 47.7k | if (isa<AnalyzeJobAction>(JA)) { |
4865 | 56 | assert(JA.getType() == types::TY_Plist && "Invalid output type."); |
4866 | 56 | CmdArgs.push_back("-analyze"); |
4867 | 47.7k | } else if (isa<MigrateJobAction>(JA)) { |
4868 | 0 | CmdArgs.push_back("-migrate"); |
4869 | 47.7k | } else if (isa<PreprocessJobAction>(JA)) { |
4870 | 2.03k | if (Output.getType() == types::TY_Dependencies) |
4871 | 14 | CmdArgs.push_back("-Eonly"); |
4872 | 2.02k | else { |
4873 | 2.02k | CmdArgs.push_back("-E"); |
4874 | 2.02k | if (Args.hasArg(options::OPT_rewrite_objc) && |
4875 | 2.02k | !Args.hasArg(options::OPT_g_Group)5 ) |
4876 | 4 | CmdArgs.push_back("-P"); |
4877 | 2.02k | else if (JA.getType() == types::TY_PP_CXXHeaderUnit) |
4878 | 1 | CmdArgs.push_back("-fdirectives-only"); |
4879 | 2.02k | } |
4880 | 45.6k | } else if (isa<AssembleJobAction>(JA)) { |
4881 | 11.2k | CmdArgs.push_back("-emit-obj"); |
4882 | | |
4883 | 11.2k | CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D); |
4884 | | |
4885 | | // Also ignore explicit -force_cpusubtype_ALL option. |
4886 | 11.2k | (void)Args.hasArg(options::OPT_force__cpusubtype__ALL); |
4887 | 34.4k | } else if (isa<PrecompileJobAction>(JA)) { |
4888 | 120 | if (JA.getType() == types::TY_Nothing) |
4889 | 37 | CmdArgs.push_back("-fsyntax-only"); |
4890 | 83 | else if (JA.getType() == types::TY_ModuleFile) |
4891 | 27 | CmdArgs.push_back("-emit-module-interface"); |
4892 | 56 | else if (JA.getType() == types::TY_HeaderUnit) |
4893 | 9 | CmdArgs.push_back("-emit-header-unit"); |
4894 | 47 | else |
4895 | 47 | CmdArgs.push_back("-emit-pch"); |
4896 | 34.3k | } else if (isa<VerifyPCHJobAction>(JA)) { |
4897 | 2 | CmdArgs.push_back("-verify-pch"); |
4898 | 34.3k | } else if (isa<ExtractAPIJobAction>(JA)) { |
4899 | 20 | assert(JA.getType() == types::TY_API_INFO && |
4900 | 20 | "Extract API actions must generate a API information."); |
4901 | 20 | CmdArgs.push_back("-extract-api"); |
4902 | 20 | if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ)) |
4903 | 7 | ProductNameArg->render(Args, CmdArgs); |
4904 | 20 | if (Arg *ExtractAPIIgnoresFileArg = |
4905 | 20 | Args.getLastArg(options::OPT_extract_api_ignores_EQ)) |
4906 | 1 | ExtractAPIIgnoresFileArg->render(Args, CmdArgs); |
4907 | 34.3k | } else { |
4908 | 34.3k | assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) && |
4909 | 34.3k | "Invalid action for clang tool."); |
4910 | 34.3k | if (JA.getType() == types::TY_Nothing) { |
4911 | 31.7k | CmdArgs.push_back("-fsyntax-only"); |
4912 | 31.7k | } else if (2.59k JA.getType() == types::TY_LLVM_IR2.59k || |
4913 | 2.59k | JA.getType() == types::TY_LTO_IR1.92k ) { |
4914 | 713 | CmdArgs.push_back("-emit-llvm"); |
4915 | 1.88k | } else if (JA.getType() == types::TY_LLVM_BC || |
4916 | 1.88k | JA.getType() == types::TY_LTO_BC1.61k ) { |
4917 | | // Emit textual llvm IR for AMDGPU offloading for -emit-llvm -S |
4918 | 500 | if (Triple.isAMDGCN() && IsOpenMPDevice141 && Args.hasArg(options::OPT_S)9 && |
4919 | 500 | Args.hasArg(options::OPT_emit_llvm)1 ) { |
4920 | 1 | CmdArgs.push_back("-emit-llvm"); |
4921 | 499 | } else { |
4922 | 499 | CmdArgs.push_back("-emit-llvm-bc"); |
4923 | 499 | } |
4924 | 1.38k | } else if (JA.getType() == types::TY_IFS || |
4925 | 1.38k | JA.getType() == types::TY_IFS_CPP1.37k ) { |
4926 | 26 | StringRef ArgStr = |
4927 | 26 | Args.hasArg(options::OPT_interface_stub_version_EQ) |
4928 | 26 | ? Args.getLastArgValue(options::OPT_interface_stub_version_EQ)8 |
4929 | 26 | : "ifs-v1"18 ; |
4930 | 26 | CmdArgs.push_back("-emit-interface-stubs"); |
4931 | 26 | CmdArgs.push_back( |
4932 | 26 | Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str())); |
4933 | 1.35k | } else if (JA.getType() == types::TY_PP_Asm) { |
4934 | 1.32k | CmdArgs.push_back("-S"); |
4935 | 1.32k | } else if (31 JA.getType() == types::TY_AST31 ) { |
4936 | 15 | CmdArgs.push_back("-emit-pch"); |
4937 | 16 | } else if (JA.getType() == types::TY_ModuleFile) { |
4938 | 2 | CmdArgs.push_back("-module-file-info"); |
4939 | 14 | } else if (JA.getType() == types::TY_RewrittenObjC) { |
4940 | 5 | CmdArgs.push_back("-rewrite-objc"); |
4941 | 5 | rewriteKind = RK_NonFragile; |
4942 | 9 | } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { |
4943 | 3 | CmdArgs.push_back("-rewrite-objc"); |
4944 | 3 | rewriteKind = RK_Fragile; |
4945 | 6 | } else { |
4946 | 6 | assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!"); |
4947 | 6 | } |
4948 | | |
4949 | | // Preserve use-list order by default when emitting bitcode, so that |
4950 | | // loading the bitcode up in 'opt' or 'llc' and running passes gives the |
4951 | | // same result as running passes here. For LTO, we don't need to preserve |
4952 | | // the use-list order, since serialization to bitcode is part of the flow. |
4953 | 34.3k | if (JA.getType() == types::TY_LLVM_BC) |
4954 | 264 | CmdArgs.push_back("-emit-llvm-uselists"); |
4955 | | |
4956 | 34.3k | if (IsUsingLTO) { |
4957 | 288 | if (IsDeviceOffloadAction && !JA.isDeviceOffloading(Action::OFK_OpenMP)2 && |
4958 | 288 | !Args.hasFlag(options::OPT_offload_new_driver, |
4959 | 2 | options::OPT_no_offload_new_driver, false) && |
4960 | 288 | !Triple.isAMDGPU()2 ) { |
4961 | 0 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
4962 | 0 | << Args.getLastArg(options::OPT_foffload_lto, |
4963 | 0 | options::OPT_foffload_lto_EQ) |
4964 | 0 | ->getAsString(Args) |
4965 | 0 | << Triple.getTriple(); |
4966 | 288 | } else if (Triple.isNVPTX() && !IsRDCMode0 && |
4967 | 288 | JA.isDeviceOffloading(Action::OFK_Cuda)0 ) { |
4968 | 0 | D.Diag(diag::err_drv_unsupported_opt_for_language_mode) |
4969 | 0 | << Args.getLastArg(options::OPT_foffload_lto, |
4970 | 0 | options::OPT_foffload_lto_EQ) |
4971 | 0 | ->getAsString(Args) |
4972 | 0 | << "-fno-gpu-rdc"; |
4973 | 288 | } else { |
4974 | 288 | assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin); |
4975 | 288 | CmdArgs.push_back(Args.MakeArgString( |
4976 | 288 | Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin"76 : "full"212 ))); |
4977 | | // PS4 uses the legacy LTO API, which does not support some of the |
4978 | | // features enabled by -flto-unit. |
4979 | 288 | if (!RawTriple.isPS4() || |
4980 | 288 | (D.getLTOMode() == LTOK_Full)16 || !UnifiedLTO8 ) |
4981 | 281 | CmdArgs.push_back("-flto-unit"); |
4982 | 288 | } |
4983 | 288 | } |
4984 | 34.3k | } |
4985 | | |
4986 | 47.7k | Args.AddLastArg(CmdArgs, options::OPT_dumpdir); |
4987 | | |
4988 | 47.7k | if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) { |
4989 | 30 | if (!types::isLLVMIR(Input.getType())) |
4990 | 1 | D.Diag(diag::err_drv_arg_requires_bitcode_input) << A->getAsString(Args); |
4991 | 30 | Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ); |
4992 | 30 | } |
4993 | | |
4994 | 47.7k | if (Args.getLastArg(options::OPT_fthin_link_bitcode_EQ)) |
4995 | 1 | Args.AddLastArg(CmdArgs, options::OPT_fthin_link_bitcode_EQ); |
4996 | | |
4997 | 47.7k | if (Args.getLastArg(options::OPT_save_temps_EQ)) |
4998 | 255 | Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ); |
4999 | | |
5000 | 47.7k | auto *MemProfArg = Args.getLastArg(options::OPT_fmemory_profile, |
5001 | 47.7k | options::OPT_fmemory_profile_EQ, |
5002 | 47.7k | options::OPT_fno_memory_profile); |
5003 | 47.7k | if (MemProfArg && |
5004 | 47.7k | !MemProfArg->getOption().matches(options::OPT_fno_memory_profile)7 ) |
5005 | 5 | MemProfArg->render(Args, CmdArgs); |
5006 | | |
5007 | 47.7k | if (auto *MemProfUseArg = |
5008 | 47.7k | Args.getLastArg(options::OPT_fmemory_profile_use_EQ)) { |
5009 | 3 | if (MemProfArg) |
5010 | 1 | D.Diag(diag::err_drv_argument_not_allowed_with) |
5011 | 1 | << MemProfUseArg->getAsString(Args) << MemProfArg->getAsString(Args); |
5012 | 3 | if (auto *PGOInstrArg = Args.getLastArg(options::OPT_fprofile_generate, |
5013 | 3 | options::OPT_fprofile_generate_EQ)) |
5014 | 1 | D.Diag(diag::err_drv_argument_not_allowed_with) |
5015 | 1 | << MemProfUseArg->getAsString(Args) << PGOInstrArg->getAsString(Args); |
5016 | 3 | MemProfUseArg->render(Args, CmdArgs); |
5017 | 3 | } |
5018 | | |
5019 | | // Embed-bitcode option. |
5020 | | // Only white-listed flags below are allowed to be embedded. |
5021 | 47.7k | if (C.getDriver().embedBitcodeInObject() && !IsUsingLTO32 && |
5022 | 47.7k | (27 isa<BackendJobAction>(JA)27 || isa<AssembleJobAction>(JA)26 )) { |
5023 | | // Add flags implied by -fembed-bitcode. |
5024 | 12 | Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ); |
5025 | | // Disable all llvm IR level optimizations. |
5026 | 12 | CmdArgs.push_back("-disable-llvm-passes"); |
5027 | | |
5028 | | // Render target options. |
5029 | 12 | TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind()); |
5030 | | |
5031 | | // reject options that shouldn't be supported in bitcode |
5032 | | // also reject kernel/kext |
5033 | 12 | static const constexpr unsigned kBitcodeOptionIgnorelist[] = { |
5034 | 12 | options::OPT_mkernel, |
5035 | 12 | options::OPT_fapple_kext, |
5036 | 12 | options::OPT_ffunction_sections, |
5037 | 12 | options::OPT_fno_function_sections, |
5038 | 12 | options::OPT_fdata_sections, |
5039 | 12 | options::OPT_fno_data_sections, |
5040 | 12 | options::OPT_fbasic_block_sections_EQ, |
5041 | 12 |
|