Bug Summary

File:build/source/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Warning:line 279, column 15
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name AArch64.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/Driver -I /build/source/clang/lib/Driver -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -source-date-epoch 1668078801 -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-11-10-135928-647445-1 -x c++ /build/source/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
1//===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- 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 "AArch64.h"
10#include "../CommonArgs.h"
11#include "clang/Driver/Driver.h"
12#include "clang/Driver/DriverDiagnostic.h"
13#include "clang/Driver/Options.h"
14#include "llvm/Option/ArgList.h"
15#include "llvm/Support/AArch64TargetParser.h"
16#include "llvm/Support/TargetParser.h"
17#include "llvm/Support/Host.h"
18
19using namespace clang::driver;
20using namespace clang::driver::tools;
21using namespace clang;
22using namespace llvm::opt;
23
24/// \returns true if the given triple can determine the default CPU type even
25/// if -arch is not specified.
26static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
27 return Triple.isOSDarwin();
28}
29
30/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
31/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
32/// provided, or to nullptr otherwise.
33std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
34 const llvm::Triple &Triple, Arg *&A) {
35 std::string CPU;
36 // If we have -mcpu, use that.
37 if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
38 StringRef Mcpu = A->getValue();
39 CPU = Mcpu.split("+").first.lower();
40 }
41
42 CPU = llvm::AArch64::resolveCPUAlias(CPU);
43
44 // Handle CPU name is 'native'.
45 if (CPU == "native")
46 return std::string(llvm::sys::getHostCPUName());
47
48 if (CPU.size())
49 return CPU;
50
51 if (Triple.isTargetMachineMac() &&
52 Triple.getArch() == llvm::Triple::aarch64) {
53 // Apple Silicon macs default to M1 CPUs.
54 return "apple-m1";
55 }
56
57 // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
58 if (Triple.isArm64e())
59 return "apple-a12";
60
61 // Make sure we pick the appropriate Apple CPU if -arch is used or when
62 // targetting a Darwin OS.
63 if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
64 return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
65 : "apple-a7";
66
67 return "generic";
68}
69
70// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
71static bool DecodeAArch64Features(const Driver &D, StringRef text,
72 std::vector<StringRef> &Features,
73 llvm::AArch64::ArchKind ArchKind) {
74 SmallVector<StringRef, 8> Split;
75 text.split(Split, StringRef("+"), -1, false);
76
77 for (StringRef Feature : Split) {
78 StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
79 if (!FeatureName.empty())
80 Features.push_back(FeatureName);
81 else if (Feature == "neon" || Feature == "noneon")
82 D.Diag(clang::diag::err_drv_no_neon_modifier);
83 else
84 return false;
85
86 if (Feature == "sve2")
87 Features.push_back("+sve");
88 else if (Feature == "sve2-bitperm" || Feature == "sve2-sha3" ||
89 Feature == "sve2-aes" || Feature == "sve2-sm4") {
90 Features.push_back("+sve");
91 Features.push_back("+sve2");
92 } else if (Feature == "nosve") {
93 Features.push_back("-sve2");
94 Features.push_back("-sve2-bitperm");
95 Features.push_back("-sve2-sha3");
96 Features.push_back("-sve2-aes");
97 Features.push_back("-sve2-sm4");
98 } else if (Feature == "nosve2") {
99 Features.push_back("-sve2-bitperm");
100 Features.push_back("-sve2-sha3");
101 Features.push_back("-sve2-aes");
102 Features.push_back("-sve2-sm4");
103 }
104
105 // +sve implies +f32mm if the base architecture is >= v8.6A (except v9A)
106 // It isn't the case in general that sve implies both f64mm and f32mm
107 if ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A ||
108 ArchKind == llvm::AArch64::ArchKind::ARMV8_7A ||
109 ArchKind == llvm::AArch64::ArchKind::ARMV8_8A ||
110 ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
111 ArchKind == llvm::AArch64::ArchKind::ARMV9_2A ||
112 ArchKind == llvm::AArch64::ArchKind::ARMV9_3A) &&
113 Feature == "sve")
114 Features.push_back("+f32mm");
115 }
116 return true;
117}
118
119// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
120// decode CPU and feature.
121static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
122 std::vector<StringRef> &Features) {
123 std::pair<StringRef, StringRef> Split = Mcpu.split("+");
124 CPU = Split.first;
125 llvm::AArch64::ArchKind ArchKind = llvm::AArch64::ArchKind::ARMV8A;
126
127 CPU = llvm::AArch64::resolveCPUAlias(CPU);
128
129 if (CPU == "native")
130 CPU = llvm::sys::getHostCPUName();
131
132 if (CPU == "generic") {
133 Features.push_back("+neon");
134 } else {
135 ArchKind = llvm::AArch64::parseCPUArch(CPU);
136 if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
137 return false;
138
139 uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
140 if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
141 return false;
142 }
143
144 if (Split.second.size() &&
145 !DecodeAArch64Features(D, Split.second, Features, ArchKind))
146 return false;
147
148 return true;
149}
150
151static bool
152getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
153 const ArgList &Args,
154 std::vector<StringRef> &Features) {
155 std::string MarchLowerCase = March.lower();
156 std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
157
158 llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
159 if (Split.first == "native")
13
Assuming the condition is false
160 ArchKind = llvm::AArch64::getCPUArchKind(llvm::sys::getHostCPUName().str());
161 if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
14
Assuming 'ArchKind' is not equal to INVALID
162 !llvm::AArch64::getArchFeatures(ArchKind, Features))
15
Assuming the condition is false
163 return false;
164
165 // Enable SVE2 by default on Armv9-A.
166 // It can still be disabled if +nosve2 is present.
167 // We must do this early so that DecodeAArch64Features has the correct state
168 if ((ArchKind == llvm::AArch64::ArchKind::ARMV9A ||
16
Assuming 'ArchKind' is not equal to ARMV9A
169 ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
17
Assuming 'ArchKind' is not equal to ARMV9_1A
170 ArchKind == llvm::AArch64::ArchKind::ARMV9_2A)) {
18
Assuming 'ArchKind' is not equal to ARMV9_2A
171 Features.push_back("+sve");
172 Features.push_back("+sve2");
173 }
174
175 if ((Split.second.size() &&
19
Assuming the condition is true
20
Taking true branch
176 !DecodeAArch64Features(D, Split.second, Features, ArchKind)))
177 return false;
21
Returning zero, which participates in a condition later
178
179 return true;
180}
181
182static bool
183getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
184 const ArgList &Args,
185 std::vector<StringRef> &Features) {
186 StringRef CPU;
187 std::string McpuLowerCase = Mcpu.lower();
188 if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
189 return false;
190
191 return true;
192}
193
194static bool
195getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
196 const ArgList &Args,
197 std::vector<StringRef> &Features) {
198 std::string MtuneLowerCase = Mtune.lower();
199 // Check CPU name is valid
200 std::vector<StringRef> MtuneFeatures;
201 StringRef Tune;
202 if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, MtuneFeatures))
203 return false;
204
205 // Handle CPU name is 'native'.
206 if (MtuneLowerCase == "native")
207 MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
208 if (MtuneLowerCase == "cyclone" ||
209 StringRef(MtuneLowerCase).startswith("apple")) {
210 Features.push_back("+zcm");
211 Features.push_back("+zcz");
212 }
213 return true;
214}
215
216static bool
217getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
218 const ArgList &Args,
219 std::vector<StringRef> &Features) {
220 StringRef CPU;
221 std::vector<StringRef> DecodedFeature;
222 std::string McpuLowerCase = Mcpu.lower();
223 if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
224 return false;
225
226 return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
227}
228
229void aarch64::getAArch64TargetFeatures(const Driver &D,
230 const llvm::Triple &Triple,
231 const ArgList &Args,
232 std::vector<StringRef> &Features,
233 bool ForAS) {
234 Arg *A;
235 bool success = true;
236 // Enable NEON by default.
237 Features.push_back("+neon");
238 llvm::StringRef WaMArch;
239 if (ForAS)
1
Assuming 'ForAS' is false
2
Taking false branch
240 for (const auto *A :
241 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
242 for (StringRef Value : A->getValues())
243 if (Value.startswith("-march="))
244 WaMArch = Value.substr(7);
245 // Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
246 // "-Xassembler -march" is detected. Otherwise it may return false
247 // and causes Clang to error out.
248 if (!WaMArch.empty())
3
Assuming the condition is false
4
Taking false branch
249 success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Features);
250 else if ((A = Args.getLastArg(options::OPT_march_EQ)))
5
Assuming 'A' is null
6
Taking false branch
251 success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
252 else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
7
Value assigned to 'A'
8
Assuming 'A' is null
9
Assuming pointer value is null
253 success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
254 else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
10
Assuming the condition is false
11
Taking false branch
255 success = getAArch64ArchFeaturesFromMcpu(
256 D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
257 else
258 // Default to 'A' profile if the architecture is not specified.
259 success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Features);
12
Calling 'getAArch64ArchFeaturesFromMarch'
22
Returning from 'getAArch64ArchFeaturesFromMarch'
260
261 if (success
22.1
'success' is false
&& (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
262 success =
263 getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
264 else if (success
22.2
'success' is false
&& (A = Args.getLastArg(options::OPT_mcpu_EQ)))
265 success =
266 getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
267 else if (success
22.3
'success' is false
&&
268 (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
269 success = getAArch64MicroArchFeaturesFromMcpu(
270 D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
271
272 if (!success
22.4
'success' is false
) {
23
Taking true branch
273 auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
274 // If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
275 // while 'A' is uninitialized. Only dereference 'A' in the other case.
276 if (!WaMArch.empty())
24
Assuming the condition is false
25
Taking false branch
277 Diag << "-march=" << WaMArch;
278 else
279 Diag << A->getSpelling() << A->getValue();
26
Called C++ object pointer is null
280 }
281
282 if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
283 Features.push_back("-fp-armv8");
284 Features.push_back("-crypto");
285 Features.push_back("-neon");
286 }
287
288 if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
289 StringRef Mtp = A->getValue();
290 if (Mtp == "el3")
291 Features.push_back("+tpidr-el3");
292 else if (Mtp == "el2")
293 Features.push_back("+tpidr-el2");
294 else if (Mtp == "el1")
295 Features.push_back("+tpidr-el1");
296 else if (Mtp != "el0")
297 D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
298 }
299
300 // Enable/disable straight line speculation hardening.
301 if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
302 StringRef Scope = A->getValue();
303 bool EnableRetBr = false;
304 bool EnableBlr = false;
305 bool DisableComdat = false;
306 if (Scope != "none") {
307 SmallVector<StringRef, 4> Opts;
308 Scope.split(Opts, ",");
309 for (auto Opt : Opts) {
310 Opt = Opt.trim();
311 if (Opt == "all") {
312 EnableBlr = true;
313 EnableRetBr = true;
314 continue;
315 }
316 if (Opt == "retbr") {
317 EnableRetBr = true;
318 continue;
319 }
320 if (Opt == "blr") {
321 EnableBlr = true;
322 continue;
323 }
324 if (Opt == "comdat") {
325 DisableComdat = false;
326 continue;
327 }
328 if (Opt == "nocomdat") {
329 DisableComdat = true;
330 continue;
331 }
332 D.Diag(diag::err_drv_unsupported_option_argument)
333 << A->getSpelling() << Scope;
334 break;
335 }
336 }
337
338 if (EnableRetBr)
339 Features.push_back("+harden-sls-retbr");
340 if (EnableBlr)
341 Features.push_back("+harden-sls-blr");
342 if (DisableComdat) {
343 Features.push_back("+harden-sls-nocomdat");
344 }
345 }
346
347 // En/disable crc
348 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
349 if (A->getOption().matches(options::OPT_mcrc))
350 Features.push_back("+crc");
351 else
352 Features.push_back("-crc");
353 }
354
355 int V8Version = -1;
356 int V9Version = -1;
357 bool HasNoSM4 = false;
358 bool HasNoSHA3 = false;
359 bool HasNoSHA2 = false;
360 bool HasNoAES = false;
361 bool HasSM4 = false;
362 bool HasSHA3 = false;
363 bool HasSHA2 = false;
364 bool HasAES = false;
365 bool HasCrypto = false;
366 bool HasNoCrypto = false;
367 int FullFP16Pos = -1;
368 int NoFullFP16Pos = -1;
369 int FP16FMLPos = -1;
370 int NoFP16FMLPos = -1;
371 int ArchFeatPos = -1;
372
373 for (auto I = Features.begin(), E = Features.end(); I != E; I++) {
374 if (*I == "+v8a") V8Version = 0;
375 else if (*I == "+v8.1a") V8Version = 1;
376 else if (*I == "+v8.2a") V8Version = 2;
377 else if (*I == "+v8.3a") V8Version = 3;
378 else if (*I == "+v8.4a") V8Version = 4;
379 else if (*I == "+v8.5a") V8Version = 5;
380 else if (*I == "+v8.6a") V8Version = 6;
381 else if (*I == "+v8.7a") V8Version = 7;
382 else if (*I == "+v8.8a") V8Version = 8;
383 else if (*I == "+v8.9a") V8Version = 9;
384 else if (*I == "+v9a") V9Version = 0;
385 else if (*I == "+v9.1a") V9Version = 1;
386 else if (*I == "+v9.2a") V9Version = 2;
387 else if (*I == "+v9.3a") V9Version = 3;
388 else if (*I == "+v9.4a") V9Version = 4;
389 else if (*I == "+sm4") HasSM4 = true;
390 else if (*I == "+sha3") HasSHA3 = true;
391 else if (*I == "+sha2") HasSHA2 = true;
392 else if (*I == "+aes") HasAES = true;
393 else if (*I == "-sm4") HasNoSM4 = true;
394 else if (*I == "-sha3") HasNoSHA3 = true;
395 else if (*I == "-sha2") HasNoSHA2 = true;
396 else if (*I == "-aes") HasNoAES = true;
397 else if (*I == "+fp16fml") FP16FMLPos = I - Features.begin();
398 else if (*I == "-fp16fml") NoFP16FMLPos = I - Features.begin();
399 else if (*I == "-fullfp16") NoFullFP16Pos = I - Features.begin();
400 else if (*I == "+fullfp16") FullFP16Pos = I - Features.begin();
401 // Whichever option comes after (right-most option) will win
402 else if (*I == "+crypto") {
403 HasCrypto = true;
404 HasNoCrypto = false;
405 } else if (*I == "-crypto") {
406 HasCrypto = false;
407 HasNoCrypto = true;
408 }
409 // Register the iterator position if this is an architecture feature
410 if (ArchFeatPos == -1 && (V8Version != -1 || V9Version != -1))
411 ArchFeatPos = I - Features.begin();
412 }
413
414 // Handle (arch-dependent) fp16fml/fullfp16 relationship.
415 // FIXME: this fp16fml option handling will be reimplemented after the
416 // TargetParser rewrite.
417 if (V8Version >= 4) {
418 // "-fullfp16" "+fullfp16" && "+fp16fml" "+fullfp16" && no "+fullfp16" "-fp16fml" = "+fp16fml"
419 if (FullFP16Pos > NoFullFP16Pos && FullFP16Pos > FP16FMLPos && FullFP16Pos > NoFP16FMLPos)
420 // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
421 // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
422 Features.push_back("+fp16fml");
423 else
424 goto fp16_fml_fallthrough;
425 } else {
426fp16_fml_fallthrough:
427 // In both of these cases, putting the 'other' feature on the end of the vector will
428 // result in the same effect as placing it immediately after the current feature.
429 // "+fp16fml" "-fullfp16" = "-fp16fml"
430 if (NoFullFP16Pos > FP16FMLPos)
431 Features.push_back("-fp16fml");
432 // "-fullfp16" "+fp16fml" = "+fullfp16"
433 else if (NoFullFP16Pos < FP16FMLPos)
434 Features.push_back("+fullfp16");
435 }
436
437 // FIXME: this needs reimplementation too after the TargetParser rewrite
438 //
439 // Context sensitive meaning of Crypto:
440 // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
441 // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
442 if (V8Version >= 4 || V9Version >= 0) {
443 if (HasCrypto && !HasNoCrypto) {
444 // Check if we have NOT disabled an algorithm with something like:
445 // +crypto, -algorithm
446 // And if "-algorithm" does not occur, we enable that crypto algorithm.
447 if (!HasNoSM4)
448 Features.push_back("+sm4");
449 if (!HasNoSHA3)
450 Features.push_back("+sha3");
451 if (!HasNoSHA2)
452 Features.push_back("+sha2");
453 if (!HasNoAES)
454 Features.push_back("+aes");
455 } else if (HasNoCrypto) {
456 // Check if we have NOT enabled a crypto algorithm with something like:
457 // -crypto, +algorithm
458 // And if "+algorithm" does not occur, we disable that crypto algorithm.
459 if (!HasSM4)
460 Features.push_back("-sm4");
461 if (!HasSHA3)
462 Features.push_back("-sha3");
463 if (!HasSHA2)
464 Features.push_back("-sha2");
465 if (!HasAES)
466 Features.push_back("-aes");
467 }
468 } else {
469 if (HasCrypto && !HasNoCrypto) {
470 if (!HasNoSHA2)
471 Features.push_back("+sha2");
472 if (!HasNoAES)
473 Features.push_back("+aes");
474 } else if (HasNoCrypto) {
475 if (!HasSHA2)
476 Features.push_back("-sha2");
477 if (!HasAES)
478 Features.push_back("-aes");
479 if (V8Version == 2 || V8Version == 3) {
480 Features.push_back("-sm4");
481 Features.push_back("-sha3");
482 }
483 }
484 }
485
486 // FIXME: these insertions should ideally be automated using default
487 // extensions support from the backend target parser.
488 if (V8Version >= 6 || V9Version >= 1)
489 Features.insert(std::next(Features.begin() + ArchFeatPos),
490 {"+i8mm", "+bf16"});
491
492 // For Armv8.8-a/Armv9.3-a or later, FEAT_HBC and FEAT_MOPS are enabled by
493 // default.
494 if (V8Version >= 8 || V9Version >= 3)
495 Features.insert(std::next(Features.begin() + ArchFeatPos),
496 {"+hbc", "+mops"});
497
498 if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
499 options::OPT_munaligned_access)) {
500 if (A->getOption().matches(options::OPT_mno_unaligned_access))
501 Features.push_back("+strict-align");
502 } else if (Triple.isOSOpenBSD())
503 Features.push_back("+strict-align");
504
505 if (Args.hasArg(options::OPT_ffixed_x1))
506 Features.push_back("+reserve-x1");
507
508 if (Args.hasArg(options::OPT_ffixed_x2))
509 Features.push_back("+reserve-x2");
510
511 if (Args.hasArg(options::OPT_ffixed_x3))
512 Features.push_back("+reserve-x3");
513
514 if (Args.hasArg(options::OPT_ffixed_x4))
515 Features.push_back("+reserve-x4");
516
517 if (Args.hasArg(options::OPT_ffixed_x5))
518 Features.push_back("+reserve-x5");
519
520 if (Args.hasArg(options::OPT_ffixed_x6))
521 Features.push_back("+reserve-x6");
522
523 if (Args.hasArg(options::OPT_ffixed_x7))
524 Features.push_back("+reserve-x7");
525
526 if (Args.hasArg(options::OPT_ffixed_x9))
527 Features.push_back("+reserve-x9");
528
529 if (Args.hasArg(options::OPT_ffixed_x10))
530 Features.push_back("+reserve-x10");
531
532 if (Args.hasArg(options::OPT_ffixed_x11))
533 Features.push_back("+reserve-x11");
534
535 if (Args.hasArg(options::OPT_ffixed_x12))
536 Features.push_back("+reserve-x12");
537
538 if (Args.hasArg(options::OPT_ffixed_x13))
539 Features.push_back("+reserve-x13");
540
541 if (Args.hasArg(options::OPT_ffixed_x14))
542 Features.push_back("+reserve-x14");
543
544 if (Args.hasArg(options::OPT_ffixed_x15))
545 Features.push_back("+reserve-x15");
546
547 if (Args.hasArg(options::OPT_ffixed_x18))
548 Features.push_back("+reserve-x18");
549
550 if (Args.hasArg(options::OPT_ffixed_x20))
551 Features.push_back("+reserve-x20");
552
553 if (Args.hasArg(options::OPT_ffixed_x21))
554 Features.push_back("+reserve-x21");
555
556 if (Args.hasArg(options::OPT_ffixed_x22))
557 Features.push_back("+reserve-x22");
558
559 if (Args.hasArg(options::OPT_ffixed_x23))
560 Features.push_back("+reserve-x23");
561
562 if (Args.hasArg(options::OPT_ffixed_x24))
563 Features.push_back("+reserve-x24");
564
565 if (Args.hasArg(options::OPT_ffixed_x25))
566 Features.push_back("+reserve-x25");
567
568 if (Args.hasArg(options::OPT_ffixed_x26))
569 Features.push_back("+reserve-x26");
570
571 if (Args.hasArg(options::OPT_ffixed_x27))
572 Features.push_back("+reserve-x27");
573
574 if (Args.hasArg(options::OPT_ffixed_x28))
575 Features.push_back("+reserve-x28");
576
577 if (Args.hasArg(options::OPT_ffixed_x30))
578 Features.push_back("+reserve-x30");
579
580 if (Args.hasArg(options::OPT_fcall_saved_x8))
581 Features.push_back("+call-saved-x8");
582
583 if (Args.hasArg(options::OPT_fcall_saved_x9))
584 Features.push_back("+call-saved-x9");
585
586 if (Args.hasArg(options::OPT_fcall_saved_x10))
587 Features.push_back("+call-saved-x10");
588
589 if (Args.hasArg(options::OPT_fcall_saved_x11))
590 Features.push_back("+call-saved-x11");
591
592 if (Args.hasArg(options::OPT_fcall_saved_x12))
593 Features.push_back("+call-saved-x12");
594
595 if (Args.hasArg(options::OPT_fcall_saved_x13))
596 Features.push_back("+call-saved-x13");
597
598 if (Args.hasArg(options::OPT_fcall_saved_x14))
599 Features.push_back("+call-saved-x14");
600
601 if (Args.hasArg(options::OPT_fcall_saved_x15))
602 Features.push_back("+call-saved-x15");
603
604 if (Args.hasArg(options::OPT_fcall_saved_x18))
605 Features.push_back("+call-saved-x18");
606
607 if (Args.hasArg(options::OPT_mno_neg_immediates))
608 Features.push_back("+no-neg-immediates");
609
610 if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
611 options::OPT_mno_fix_cortex_a53_835769)) {
612 if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
613 Features.push_back("+fix-cortex-a53-835769");
614 else
615 Features.push_back("-fix-cortex-a53-835769");
616 } else if (Triple.isAndroid()) {
617 // Enabled A53 errata (835769) workaround by default on android
618 Features.push_back("+fix-cortex-a53-835769");
619 } else if (Triple.isOSFuchsia()) {
620 std::string CPU = getCPUName(D, Args, Triple);
621 if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
622 Features.push_back("+fix-cortex-a53-835769");
623 }
624
625 if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
626 Features.push_back("+no-bti-at-return-twice");
627}