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