1 //===--- ARM.cpp - ARM (not AArch64) 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 "ARM.h"
10 #include "clang/Driver/Driver.h"
11 #include "clang/Driver/DriverDiagnostic.h"
12 #include "clang/Driver/Options.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/Option/ArgList.h"
15 #include "llvm/Support/TargetParser.h"
16 #include "llvm/Support/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 // Get SubArch (vN).
getARMSubArchVersionNumber(const llvm::Triple & Triple)24 int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) {
25 llvm::StringRef Arch = Triple.getArchName();
26 return llvm::ARM::parseArchVersion(Arch);
27 }
28
29 // True if M-profile.
isARMMProfile(const llvm::Triple & Triple)30 bool arm::isARMMProfile(const llvm::Triple &Triple) {
31 llvm::StringRef Arch = Triple.getArchName();
32 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;
33 }
34
35 // True if A-profile.
isARMAProfile(const llvm::Triple & Triple)36 bool arm::isARMAProfile(const llvm::Triple &Triple) {
37 llvm::StringRef Arch = Triple.getArchName();
38 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A;
39 }
40
41 // Get Arch/CPU from args.
getARMArchCPUFromArgs(const ArgList & Args,llvm::StringRef & Arch,llvm::StringRef & CPU,bool FromAs)42 void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
43 llvm::StringRef &CPU, bool FromAs) {
44 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
45 CPU = A->getValue();
46 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
47 Arch = A->getValue();
48 if (!FromAs)
49 return;
50
51 for (const Arg *A :
52 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
53 // Use getValues because -Wa can have multiple arguments
54 // e.g. -Wa,-mcpu=foo,-mcpu=bar
55 for (StringRef Value : A->getValues()) {
56 if (Value.startswith("-mcpu="))
57 CPU = Value.substr(6);
58 if (Value.startswith("-march="))
59 Arch = Value.substr(7);
60 }
61 }
62 }
63
64 // Handle -mhwdiv=.
65 // FIXME: Use ARMTargetParser.
getARMHWDivFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef HWDiv,std::vector<StringRef> & Features)66 static void getARMHWDivFeatures(const Driver &D, const Arg *A,
67 const ArgList &Args, StringRef HWDiv,
68 std::vector<StringRef> &Features) {
69 uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv);
70 if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
71 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
72 }
73
74 // Handle -mfpu=.
getARMFPUFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef FPU,std::vector<StringRef> & Features)75 static unsigned getARMFPUFeatures(const Driver &D, const Arg *A,
76 const ArgList &Args, StringRef FPU,
77 std::vector<StringRef> &Features) {
78 unsigned FPUID = llvm::ARM::parseFPU(FPU);
79 if (!llvm::ARM::getFPUFeatures(FPUID, Features))
80 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
81 return FPUID;
82 }
83
84 // Decode ARM features from string like +[no]featureA+[no]featureB+...
DecodeARMFeatures(const Driver & D,StringRef text,StringRef CPU,llvm::ARM::ArchKind ArchKind,std::vector<StringRef> & Features,unsigned & ArgFPUID)85 static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,
86 llvm::ARM::ArchKind ArchKind,
87 std::vector<StringRef> &Features,
88 unsigned &ArgFPUID) {
89 SmallVector<StringRef, 8> Split;
90 text.split(Split, StringRef("+"), -1, false);
91
92 for (StringRef Feature : Split) {
93 if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUID))
94 return false;
95 }
96 return true;
97 }
98
DecodeARMFeaturesFromCPU(const Driver & D,StringRef CPU,std::vector<StringRef> & Features)99 static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
100 std::vector<StringRef> &Features) {
101 CPU = CPU.split("+").first;
102 if (CPU != "generic") {
103 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
104 uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);
105 llvm::ARM::getExtensionFeatures(Extension, Features);
106 }
107 }
108
109 // Check if -march is valid by checking if it can be canonicalised and parsed.
110 // getARMArch is used here instead of just checking the -march value in order
111 // to handle -march=native correctly.
checkARMArchName(const Driver & D,const Arg * A,const ArgList & Args,llvm::StringRef ArchName,llvm::StringRef CPUName,std::vector<StringRef> & Features,const llvm::Triple & Triple,unsigned & ArgFPUID)112 static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
113 llvm::StringRef ArchName, llvm::StringRef CPUName,
114 std::vector<StringRef> &Features,
115 const llvm::Triple &Triple, unsigned &ArgFPUID) {
116 std::pair<StringRef, StringRef> Split = ArchName.split("+");
117
118 std::string MArch = arm::getARMArch(ArchName, Triple);
119 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
120 if (ArchKind == llvm::ARM::ArchKind::INVALID ||
121 (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName,
122 ArchKind, Features, ArgFPUID)))
123 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
124 }
125
126 // Check -mcpu=. Needs ArchName to handle -mcpu=generic.
checkARMCPUName(const Driver & D,const Arg * A,const ArgList & Args,llvm::StringRef CPUName,llvm::StringRef ArchName,std::vector<StringRef> & Features,const llvm::Triple & Triple,unsigned & ArgFPUID)127 static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
128 llvm::StringRef CPUName, llvm::StringRef ArchName,
129 std::vector<StringRef> &Features,
130 const llvm::Triple &Triple, unsigned &ArgFPUID) {
131 std::pair<StringRef, StringRef> Split = CPUName.split("+");
132
133 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
134 llvm::ARM::ArchKind ArchKind =
135 arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
136 if (ArchKind == llvm::ARM::ArchKind::INVALID ||
137 (Split.second.size() &&
138 !DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID)))
139 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
140 }
141
useAAPCSForMachO(const llvm::Triple & T)142 bool arm::useAAPCSForMachO(const llvm::Triple &T) {
143 // The backend is hardwired to assume AAPCS for M-class processors, ensure
144 // the frontend matches that.
145 return T.getEnvironment() == llvm::Triple::EABI ||
146 T.getEnvironment() == llvm::Triple::EABIHF ||
147 T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
148 }
149
150 // Select mode for reading thread pointer (-mtp=soft/cp15).
getReadTPMode(const Driver & D,const ArgList & Args)151 arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) {
152 if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
153 arm::ReadTPMode ThreadPointer =
154 llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
155 .Case("cp15", ReadTPMode::Cp15)
156 .Case("soft", ReadTPMode::Soft)
157 .Default(ReadTPMode::Invalid);
158 if (ThreadPointer != ReadTPMode::Invalid)
159 return ThreadPointer;
160 if (StringRef(A->getValue()).empty())
161 D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args);
162 else
163 D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
164 return ReadTPMode::Invalid;
165 }
166 return ReadTPMode::Soft;
167 }
168
setArchNameInTriple(const Driver & D,const ArgList & Args,types::ID InputType,llvm::Triple & Triple)169 void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
170 types::ID InputType, llvm::Triple &Triple) {
171 StringRef MCPU, MArch;
172 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
173 MCPU = A->getValue();
174 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
175 MArch = A->getValue();
176
177 std::string CPU = Triple.isOSBinFormatMachO()
178 ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
179 : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
180 StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
181
182 bool IsBigEndian = Triple.getArch() == llvm::Triple::armeb ||
183 Triple.getArch() == llvm::Triple::thumbeb;
184 // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
185 // '-mbig-endian'/'-EB'.
186 if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
187 options::OPT_mbig_endian)) {
188 IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
189 }
190 std::string ArchName = IsBigEndian ? "armeb" : "arm";
191
192 // FIXME: Thumb should just be another -target-feaure, not in the triple.
193 bool IsMProfile =
194 llvm::ARM::parseArchProfile(Suffix) == llvm::ARM::ProfileKind::M;
195 bool ThumbDefault = IsMProfile ||
196 // Thumb2 is the default for V7 on Darwin.
197 (llvm::ARM::parseArchVersion(Suffix) == 7 &&
198 Triple.isOSBinFormatMachO()) ||
199 // FIXME: this is invalid for WindowsCE
200 Triple.isOSWindows();
201
202 // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
203 // M-Class CPUs/architecture variants, which is not supported.
204 bool ARMModeRequested =
205 !Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
206 if (IsMProfile && ARMModeRequested) {
207 if (MCPU.size())
208 D.Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
209 else
210 D.Diag(diag::err_arch_unsupported_isa)
211 << tools::arm::getARMArch(MArch, Triple) << "ARM";
212 }
213
214 // Check to see if an explicit choice to use thumb has been made via
215 // -mthumb. For assembler files we must check for -mthumb in the options
216 // passed to the assembler via -Wa or -Xassembler.
217 bool IsThumb = false;
218 if (InputType != types::TY_PP_Asm)
219 IsThumb =
220 Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
221 else {
222 // Ideally we would check for these flags in
223 // CollectArgsForIntegratedAssembler but we can't change the ArchName at
224 // that point.
225 llvm::StringRef WaMArch, WaMCPU;
226 for (const auto *A :
227 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
228 for (StringRef Value : A->getValues()) {
229 // There is no assembler equivalent of -mno-thumb, -marm, or -mno-arm.
230 if (Value == "-mthumb")
231 IsThumb = true;
232 else if (Value.startswith("-march="))
233 WaMArch = Value.substr(7);
234 else if (Value.startswith("-mcpu="))
235 WaMCPU = Value.substr(6);
236 }
237 }
238
239 if (WaMCPU.size() || WaMArch.size()) {
240 // The way this works means that we prefer -Wa,-mcpu's architecture
241 // over -Wa,-march. Which matches the compiler behaviour.
242 Suffix = tools::arm::getLLVMArchSuffixForARM(WaMCPU, WaMArch, Triple);
243 }
244 }
245
246 // Assembly files should start in ARM mode, unless arch is M-profile, or
247 // -mthumb has been passed explicitly to the assembler. Windows is always
248 // thumb.
249 if (IsThumb || IsMProfile || Triple.isOSWindows()) {
250 if (IsBigEndian)
251 ArchName = "thumbeb";
252 else
253 ArchName = "thumb";
254 }
255 Triple.setArchName(ArchName + Suffix.str());
256 }
257
setFloatABIInTriple(const Driver & D,const ArgList & Args,llvm::Triple & Triple)258 void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
259 llvm::Triple &Triple) {
260 bool isHardFloat =
261 (arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard);
262
263 switch (Triple.getEnvironment()) {
264 case llvm::Triple::GNUEABI:
265 case llvm::Triple::GNUEABIHF:
266 Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF
267 : llvm::Triple::GNUEABI);
268 break;
269 case llvm::Triple::EABI:
270 case llvm::Triple::EABIHF:
271 Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF
272 : llvm::Triple::EABI);
273 break;
274 case llvm::Triple::MuslEABI:
275 case llvm::Triple::MuslEABIHF:
276 Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF
277 : llvm::Triple::MuslEABI);
278 break;
279 default: {
280 arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);
281 if (DefaultABI != arm::FloatABI::Invalid &&
282 isHardFloat != (DefaultABI == arm::FloatABI::Hard)) {
283 Arg *ABIArg =
284 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
285 options::OPT_mfloat_abi_EQ);
286 assert(ABIArg && "Non-default float abi expected to be from arg");
287 D.Diag(diag::err_drv_unsupported_opt_for_target)
288 << ABIArg->getAsString(Args) << Triple.getTriple();
289 }
290 break;
291 }
292 }
293 }
294
getARMFloatABI(const ToolChain & TC,const ArgList & Args)295 arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
296 return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);
297 }
298
getDefaultFloatABI(const llvm::Triple & Triple)299 arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
300 auto SubArch = getARMSubArchVersionNumber(Triple);
301 switch (Triple.getOS()) {
302 case llvm::Triple::Darwin:
303 case llvm::Triple::MacOSX:
304 case llvm::Triple::IOS:
305 case llvm::Triple::TvOS:
306 // Darwin defaults to "softfp" for v6 and v7.
307 if (Triple.isWatchABI())
308 return FloatABI::Hard;
309 else
310 return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
311
312 case llvm::Triple::WatchOS:
313 return FloatABI::Hard;
314
315 // FIXME: this is invalid for WindowsCE
316 case llvm::Triple::Win32:
317 return FloatABI::Hard;
318
319 case llvm::Triple::NetBSD:
320 switch (Triple.getEnvironment()) {
321 case llvm::Triple::EABIHF:
322 case llvm::Triple::GNUEABIHF:
323 return FloatABI::Hard;
324 default:
325 return FloatABI::Soft;
326 }
327 break;
328
329 case llvm::Triple::FreeBSD:
330 switch (Triple.getEnvironment()) {
331 case llvm::Triple::GNUEABIHF:
332 return FloatABI::Hard;
333 default:
334 // FreeBSD defaults to soft float
335 return FloatABI::Soft;
336 }
337 break;
338
339 case llvm::Triple::OpenBSD:
340 return FloatABI::SoftFP;
341
342 default:
343 switch (Triple.getEnvironment()) {
344 case llvm::Triple::GNUEABIHF:
345 case llvm::Triple::MuslEABIHF:
346 case llvm::Triple::EABIHF:
347 return FloatABI::Hard;
348 case llvm::Triple::GNUEABI:
349 case llvm::Triple::MuslEABI:
350 case llvm::Triple::EABI:
351 // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
352 return FloatABI::SoftFP;
353 case llvm::Triple::Android:
354 return (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft;
355 default:
356 return FloatABI::Invalid;
357 }
358 }
359 return FloatABI::Invalid;
360 }
361
362 // Select the float ABI as determined by -msoft-float, -mhard-float, and
363 // -mfloat-abi=.
getARMFloatABI(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)364 arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
365 const ArgList &Args) {
366 arm::FloatABI ABI = FloatABI::Invalid;
367 if (Arg *A =
368 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
369 options::OPT_mfloat_abi_EQ)) {
370 if (A->getOption().matches(options::OPT_msoft_float)) {
371 ABI = FloatABI::Soft;
372 } else if (A->getOption().matches(options::OPT_mhard_float)) {
373 ABI = FloatABI::Hard;
374 } else {
375 ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
376 .Case("soft", FloatABI::Soft)
377 .Case("softfp", FloatABI::SoftFP)
378 .Case("hard", FloatABI::Hard)
379 .Default(FloatABI::Invalid);
380 if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
381 D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
382 ABI = FloatABI::Soft;
383 }
384 }
385 }
386
387 // If unspecified, choose the default based on the platform.
388 if (ABI == FloatABI::Invalid)
389 ABI = arm::getDefaultFloatABI(Triple);
390
391 if (ABI == FloatABI::Invalid) {
392 // Assume "soft", but warn the user we are guessing.
393 if (Triple.isOSBinFormatMachO() &&
394 Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
395 ABI = FloatABI::Hard;
396 else
397 ABI = FloatABI::Soft;
398
399 if (Triple.getOS() != llvm::Triple::UnknownOS ||
400 !Triple.isOSBinFormatMachO())
401 D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
402 }
403
404 assert(ABI != FloatABI::Invalid && "must select an ABI");
405 return ABI;
406 }
407
hasIntegerMVE(const std::vector<StringRef> & F)408 static bool hasIntegerMVE(const std::vector<StringRef> &F) {
409 auto MVE = llvm::find(llvm::reverse(F), "+mve");
410 auto NoMVE = llvm::find(llvm::reverse(F), "-mve");
411 return MVE != F.rend() &&
412 (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);
413 }
414
getARMTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,ArgStringList & CmdArgs,std::vector<StringRef> & Features,bool ForAS)415 void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
416 const ArgList &Args, ArgStringList &CmdArgs,
417 std::vector<StringRef> &Features, bool ForAS) {
418 bool KernelOrKext =
419 Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
420 arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
421 arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args);
422 llvm::Optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv,
423 WaArch;
424
425 // This vector will accumulate features from the architecture
426 // extension suffixes on -mcpu and -march (e.g. the 'bar' in
427 // -mcpu=foo+bar). We want to apply those after the features derived
428 // from the FPU, in case -mfpu generates a negative feature which
429 // the +bar is supposed to override.
430 std::vector<StringRef> ExtensionFeatures;
431
432 if (!ForAS) {
433 // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
434 // yet (it uses the -mfloat-abi and -msoft-float options), and it is
435 // stripped out by the ARM target. We should probably pass this a new
436 // -target-option, which is handled by the -cc1/-cc1as invocation.
437 //
438 // FIXME2: For consistency, it would be ideal if we set up the target
439 // machine state the same when using the frontend or the assembler. We don't
440 // currently do that for the assembler, we pass the options directly to the
441 // backend and never even instantiate the frontend TargetInfo. If we did,
442 // and used its handleTargetFeatures hook, then we could ensure the
443 // assembler and the frontend behave the same.
444
445 // Use software floating point operations?
446 if (ABI == arm::FloatABI::Soft)
447 Features.push_back("+soft-float");
448
449 // Use software floating point argument passing?
450 if (ABI != arm::FloatABI::Hard)
451 Features.push_back("+soft-float-abi");
452 } else {
453 // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
454 // to the assembler correctly.
455 for (const Arg *A :
456 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
457 // We use getValues here because you can have many options per -Wa
458 // We will keep the last one we find for each of these
459 for (StringRef Value : A->getValues()) {
460 if (Value.startswith("-mfpu=")) {
461 WaFPU = std::make_pair(A, Value.substr(6));
462 } else if (Value.startswith("-mcpu=")) {
463 WaCPU = std::make_pair(A, Value.substr(6));
464 } else if (Value.startswith("-mhwdiv=")) {
465 WaHDiv = std::make_pair(A, Value.substr(8));
466 } else if (Value.startswith("-march=")) {
467 WaArch = std::make_pair(A, Value.substr(7));
468 }
469 }
470 }
471 }
472
473 if (ThreadPointer == arm::ReadTPMode::Cp15)
474 Features.push_back("+read-tp-hard");
475
476 const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
477 const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
478 StringRef ArchName;
479 StringRef CPUName;
480 unsigned ArchArgFPUID = llvm::ARM::FK_INVALID;
481 unsigned CPUArgFPUID = llvm::ARM::FK_INVALID;
482
483 // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
484 if (WaCPU) {
485 if (CPUArg)
486 D.Diag(clang::diag::warn_drv_unused_argument)
487 << CPUArg->getAsString(Args);
488 CPUName = WaCPU->second;
489 CPUArg = WaCPU->first;
490 } else if (CPUArg)
491 CPUName = CPUArg->getValue();
492
493 // Check -march. ClangAs gives preference to -Wa,-march=.
494 if (WaArch) {
495 if (ArchArg)
496 D.Diag(clang::diag::warn_drv_unused_argument)
497 << ArchArg->getAsString(Args);
498 ArchName = WaArch->second;
499 // This will set any features after the base architecture.
500 checkARMArchName(D, WaArch->first, Args, ArchName, CPUName,
501 ExtensionFeatures, Triple, ArchArgFPUID);
502 // The base architecture was handled in ToolChain::ComputeLLVMTriple because
503 // triple is read only by this point.
504 } else if (ArchArg) {
505 ArchName = ArchArg->getValue();
506 checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
507 Triple, ArchArgFPUID);
508 }
509
510 // Add CPU features for generic CPUs
511 if (CPUName == "native") {
512 llvm::StringMap<bool> HostFeatures;
513 if (llvm::sys::getHostCPUFeatures(HostFeatures))
514 for (auto &F : HostFeatures)
515 Features.push_back(
516 Args.MakeArgString((F.second ? "+" : "-") + F.first()));
517 } else if (!CPUName.empty()) {
518 // This sets the default features for the specified CPU. We certainly don't
519 // want to override the features that have been explicitly specified on the
520 // command line. Therefore, process them directly instead of appending them
521 // at the end later.
522 DecodeARMFeaturesFromCPU(D, CPUName, Features);
523 }
524
525 if (CPUArg)
526 checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,
527 Triple, CPUArgFPUID);
528 // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
529 unsigned FPUID = llvm::ARM::FK_INVALID;
530 const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
531 if (WaFPU) {
532 if (FPUArg)
533 D.Diag(clang::diag::warn_drv_unused_argument)
534 << FPUArg->getAsString(Args);
535 (void)getARMFPUFeatures(D, WaFPU->first, Args, WaFPU->second, Features);
536 } else if (FPUArg) {
537 FPUID = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
538 } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
539 const char *AndroidFPU = "neon";
540 FPUID = llvm::ARM::parseFPU(AndroidFPU);
541 if (!llvm::ARM::getFPUFeatures(FPUID, Features))
542 D.Diag(clang::diag::err_drv_clang_unsupported)
543 << std::string("-mfpu=") + AndroidFPU;
544 } else {
545 if (!ForAS) {
546 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
547 llvm::ARM::ArchKind ArchKind =
548 arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
549 FPUID = llvm::ARM::getDefaultFPU(CPU, ArchKind);
550 (void)llvm::ARM::getFPUFeatures(FPUID, Features);
551 }
552 }
553
554 // Now we've finished accumulating features from arch, cpu and fpu,
555 // we can append the ones for architecture extensions that we
556 // collected separately.
557 Features.insert(std::end(Features),
558 std::begin(ExtensionFeatures), std::end(ExtensionFeatures));
559
560 // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
561 const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
562 if (WaHDiv) {
563 if (HDivArg)
564 D.Diag(clang::diag::warn_drv_unused_argument)
565 << HDivArg->getAsString(Args);
566 getARMHWDivFeatures(D, WaHDiv->first, Args, WaHDiv->second, Features);
567 } else if (HDivArg)
568 getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
569
570 // Handle (arch-dependent) fp16fml/fullfp16 relationship.
571 // Must happen before any features are disabled due to soft-float.
572 // FIXME: this fp16fml option handling will be reimplemented after the
573 // TargetParser rewrite.
574 const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
575 const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
576 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) {
577 const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
578 if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
579 // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
580 // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
581 if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
582 Features.push_back("+fp16fml");
583 }
584 else
585 goto fp16_fml_fallthrough;
586 }
587 else {
588 fp16_fml_fallthrough:
589 // In both of these cases, putting the 'other' feature on the end of the vector will
590 // result in the same effect as placing it immediately after the current feature.
591 if (ItRNoFullFP16 < ItRFP16FML)
592 Features.push_back("-fp16fml");
593 else if (ItRNoFullFP16 > ItRFP16FML)
594 Features.push_back("+fullfp16");
595 }
596
597 // Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to
598 // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
599 // this case). Note that the ABI can also be set implicitly by the target
600 // selected.
601 if (ABI == arm::FloatABI::Soft) {
602 llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
603
604 // Disable all features relating to hardware FP, not already disabled by the
605 // above call.
606 Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
607 "-mve.fp", "-fpregs"});
608 } else if (FPUID == llvm::ARM::FK_NONE ||
609 ArchArgFPUID == llvm::ARM::FK_NONE ||
610 CPUArgFPUID == llvm::ARM::FK_NONE) {
611 // -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to
612 // -mfloat-abi=soft, only that it should not disable MVE-I. They disable the
613 // FPU, but not the FPU registers, thus MVE-I, which depends only on the
614 // latter, is still supported.
615 Features.insert(Features.end(),
616 {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
617 if (!hasIntegerMVE(Features))
618 Features.emplace_back("-fpregs");
619 }
620
621 // En/disable crc code generation.
622 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
623 if (A->getOption().matches(options::OPT_mcrc))
624 Features.push_back("+crc");
625 else
626 Features.push_back("-crc");
627 }
628
629 // For Arch >= ARMv8.0 && A or R profile: crypto = sha2 + aes
630 // Rather than replace within the feature vector, determine whether each
631 // algorithm is enabled and append this to the end of the vector.
632 // The algorithms can be controlled by their specific feature or the crypto
633 // feature, so their status can be determined by the last occurance of
634 // either in the vector. This allows one to supercede the other.
635 // e.g. +crypto+noaes in -march/-mcpu should enable sha2, but not aes
636 // FIXME: this needs reimplementation after the TargetParser rewrite
637 bool HasSHA2 = false;
638 bool HasAES = false;
639 const auto ItCrypto =
640 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
641 return F.contains("crypto");
642 });
643 const auto ItSHA2 =
644 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
645 return F.contains("crypto") || F.contains("sha2");
646 });
647 const auto ItAES =
648 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
649 return F.contains("crypto") || F.contains("aes");
650 });
651 const bool FoundSHA2 = ItSHA2 != Features.rend();
652 const bool FoundAES = ItAES != Features.rend();
653 if (FoundSHA2)
654 HasSHA2 = ItSHA2->take_front() == "+";
655 if (FoundAES)
656 HasAES = ItAES->take_front() == "+";
657 if (ItCrypto != Features.rend()) {
658 if (HasSHA2 && HasAES)
659 Features.push_back("+crypto");
660 else
661 Features.push_back("-crypto");
662 if (HasSHA2)
663 Features.push_back("+sha2");
664 else
665 Features.push_back("-sha2");
666 if (HasAES)
667 Features.push_back("+aes");
668 else
669 Features.push_back("-aes");
670 }
671
672 if (HasSHA2 || HasAES) {
673 StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(
674 arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple);
675 llvm::ARM::ProfileKind ArchProfile =
676 llvm::ARM::parseArchProfile(ArchSuffix);
677 if (!((llvm::ARM::parseArchVersion(ArchSuffix) >= 8) &&
678 (ArchProfile == llvm::ARM::ProfileKind::A ||
679 ArchProfile == llvm::ARM::ProfileKind::R))) {
680 if (HasSHA2)
681 D.Diag(clang::diag::warn_target_unsupported_extension)
682 << "sha2"
683 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
684 if (HasAES)
685 D.Diag(clang::diag::warn_target_unsupported_extension)
686 << "aes"
687 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
688 // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such
689 // as the GNU assembler will permit the use of crypto instructions as the
690 // fpu will override the architecture. We keep the crypto feature in this
691 // case to preserve compatibility. In all other cases we remove the crypto
692 // feature.
693 if (!Args.hasArg(options::OPT_fno_integrated_as)) {
694 Features.push_back("-sha2");
695 Features.push_back("-aes");
696 }
697 }
698 }
699
700 // CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.
701 if (Args.getLastArg(options::OPT_mcmse))
702 Features.push_back("+8msecext");
703
704 // Look for the last occurrence of -mlong-calls or -mno-long-calls. If
705 // neither options are specified, see if we are compiling for kernel/kext and
706 // decide whether to pass "+long-calls" based on the OS and its version.
707 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
708 options::OPT_mno_long_calls)) {
709 if (A->getOption().matches(options::OPT_mlong_calls))
710 Features.push_back("+long-calls");
711 } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
712 !Triple.isWatchOS()) {
713 Features.push_back("+long-calls");
714 }
715
716 // Generate execute-only output (no data access to code sections).
717 // This only makes sense for the compiler, not for the assembler.
718 if (!ForAS) {
719 // Supported only on ARMv6T2 and ARMv7 and above.
720 // Cannot be combined with -mno-movt or -mlong-calls
721 if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
722 if (A->getOption().matches(options::OPT_mexecute_only)) {
723 if (getARMSubArchVersionNumber(Triple) < 7 &&
724 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2)
725 D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
726 else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
727 D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
728 // Long calls create constant pool entries and have not yet been fixed up
729 // to play nicely with execute-only. Hence, they cannot be used in
730 // execute-only code for now
731 else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
732 if (B->getOption().matches(options::OPT_mlong_calls))
733 D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
734 }
735 Features.push_back("+execute-only");
736 }
737 }
738 }
739
740 // Kernel code has more strict alignment requirements.
741 if (KernelOrKext)
742 Features.push_back("+strict-align");
743 else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
744 options::OPT_munaligned_access)) {
745 if (A->getOption().matches(options::OPT_munaligned_access)) {
746 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
747 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
748 D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
749 // v8M Baseline follows on from v6M, so doesn't support unaligned memory
750 // access either.
751 else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
752 D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
753 } else
754 Features.push_back("+strict-align");
755 } else {
756 // Assume pre-ARMv6 doesn't support unaligned accesses.
757 //
758 // ARMv6 may or may not support unaligned accesses depending on the
759 // SCTLR.U bit, which is architecture-specific. We assume ARMv6
760 // Darwin and NetBSD targets support unaligned accesses, and others don't.
761 //
762 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
763 // which raises an alignment fault on unaligned accesses. Linux
764 // defaults this bit to 0 and handles it as a system-wide (not
765 // per-process) setting. It is therefore safe to assume that ARMv7+
766 // Linux targets support unaligned accesses. The same goes for NaCl.
767 //
768 // The above behavior is consistent with GCC.
769 int VersionNum = getARMSubArchVersionNumber(Triple);
770 if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
771 if (VersionNum < 6 ||
772 Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
773 Features.push_back("+strict-align");
774 } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
775 if (VersionNum < 7)
776 Features.push_back("+strict-align");
777 } else
778 Features.push_back("+strict-align");
779 }
780
781 // llvm does not support reserving registers in general. There is support
782 // for reserving r9 on ARM though (defined as a platform-specific register
783 // in ARM EABI).
784 if (Args.hasArg(options::OPT_ffixed_r9))
785 Features.push_back("+reserve-r9");
786
787 // The kext linker doesn't know how to deal with movw/movt.
788 if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
789 Features.push_back("+no-movt");
790
791 if (Args.hasArg(options::OPT_mno_neg_immediates))
792 Features.push_back("+no-neg-immediates");
793
794 // Enable/disable straight line speculation hardening.
795 if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
796 StringRef Scope = A->getValue();
797 bool EnableRetBr = false;
798 bool EnableBlr = false;
799 bool DisableComdat = false;
800 if (Scope != "none") {
801 SmallVector<StringRef, 4> Opts;
802 Scope.split(Opts, ",");
803 for (auto Opt : Opts) {
804 Opt = Opt.trim();
805 if (Opt == "all") {
806 EnableBlr = true;
807 EnableRetBr = true;
808 continue;
809 }
810 if (Opt == "retbr") {
811 EnableRetBr = true;
812 continue;
813 }
814 if (Opt == "blr") {
815 EnableBlr = true;
816 continue;
817 }
818 if (Opt == "comdat") {
819 DisableComdat = false;
820 continue;
821 }
822 if (Opt == "nocomdat") {
823 DisableComdat = true;
824 continue;
825 }
826 D.Diag(diag::err_invalid_sls_hardening)
827 << Scope << A->getAsString(Args);
828 break;
829 }
830 }
831
832 if (EnableRetBr || EnableBlr)
833 if (!(isARMAProfile(Triple) && getARMSubArchVersionNumber(Triple) >= 7))
834 D.Diag(diag::err_sls_hardening_arm_not_supported)
835 << Scope << A->getAsString(Args);
836
837 if (EnableRetBr)
838 Features.push_back("+harden-sls-retbr");
839 if (EnableBlr)
840 Features.push_back("+harden-sls-blr");
841 if (DisableComdat) {
842 Features.push_back("+harden-sls-nocomdat");
843 }
844 }
845
846 }
847
getARMArch(StringRef Arch,const llvm::Triple & Triple)848 const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
849 std::string MArch;
850 if (!Arch.empty())
851 MArch = std::string(Arch);
852 else
853 MArch = std::string(Triple.getArchName());
854 MArch = StringRef(MArch).split("+").first.lower();
855
856 // Handle -march=native.
857 if (MArch == "native") {
858 std::string CPU = std::string(llvm::sys::getHostCPUName());
859 if (CPU != "generic") {
860 // Translate the native cpu into the architecture suffix for that CPU.
861 StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
862 // If there is no valid architecture suffix for this CPU we don't know how
863 // to handle it, so return no architecture.
864 if (Suffix.empty())
865 MArch = "";
866 else
867 MArch = std::string("arm") + Suffix.str();
868 }
869 }
870
871 return MArch;
872 }
873
874 /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
getARMCPUForMArch(StringRef Arch,const llvm::Triple & Triple)875 StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
876 std::string MArch = getARMArch(Arch, Triple);
877 // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
878 // here means an -march=native that we can't handle, so instead return no CPU.
879 if (MArch.empty())
880 return StringRef();
881
882 // We need to return an empty string here on invalid MArch values as the
883 // various places that call this function can't cope with a null result.
884 return Triple.getARMCPUForArch(MArch);
885 }
886
887 /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
getARMTargetCPU(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)888 std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
889 const llvm::Triple &Triple) {
890 // FIXME: Warn on inconsistent use of -mcpu and -march.
891 // If we have -mcpu=, use that.
892 if (!CPU.empty()) {
893 std::string MCPU = StringRef(CPU).split("+").first.lower();
894 // Handle -mcpu=native.
895 if (MCPU == "native")
896 return std::string(llvm::sys::getHostCPUName());
897 else
898 return MCPU;
899 }
900
901 return std::string(getARMCPUForMArch(Arch, Triple));
902 }
903
904 /// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a
905 /// particular CPU (or Arch, if CPU is generic). This is needed to
906 /// pass to functions like llvm::ARM::getDefaultFPU which need an
907 /// ArchKind as well as a CPU name.
getLLVMArchKindForARM(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)908 llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch,
909 const llvm::Triple &Triple) {
910 llvm::ARM::ArchKind ArchKind;
911 if (CPU == "generic" || CPU.empty()) {
912 std::string ARMArch = tools::arm::getARMArch(Arch, Triple);
913 ArchKind = llvm::ARM::parseArch(ARMArch);
914 if (ArchKind == llvm::ARM::ArchKind::INVALID)
915 // In case of generic Arch, i.e. "arm",
916 // extract arch from default cpu of the Triple
917 ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
918 } else {
919 // FIXME: horrible hack to get around the fact that Cortex-A7 is only an
920 // armv7k triple if it's actually been specified via "-arch armv7k".
921 ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
922 ? llvm::ARM::ArchKind::ARMV7K
923 : llvm::ARM::parseCPUArch(CPU);
924 }
925 return ArchKind;
926 }
927
928 /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
929 /// CPU (or Arch, if CPU is generic).
930 // FIXME: This is redundant with -mcpu, why does LLVM use this.
getLLVMArchSuffixForARM(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)931 StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
932 const llvm::Triple &Triple) {
933 llvm::ARM::ArchKind ArchKind = getLLVMArchKindForARM(CPU, Arch, Triple);
934 if (ArchKind == llvm::ARM::ArchKind::INVALID)
935 return "";
936 return llvm::ARM::getSubArch(ArchKind);
937 }
938
appendBE8LinkFlag(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple)939 void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs,
940 const llvm::Triple &Triple) {
941 if (Args.hasArg(options::OPT_r))
942 return;
943
944 // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker
945 // to generate BE-8 executables.
946 if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple))
947 CmdArgs.push_back("--be8");
948 }
949