1 //===--- ARM.cpp - ARM (not AArch64) Helpers for Tools ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ARM.h" 11 #include "clang/Driver/Driver.h" 12 #include "clang/Driver/DriverDiagnostic.h" 13 #include "clang/Driver/Options.h" 14 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/Option/ArgList.h" 16 #include "llvm/Support/TargetParser.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). 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. 30 bool arm::isARMMProfile(const llvm::Triple &Triple) { 31 llvm::StringRef Arch = Triple.getArchName(); 32 unsigned Profile = llvm::ARM::parseArchProfile(Arch); 33 return Profile == llvm::ARM::PK_M; 34 } 35 36 // Get Arch/CPU from args. 37 void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, 38 llvm::StringRef &CPU, bool FromAs) { 39 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) 40 CPU = A->getValue(); 41 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 42 Arch = A->getValue(); 43 if (!FromAs) 44 return; 45 46 for (const Arg *A : 47 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { 48 StringRef Value = A->getValue(); 49 if (Value.startswith("-mcpu=")) 50 CPU = Value.substr(6); 51 if (Value.startswith("-march=")) 52 Arch = Value.substr(7); 53 } 54 } 55 56 // Handle -mhwdiv=. 57 // FIXME: Use ARMTargetParser. 58 static void getARMHWDivFeatures(const Driver &D, const Arg *A, 59 const ArgList &Args, StringRef HWDiv, 60 std::vector<StringRef> &Features) { 61 unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv); 62 if (!llvm::ARM::getHWDivFeatures(HWDivID, Features)) 63 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 64 } 65 66 // Handle -mfpu=. 67 static void getARMFPUFeatures(const Driver &D, const Arg *A, 68 const ArgList &Args, StringRef FPU, 69 std::vector<StringRef> &Features) { 70 unsigned FPUID = llvm::ARM::parseFPU(FPU); 71 if (!llvm::ARM::getFPUFeatures(FPUID, Features)) 72 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 73 } 74 75 // Decode ARM features from string like +[no]featureA+[no]featureB+... 76 static bool DecodeARMFeatures(const Driver &D, StringRef text, 77 std::vector<StringRef> &Features) { 78 SmallVector<StringRef, 8> Split; 79 text.split(Split, StringRef("+"), -1, false); 80 81 for (StringRef Feature : Split) { 82 StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature); 83 if (!FeatureName.empty()) 84 Features.push_back(FeatureName); 85 else 86 return false; 87 } 88 return true; 89 } 90 91 // Check if -march is valid by checking if it can be canonicalised and parsed. 92 // getARMArch is used here instead of just checking the -march value in order 93 // to handle -march=native correctly. 94 static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args, 95 llvm::StringRef ArchName, 96 std::vector<StringRef> &Features, 97 const llvm::Triple &Triple) { 98 std::pair<StringRef, StringRef> Split = ArchName.split("+"); 99 100 std::string MArch = arm::getARMArch(ArchName, Triple); 101 if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID || 102 (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) 103 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 104 } 105 106 // Check -mcpu=. Needs ArchName to handle -mcpu=generic. 107 static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args, 108 llvm::StringRef CPUName, llvm::StringRef ArchName, 109 std::vector<StringRef> &Features, 110 const llvm::Triple &Triple) { 111 std::pair<StringRef, StringRef> Split = CPUName.split("+"); 112 113 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); 114 if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() || 115 (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) 116 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 117 } 118 119 bool arm::useAAPCSForMachO(const llvm::Triple &T) { 120 // The backend is hardwired to assume AAPCS for M-class processors, ensure 121 // the frontend matches that. 122 return T.getEnvironment() == llvm::Triple::EABI || 123 T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T); 124 } 125 126 // Select the float ABI as determined by -msoft-float, -mhard-float, and 127 // -mfloat-abi=. 128 arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { 129 const Driver &D = TC.getDriver(); 130 const llvm::Triple &Triple = TC.getEffectiveTriple(); 131 auto SubArch = getARMSubArchVersionNumber(Triple); 132 arm::FloatABI ABI = FloatABI::Invalid; 133 if (Arg *A = 134 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, 135 options::OPT_mfloat_abi_EQ)) { 136 if (A->getOption().matches(options::OPT_msoft_float)) { 137 ABI = FloatABI::Soft; 138 } else if (A->getOption().matches(options::OPT_mhard_float)) { 139 ABI = FloatABI::Hard; 140 } else { 141 ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue()) 142 .Case("soft", FloatABI::Soft) 143 .Case("softfp", FloatABI::SoftFP) 144 .Case("hard", FloatABI::Hard) 145 .Default(FloatABI::Invalid); 146 if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) { 147 D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); 148 ABI = FloatABI::Soft; 149 } 150 } 151 152 // It is incorrect to select hard float ABI on MachO platforms if the ABI is 153 // "apcs-gnu". 154 if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) && 155 ABI == FloatABI::Hard) { 156 D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) 157 << Triple.getArchName(); 158 } 159 } 160 161 // If unspecified, choose the default based on the platform. 162 if (ABI == FloatABI::Invalid) { 163 switch (Triple.getOS()) { 164 case llvm::Triple::Darwin: 165 case llvm::Triple::MacOSX: 166 case llvm::Triple::IOS: 167 case llvm::Triple::TvOS: { 168 // Darwin defaults to "softfp" for v6 and v7. 169 ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; 170 ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI; 171 break; 172 } 173 case llvm::Triple::WatchOS: 174 ABI = FloatABI::Hard; 175 break; 176 177 // FIXME: this is invalid for WindowsCE 178 case llvm::Triple::Win32: 179 ABI = FloatABI::Hard; 180 break; 181 182 case llvm::Triple::FreeBSD: 183 switch (Triple.getEnvironment()) { 184 case llvm::Triple::GNUEABIHF: 185 ABI = FloatABI::Hard; 186 break; 187 default: 188 // FreeBSD defaults to soft float 189 ABI = FloatABI::Soft; 190 break; 191 } 192 break; 193 194 case llvm::Triple::OpenBSD: 195 ABI = FloatABI::Soft; 196 break; 197 198 default: 199 switch (Triple.getEnvironment()) { 200 case llvm::Triple::GNUEABIHF: 201 case llvm::Triple::MuslEABIHF: 202 case llvm::Triple::EABIHF: 203 ABI = FloatABI::Hard; 204 break; 205 case llvm::Triple::GNUEABI: 206 case llvm::Triple::MuslEABI: 207 case llvm::Triple::EABI: 208 // EABI is always AAPCS, and if it was not marked 'hard', it's softfp 209 ABI = FloatABI::SoftFP; 210 break; 211 case llvm::Triple::Android: 212 ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; 213 break; 214 default: 215 // Assume "soft", but warn the user we are guessing. 216 if (Triple.isOSBinFormatMachO() && 217 Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) 218 ABI = FloatABI::Hard; 219 else 220 ABI = FloatABI::Soft; 221 222 if (Triple.getOS() != llvm::Triple::UnknownOS || 223 !Triple.isOSBinFormatMachO()) 224 D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; 225 break; 226 } 227 } 228 } 229 230 assert(ABI != FloatABI::Invalid && "must select an ABI"); 231 return ABI; 232 } 233 234 void arm::getARMTargetFeatures(const ToolChain &TC, 235 const llvm::Triple &Triple, 236 const ArgList &Args, 237 ArgStringList &CmdArgs, 238 std::vector<StringRef> &Features, 239 bool ForAS) { 240 const Driver &D = TC.getDriver(); 241 242 bool KernelOrKext = 243 Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); 244 arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); 245 const Arg *WaCPU = nullptr, *WaFPU = nullptr; 246 const Arg *WaHDiv = nullptr, *WaArch = nullptr; 247 248 if (!ForAS) { 249 // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these 250 // yet (it uses the -mfloat-abi and -msoft-float options), and it is 251 // stripped out by the ARM target. We should probably pass this a new 252 // -target-option, which is handled by the -cc1/-cc1as invocation. 253 // 254 // FIXME2: For consistency, it would be ideal if we set up the target 255 // machine state the same when using the frontend or the assembler. We don't 256 // currently do that for the assembler, we pass the options directly to the 257 // backend and never even instantiate the frontend TargetInfo. If we did, 258 // and used its handleTargetFeatures hook, then we could ensure the 259 // assembler and the frontend behave the same. 260 261 // Use software floating point operations? 262 if (ABI == arm::FloatABI::Soft) 263 Features.push_back("+soft-float"); 264 265 // Use software floating point argument passing? 266 if (ABI != arm::FloatABI::Hard) 267 Features.push_back("+soft-float-abi"); 268 } else { 269 // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down 270 // to the assembler correctly. 271 for (const Arg *A : 272 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { 273 StringRef Value = A->getValue(); 274 if (Value.startswith("-mfpu=")) { 275 WaFPU = A; 276 } else if (Value.startswith("-mcpu=")) { 277 WaCPU = A; 278 } else if (Value.startswith("-mhwdiv=")) { 279 WaHDiv = A; 280 } else if (Value.startswith("-march=")) { 281 WaArch = A; 282 } 283 } 284 } 285 286 // Check -march. ClangAs gives preference to -Wa,-march=. 287 const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); 288 StringRef ArchName; 289 if (WaArch) { 290 if (ArchArg) 291 D.Diag(clang::diag::warn_drv_unused_argument) 292 << ArchArg->getAsString(Args); 293 ArchName = StringRef(WaArch->getValue()).substr(7); 294 checkARMArchName(D, WaArch, Args, ArchName, Features, Triple); 295 // FIXME: Set Arch. 296 D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); 297 } else if (ArchArg) { 298 ArchName = ArchArg->getValue(); 299 checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple); 300 } 301 302 // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. 303 const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); 304 StringRef CPUName; 305 if (WaCPU) { 306 if (CPUArg) 307 D.Diag(clang::diag::warn_drv_unused_argument) 308 << CPUArg->getAsString(Args); 309 CPUName = StringRef(WaCPU->getValue()).substr(6); 310 checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple); 311 } else if (CPUArg) { 312 CPUName = CPUArg->getValue(); 313 checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple); 314 } 315 316 // Add CPU features for generic CPUs 317 if (CPUName == "native") { 318 llvm::StringMap<bool> HostFeatures; 319 if (llvm::sys::getHostCPUFeatures(HostFeatures)) 320 for (auto &F : HostFeatures) 321 Features.push_back( 322 Args.MakeArgString((F.second ? "+" : "-") + F.first())); 323 } 324 325 // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. 326 const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); 327 if (WaFPU) { 328 if (FPUArg) 329 D.Diag(clang::diag::warn_drv_unused_argument) 330 << FPUArg->getAsString(Args); 331 getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), 332 Features); 333 } else if (FPUArg) { 334 getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); 335 } 336 337 // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. 338 const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); 339 if (WaHDiv) { 340 if (HDivArg) 341 D.Diag(clang::diag::warn_drv_unused_argument) 342 << HDivArg->getAsString(Args); 343 getARMHWDivFeatures(D, WaHDiv, Args, 344 StringRef(WaHDiv->getValue()).substr(8), Features); 345 } else if (HDivArg) 346 getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); 347 348 // Setting -msoft-float effectively disables NEON because of the GCC 349 // implementation, although the same isn't true of VFP or VFP3. 350 if (ABI == arm::FloatABI::Soft) { 351 Features.push_back("-neon"); 352 // Also need to explicitly disable features which imply NEON. 353 Features.push_back("-crypto"); 354 } 355 356 // En/disable crc code generation. 357 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { 358 if (A->getOption().matches(options::OPT_mcrc)) 359 Features.push_back("+crc"); 360 else 361 Features.push_back("-crc"); 362 } 363 364 // Look for the last occurrence of -mlong-calls or -mno-long-calls. If 365 // neither options are specified, see if we are compiling for kernel/kext and 366 // decide whether to pass "+long-calls" based on the OS and its version. 367 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, 368 options::OPT_mno_long_calls)) { 369 if (A->getOption().matches(options::OPT_mlong_calls)) 370 Features.push_back("+long-calls"); 371 } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) && 372 !Triple.isWatchOS()) { 373 Features.push_back("+long-calls"); 374 } 375 376 // Generate execute-only output (no data access to code sections). 377 // This only makes sense for the compiler, not for the assembler. 378 if (!ForAS) { 379 // Supported only on ARMv6T2 and ARMv7 and above. 380 // Cannot be combined with -mno-movt or -mlong-calls 381 if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { 382 if (A->getOption().matches(options::OPT_mexecute_only)) { 383 if (getARMSubArchVersionNumber(Triple) < 7 && 384 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2) 385 D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); 386 else if (Arg *B = Args.getLastArg(options::OPT_mno_movt)) 387 D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); 388 // Long calls create constant pool entries and have not yet been fixed up 389 // to play nicely with execute-only. Hence, they cannot be used in 390 // execute-only code for now 391 else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { 392 if (B->getOption().matches(options::OPT_mlong_calls)) 393 D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); 394 } 395 396 CmdArgs.push_back("-backend-option"); 397 CmdArgs.push_back("-arm-execute-only"); 398 } 399 } 400 } 401 402 // Kernel code has more strict alignment requirements. 403 if (KernelOrKext) 404 Features.push_back("+strict-align"); 405 else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, 406 options::OPT_munaligned_access)) { 407 if (A->getOption().matches(options::OPT_munaligned_access)) { 408 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). 409 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) 410 D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; 411 // v8M Baseline follows on from v6M, so doesn't support unaligned memory 412 // access either. 413 else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) 414 D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; 415 } else 416 Features.push_back("+strict-align"); 417 } else { 418 // Assume pre-ARMv6 doesn't support unaligned accesses. 419 // 420 // ARMv6 may or may not support unaligned accesses depending on the 421 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 422 // Darwin and NetBSD targets support unaligned accesses, and others don't. 423 // 424 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 425 // which raises an alignment fault on unaligned accesses. Linux 426 // defaults this bit to 0 and handles it as a system-wide (not 427 // per-process) setting. It is therefore safe to assume that ARMv7+ 428 // Linux targets support unaligned accesses. The same goes for NaCl. 429 // 430 // The above behavior is consistent with GCC. 431 int VersionNum = getARMSubArchVersionNumber(Triple); 432 if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { 433 if (VersionNum < 6 || 434 Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) 435 Features.push_back("+strict-align"); 436 } else if (Triple.isOSLinux() || Triple.isOSNaCl()) { 437 if (VersionNum < 7) 438 Features.push_back("+strict-align"); 439 } else 440 Features.push_back("+strict-align"); 441 } 442 443 // llvm does not support reserving registers in general. There is support 444 // for reserving r9 on ARM though (defined as a platform-specific register 445 // in ARM EABI). 446 if (Args.hasArg(options::OPT_ffixed_r9)) 447 Features.push_back("+reserve-r9"); 448 449 // The kext linker doesn't know how to deal with movw/movt. 450 if (KernelOrKext || Args.hasArg(options::OPT_mno_movt)) 451 Features.push_back("+no-movt"); 452 453 if (Args.hasArg(options::OPT_mno_neg_immediates)) 454 Features.push_back("+no-neg-immediates"); 455 } 456 457 const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { 458 std::string MArch; 459 if (!Arch.empty()) 460 MArch = Arch; 461 else 462 MArch = Triple.getArchName(); 463 MArch = StringRef(MArch).split("+").first.lower(); 464 465 // Handle -march=native. 466 if (MArch == "native") { 467 std::string CPU = llvm::sys::getHostCPUName(); 468 if (CPU != "generic") { 469 // Translate the native cpu into the architecture suffix for that CPU. 470 StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple); 471 // If there is no valid architecture suffix for this CPU we don't know how 472 // to handle it, so return no architecture. 473 if (Suffix.empty()) 474 MArch = ""; 475 else 476 MArch = std::string("arm") + Suffix.str(); 477 } 478 } 479 480 return MArch; 481 } 482 483 /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. 484 StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) { 485 std::string MArch = getARMArch(Arch, Triple); 486 // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch 487 // here means an -march=native that we can't handle, so instead return no CPU. 488 if (MArch.empty()) 489 return StringRef(); 490 491 // We need to return an empty string here on invalid MArch values as the 492 // various places that call this function can't cope with a null result. 493 return Triple.getARMCPUForArch(MArch); 494 } 495 496 /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. 497 std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, 498 const llvm::Triple &Triple) { 499 // FIXME: Warn on inconsistent use of -mcpu and -march. 500 // If we have -mcpu=, use that. 501 if (!CPU.empty()) { 502 std::string MCPU = StringRef(CPU).split("+").first.lower(); 503 // Handle -mcpu=native. 504 if (MCPU == "native") 505 return llvm::sys::getHostCPUName(); 506 else 507 return MCPU; 508 } 509 510 return getARMCPUForMArch(Arch, Triple); 511 } 512 513 /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular 514 /// CPU (or Arch, if CPU is generic). 515 // FIXME: This is redundant with -mcpu, why does LLVM use this. 516 StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch, 517 const llvm::Triple &Triple) { 518 unsigned ArchKind; 519 if (CPU == "generic") { 520 std::string ARMArch = tools::arm::getARMArch(Arch, Triple); 521 ArchKind = llvm::ARM::parseArch(ARMArch); 522 if (ArchKind == llvm::ARM::AK_INVALID) 523 // In case of generic Arch, i.e. "arm", 524 // extract arch from default cpu of the Triple 525 ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch)); 526 } else { 527 // FIXME: horrible hack to get around the fact that Cortex-A7 is only an 528 // armv7k triple if it's actually been specified via "-arch armv7k". 529 ArchKind = (Arch == "armv7k" || Arch == "thumbv7k") 530 ? (unsigned)llvm::ARM::AK_ARMV7K 531 : llvm::ARM::parseCPUArch(CPU); 532 } 533 if (ArchKind == llvm::ARM::AK_INVALID) 534 return ""; 535 return llvm::ARM::getSubArch(ArchKind); 536 } 537 538 void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, 539 const llvm::Triple &Triple) { 540 if (Args.hasArg(options::OPT_r)) 541 return; 542 543 // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker 544 // to generate BE-8 executables. 545 if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple)) 546 CmdArgs.push_back("--be8"); 547 } 548