1 //===--- ARM.cpp - Implement ARM target feature support -------------------===// 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 // This file implements ARM TargetInfo objects. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ARM.h" 15 #include "clang/Basic/Builtins.h" 16 #include "clang/Basic/Diagnostic.h" 17 #include "clang/Basic/TargetBuiltins.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/ADT/StringSwitch.h" 21 22 using namespace clang; 23 using namespace clang::targets; 24 25 bool ARMTargetInfo::setFPMath(StringRef Name) { 26 if (Name == "neon") { 27 FPMath = FP_Neon; 28 return true; 29 } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" || 30 Name == "vfp4") { 31 FPMath = FP_VFP; 32 return true; 33 } 34 return false; 35 } 36 37 const char *const ARMTargetInfo::GCCRegNames[] = { 38 // Integer registers 39 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", 40 "r12", "sp", "lr", "pc", 41 42 // Float registers 43 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 44 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 45 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 46 47 // Double registers 48 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 49 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 50 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 51 52 // Quad registers 53 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", 54 "q12", "q13", "q14", "q15" 55 }; 56 57 ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const { 58 return llvm::makeArrayRef(GCCRegNames); 59 } 60 61 const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { 62 {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"}, 63 {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"}, 64 {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"}, 65 {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"}, 66 // The S, D and Q registers overlap, but aren't really aliases; we 67 // don't want to substitute one of these for a different-sized one. 68 }; 69 70 ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const { 71 return llvm::makeArrayRef(GCCRegAliases); 72 } 73 74 const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { 75 #define BUILTIN(ID, TYPE, ATTRS) \ 76 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 77 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 78 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 79 #include "clang/Basic/BuiltinsNEON.def" 80 81 #define BUILTIN(ID, TYPE, ATTRS) \ 82 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 83 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ 84 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, 85 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 86 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 87 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ 88 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, 89 #include "clang/Basic/BuiltinsARM.def" 90 }; 91 92 bool ARMTargetInfo::hasFeature(StringRef Feature) const { 93 return llvm::StringSwitch<bool>(Feature) 94 .Case("arm", true) 95 .Case("aarch32", true) 96 .Case("softfloat", SoftFloat) 97 .Case("thumb", isThumb()) 98 .Case("neon", (FPU & NeonFPU) && !SoftFloat) 99 .Case("vfp", FPU && !SoftFloat) 100 .Case("hwdiv", HWDiv & HWDivThumb) 101 .Case("hwdiv-arm", HWDiv & HWDivARM) 102 .Default(false); 103 } 104 105 void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, 106 MacroBuilder &Builder) const { 107 // Target identification. 108 Builder.defineMacro("__arm"); 109 Builder.defineMacro("__arm__"); 110 // For bare-metal none-eabi. 111 if (getTriple().getOS() == llvm::Triple::UnknownOS && 112 (getTriple().getEnvironment() == llvm::Triple::EABI || 113 getTriple().getEnvironment() == llvm::Triple::EABIHF)) 114 Builder.defineMacro("__ELF__"); 115 116 // Target properties. 117 Builder.defineMacro("__REGISTER_PREFIX__", ""); 118 119 // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU 120 // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__. 121 if (getTriple().isWatchABI()) 122 Builder.defineMacro("__ARM_ARCH_7K__", "2"); 123 124 if (!CPUAttr.empty()) 125 Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__"); 126 127 // ACLE 6.4.1 ARM/Thumb instruction set architecture 128 // __ARM_ARCH is defined as an integer value indicating the current ARM ISA 129 Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion)); 130 131 if (ArchVersion >= 8) { 132 // ACLE 6.5.7 Crypto Extension 133 if (Crypto) 134 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 135 // ACLE 6.5.8 CRC32 Extension 136 if (CRC) 137 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 138 // ACLE 6.5.10 Numeric Maximum and Minimum 139 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); 140 // ACLE 6.5.9 Directed Rounding 141 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); 142 } 143 144 // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It 145 // is not defined for the M-profile. 146 // NOTE that the default profile is assumed to be 'A' 147 if (CPUProfile.empty() || ArchProfile != llvm::ARM::PK_M) 148 Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1"); 149 150 // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original 151 // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the 152 // core supports the Thumb-2 ISA as found in the v6T2 architecture and all 153 // v7 and v8 architectures excluding v8-M Baseline. 154 if (supportsThumb2()) 155 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2"); 156 else if (supportsThumb()) 157 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1"); 158 159 // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit 160 // instruction set such as ARM or Thumb. 161 Builder.defineMacro("__ARM_32BIT_STATE", "1"); 162 163 // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) 164 165 // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. 166 if (!CPUProfile.empty()) 167 Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); 168 169 // ACLE 6.4.3 Unaligned access supported in hardware 170 if (Unaligned) 171 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 172 173 // ACLE 6.4.4 LDREX/STREX 174 if (LDREX) 175 Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX)); 176 177 // ACLE 6.4.5 CLZ 178 if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") || 179 ArchVersion > 6) 180 Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); 181 182 // ACLE 6.5.1 Hardware Floating Point 183 if (HW_FP) 184 Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP)); 185 186 // ACLE predefines. 187 Builder.defineMacro("__ARM_ACLE", "200"); 188 189 // FP16 support (we currently only support IEEE format). 190 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); 191 Builder.defineMacro("__ARM_FP16_ARGS", "1"); 192 193 // ACLE 6.5.3 Fused multiply-accumulate (FMA) 194 if (ArchVersion >= 7 && (FPU & VFP4FPU)) 195 Builder.defineMacro("__ARM_FEATURE_FMA", "1"); 196 197 // Subtarget options. 198 199 // FIXME: It's more complicated than this and we don't really support 200 // interworking. 201 // Windows on ARM does not "support" interworking 202 if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows()) 203 Builder.defineMacro("__THUMB_INTERWORK__"); 204 205 if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") { 206 // Embedded targets on Darwin follow AAPCS, but not EABI. 207 // Windows on ARM follows AAPCS VFP, but does not conform to EABI. 208 if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows()) 209 Builder.defineMacro("__ARM_EABI__"); 210 Builder.defineMacro("__ARM_PCS", "1"); 211 } 212 213 if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16") 214 Builder.defineMacro("__ARM_PCS_VFP", "1"); 215 216 if (SoftFloat) 217 Builder.defineMacro("__SOFTFP__"); 218 219 if (ArchKind == llvm::ARM::AK_XSCALE) 220 Builder.defineMacro("__XSCALE__"); 221 222 if (isThumb()) { 223 Builder.defineMacro("__THUMBEL__"); 224 Builder.defineMacro("__thumb__"); 225 if (supportsThumb2()) 226 Builder.defineMacro("__thumb2__"); 227 } 228 229 // ACLE 6.4.9 32-bit SIMD instructions 230 if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM")) 231 Builder.defineMacro("__ARM_FEATURE_SIMD32", "1"); 232 233 // ACLE 6.4.10 Hardware Integer Divide 234 if (((HWDiv & HWDivThumb) && isThumb()) || 235 ((HWDiv & HWDivARM) && !isThumb())) { 236 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); 237 Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1"); 238 } 239 240 // Note, this is always on in gcc, even though it doesn't make sense. 241 Builder.defineMacro("__APCS_32__"); 242 243 if (FPUModeIsVFP((FPUMode)FPU)) { 244 Builder.defineMacro("__VFP_FP__"); 245 if (FPU & VFP2FPU) 246 Builder.defineMacro("__ARM_VFPV2__"); 247 if (FPU & VFP3FPU) 248 Builder.defineMacro("__ARM_VFPV3__"); 249 if (FPU & VFP4FPU) 250 Builder.defineMacro("__ARM_VFPV4__"); 251 if (FPU & FPARMV8) 252 Builder.defineMacro("__ARM_FPV5__"); 253 } 254 255 // This only gets set when Neon instructions are actually available, unlike 256 // the VFP define, hence the soft float and arch check. This is subtly 257 // different from gcc, we follow the intent which was that it should be set 258 // when Neon instructions are actually available. 259 if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) { 260 Builder.defineMacro("__ARM_NEON", "1"); 261 Builder.defineMacro("__ARM_NEON__"); 262 // current AArch32 NEON implementations do not support double-precision 263 // floating-point even when it is present in VFP. 264 Builder.defineMacro("__ARM_NEON_FP", 265 "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP)); 266 } 267 268 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); 269 270 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); 271 272 if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") { 273 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 274 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 275 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 276 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 277 } 278 279 // ACLE 6.4.7 DSP instructions 280 if (DSP) { 281 Builder.defineMacro("__ARM_FEATURE_DSP", "1"); 282 } 283 284 // ACLE 6.4.8 Saturation instructions 285 bool SAT = false; 286 if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) { 287 Builder.defineMacro("__ARM_FEATURE_SAT", "1"); 288 SAT = true; 289 } 290 291 // ACLE 6.4.6 Q (saturation) flag 292 if (DSP || SAT) 293 Builder.defineMacro("__ARM_FEATURE_QBIT", "1"); 294 295 if (Opts.UnsafeFPMath) 296 Builder.defineMacro("__ARM_FP_FAST", "1"); 297 298 switch (ArchKind) { 299 default: 300 break; 301 case llvm::ARM::AK_ARMV8_1A: 302 getTargetDefinesARMV81A(Opts, Builder); 303 break; 304 case llvm::ARM::AK_ARMV8_2A: 305 getTargetDefinesARMV82A(Opts, Builder); 306 break; 307 } 308 } 309 310 bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 311 DiagnosticsEngine &Diags) { 312 FPU = 0; 313 CRC = 0; 314 Crypto = 0; 315 DSP = 0; 316 Unaligned = 1; 317 SoftFloat = SoftFloatABI = false; 318 HWDiv = 0; 319 320 // This does not diagnose illegal cases like having both 321 // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". 322 uint32_t HW_FP_remove = 0; 323 for (const auto &Feature : Features) { 324 if (Feature == "+soft-float") { 325 SoftFloat = true; 326 } else if (Feature == "+soft-float-abi") { 327 SoftFloatABI = true; 328 } else if (Feature == "+vfp2") { 329 FPU |= VFP2FPU; 330 HW_FP |= HW_FP_SP | HW_FP_DP; 331 } else if (Feature == "+vfp3") { 332 FPU |= VFP3FPU; 333 HW_FP |= HW_FP_SP | HW_FP_DP; 334 } else if (Feature == "+vfp4") { 335 FPU |= VFP4FPU; 336 HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; 337 } else if (Feature == "+fp-armv8") { 338 FPU |= FPARMV8; 339 HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; 340 } else if (Feature == "+neon") { 341 FPU |= NeonFPU; 342 HW_FP |= HW_FP_SP | HW_FP_DP; 343 } else if (Feature == "+hwdiv") { 344 HWDiv |= HWDivThumb; 345 } else if (Feature == "+hwdiv-arm") { 346 HWDiv |= HWDivARM; 347 } else if (Feature == "+crc") { 348 CRC = 1; 349 } else if (Feature == "+crypto") { 350 Crypto = 1; 351 } else if (Feature == "+dsp") { 352 DSP = 1; 353 } else if (Feature == "+fp-only-sp") { 354 HW_FP_remove |= HW_FP_DP; 355 } else if (Feature == "+strict-align") { 356 Unaligned = 0; 357 } else if (Feature == "+fp16") { 358 HW_FP |= HW_FP_HP; 359 } 360 } 361 HW_FP &= ~HW_FP_remove; 362 363 switch (ArchVersion) { 364 case 6: 365 if (ArchProfile == llvm::ARM::PK_M) 366 LDREX = 0; 367 else if (ArchKind == llvm::ARM::AK_ARMV6K) 368 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 369 else 370 LDREX = LDREX_W; 371 break; 372 case 7: 373 if (ArchProfile == llvm::ARM::PK_M) 374 LDREX = LDREX_W | LDREX_H | LDREX_B; 375 else 376 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 377 break; 378 case 8: 379 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 380 } 381 382 if (!(FPU & NeonFPU) && FPMath == FP_Neon) { 383 Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; 384 return false; 385 } 386 387 if (FPMath == FP_Neon) 388 Features.push_back("+neonfp"); 389 else if (FPMath == FP_VFP) 390 Features.push_back("-neonfp"); 391 392 // Remove front-end specific options which the backend handles differently. 393 auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi"); 394 if (Feature != Features.end()) 395 Features.erase(Feature); 396 397 return true; 398 } 399 400 void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, 401 MacroBuilder &Builder) const { 402 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); 403 } 404 405 void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts, 406 MacroBuilder &Builder) const { 407 Builder.defineMacro("__ARMEL__"); 408 ARMTargetInfo::getTargetDefines(Opts, Builder); 409 } 410 411 void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, 412 MacroBuilder &Builder) const { 413 Builder.defineMacro("__ARMEB__"); 414 Builder.defineMacro("__ARM_BIG_ENDIAN"); 415 ARMTargetInfo::getTargetDefines(Opts, Builder); 416 } 417 418 void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, 419 MacroBuilder &Builder) const { 420 WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder); 421 422 // FIXME: this is invalid for WindowsCE 423 Builder.defineMacro("_M_ARM_NT", "1"); 424 Builder.defineMacro("_M_ARMT", "_M_ARM"); 425 Builder.defineMacro("_M_THUMB", "_M_ARM"); 426 427 assert((Triple.getArch() == llvm::Triple::arm || 428 Triple.getArch() == llvm::Triple::thumb) && 429 "invalid architecture for Windows ARM target info"); 430 unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6; 431 Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset)); 432 433 // TODO map the complete set of values 434 // 31: VFPv3 40: VFPv4 435 Builder.defineMacro("_M_ARM_FP", "31"); 436 } 437 438 void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, 439 MacroBuilder &Builder) const { 440 WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 441 DefineStd(Builder, "WIN32", Opts); 442 DefineStd(Builder, "WINNT", Opts); 443 Builder.defineMacro("_ARM_"); 444 addMinGWDefines(Opts, Builder); 445 } 446 447 void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, 448 MacroBuilder &Builder) const { 449 ARMleTargetInfo::getTargetDefines(Opts, Builder); 450 Builder.defineMacro("_ARM_"); 451 Builder.defineMacro("__CYGWIN__"); 452 Builder.defineMacro("__CYGWIN32__"); 453 DefineStd(Builder, "unix", Opts); 454 if (Opts.CPlusPlus) 455 Builder.defineMacro("_GNU_SOURCE"); 456 } 457 458 void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts, 459 MacroBuilder &Builder) const { 460 Builder.defineMacro("__RENDERSCRIPT__"); 461 ARMleTargetInfo::getTargetDefines(Opts, Builder); 462 } 463 464 ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const { 465 return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin - 466 Builtin::FirstTSBuiltin); 467 } 468