1 //===--- AArch64.cpp - Implement AArch64 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 AArch64 TargetInfo objects. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AArch64.h" 15 #include "clang/Basic/TargetBuiltins.h" 16 #include "clang/Basic/TargetInfo.h" 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/StringExtras.h" 19 20 using namespace clang; 21 using namespace clang::targets; 22 23 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = { 24 #define BUILTIN(ID, TYPE, ATTRS) \ 25 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 26 #include "clang/Basic/BuiltinsNEON.def" 27 28 #define BUILTIN(ID, TYPE, ATTRS) \ 29 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 30 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ 31 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, 32 #include "clang/Basic/BuiltinsAArch64.def" 33 }; 34 35 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, 36 const TargetOptions &Opts) 37 : TargetInfo(Triple), ABI("aapcs") { 38 if (getTriple().getOS() == llvm::Triple::NetBSD || 39 getTriple().getOS() == llvm::Triple::OpenBSD) { 40 // NetBSD apparently prefers consistency across ARM targets to 41 // consistency across 64-bit targets. 42 Int64Type = SignedLongLong; 43 IntMaxType = SignedLongLong; 44 } else { 45 if (!getTriple().isOSDarwin()) 46 WCharType = UnsignedInt; 47 48 Int64Type = SignedLong; 49 IntMaxType = SignedLong; 50 } 51 52 53 LongWidth = LongAlign = PointerWidth = PointerAlign = 64; 54 MaxVectorAlign = 128; 55 MaxAtomicInlineWidth = 128; 56 MaxAtomicPromoteWidth = 128; 57 58 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128; 59 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 60 61 // Make __builtin_ms_va_list available. 62 HasBuiltinMSVaList = true; 63 64 // {} in inline assembly are neon specifiers, not assembly variant 65 // specifiers. 66 NoAsmVariants = true; 67 68 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type 69 // contributes to the alignment of the containing aggregate in the same way 70 // a plain (non bit-field) member of that type would, without exception for 71 // zero-sized or anonymous bit-fields." 72 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment"); 73 UseZeroLengthBitfieldAlignment = true; 74 75 // AArch64 targets default to using the ARM C++ ABI. 76 TheCXXABI.set(TargetCXXABI::GenericAArch64); 77 78 if (Triple.getOS() == llvm::Triple::Linux) 79 this->MCountName = "\01_mcount"; 80 else if (Triple.getOS() == llvm::Triple::UnknownOS) 81 this->MCountName = 82 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount"; 83 } 84 85 StringRef AArch64TargetInfo::getABI() const { return ABI; } 86 87 bool AArch64TargetInfo::setABI(const std::string &Name) { 88 if (Name != "aapcs" && Name != "darwinpcs") 89 return false; 90 91 ABI = Name; 92 return true; 93 } 94 95 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const { 96 return Name == "generic" || 97 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID; 98 } 99 100 bool AArch64TargetInfo::setCPU(const std::string &Name) { 101 return isValidCPUName(Name); 102 } 103 104 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, 105 MacroBuilder &Builder) const { 106 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); 107 } 108 109 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, 110 MacroBuilder &Builder) const { 111 // Also include the ARMv8.1 defines 112 getTargetDefinesARMV81A(Opts, Builder); 113 } 114 115 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, 116 MacroBuilder &Builder) const { 117 // Target identification. 118 Builder.defineMacro("__aarch64__"); 119 // For bare-metal none-eabi. 120 if (getTriple().getOS() == llvm::Triple::UnknownOS && 121 (getTriple().getEnvironment() == llvm::Triple::EABI || 122 getTriple().getEnvironment() == llvm::Triple::EABIHF)) 123 Builder.defineMacro("__ELF__"); 124 125 // Target properties. 126 if (!getTriple().isOSWindows()) { 127 Builder.defineMacro("_LP64"); 128 Builder.defineMacro("__LP64__"); 129 } 130 131 // ACLE predefines. Many can only have one possible value on v8 AArch64. 132 Builder.defineMacro("__ARM_ACLE", "200"); 133 Builder.defineMacro("__ARM_ARCH", "8"); 134 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); 135 136 Builder.defineMacro("__ARM_64BIT_STATE", "1"); 137 Builder.defineMacro("__ARM_PCS_AAPCS64", "1"); 138 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1"); 139 140 Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); 141 Builder.defineMacro("__ARM_FEATURE_FMA", "1"); 142 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF"); 143 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE 144 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility 145 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); 146 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); 147 148 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); 149 150 // 0xe implies support for half, single and double precision operations. 151 Builder.defineMacro("__ARM_FP", "0xE"); 152 153 // PCS specifies this for SysV variants, which is all we support. Other ABIs 154 // may choose __ARM_FP16_FORMAT_ALTERNATIVE. 155 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); 156 Builder.defineMacro("__ARM_FP16_ARGS", "1"); 157 158 if (Opts.UnsafeFPMath) 159 Builder.defineMacro("__ARM_FP_FAST", "1"); 160 161 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", 162 Twine(Opts.WCharSize ? Opts.WCharSize : 4)); 163 164 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); 165 166 if (FPU & NeonMode) { 167 Builder.defineMacro("__ARM_NEON", "1"); 168 // 64-bit NEON supports half, single and double precision operations. 169 Builder.defineMacro("__ARM_NEON_FP", "0xE"); 170 } 171 172 if (FPU & SveMode) 173 Builder.defineMacro("__ARM_FEATURE_SVE", "1"); 174 175 if (CRC) 176 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 177 178 if (Crypto) 179 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 180 181 if (Unaligned) 182 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 183 184 if ((FPU & NeonMode) && HasFullFP16) 185 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); 186 187 switch (ArchKind) { 188 default: 189 break; 190 case llvm::AArch64::ArchKind::ARMV8_1A: 191 getTargetDefinesARMV81A(Opts, Builder); 192 break; 193 case llvm::AArch64::ArchKind::ARMV8_2A: 194 getTargetDefinesARMV82A(Opts, Builder); 195 break; 196 } 197 198 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. 199 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 200 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 201 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 202 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 203 } 204 205 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { 206 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - 207 Builtin::FirstTSBuiltin); 208 } 209 210 bool AArch64TargetInfo::hasFeature(StringRef Feature) const { 211 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" || 212 (Feature == "neon" && (FPU & NeonMode)) || 213 (Feature == "sve" && (FPU & SveMode)); 214 } 215 216 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 217 DiagnosticsEngine &Diags) { 218 FPU = FPUMode; 219 CRC = 0; 220 Crypto = 0; 221 Unaligned = 1; 222 HasFullFP16 = 0; 223 ArchKind = llvm::AArch64::ArchKind::ARMV8A; 224 225 for (const auto &Feature : Features) { 226 if (Feature == "+neon") 227 FPU |= NeonMode; 228 if (Feature == "+sve") 229 FPU |= SveMode; 230 if (Feature == "+crc") 231 CRC = 1; 232 if (Feature == "+crypto") 233 Crypto = 1; 234 if (Feature == "+strict-align") 235 Unaligned = 0; 236 if (Feature == "+v8.1a") 237 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A; 238 if (Feature == "+v8.2a") 239 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A; 240 if (Feature == "+fullfp16") 241 HasFullFP16 = 1; 242 } 243 244 setDataLayout(); 245 246 return true; 247 } 248 249 TargetInfo::CallingConvCheckResult 250 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { 251 switch (CC) { 252 case CC_C: 253 case CC_Swift: 254 case CC_PreserveMost: 255 case CC_PreserveAll: 256 case CC_OpenCLKernel: 257 case CC_Win64: 258 return CCCR_OK; 259 default: 260 return CCCR_Warning; 261 } 262 } 263 264 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } 265 266 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { 267 return TargetInfo::AArch64ABIBuiltinVaList; 268 } 269 270 const char *const AArch64TargetInfo::GCCRegNames[] = { 271 // 32-bit Integer registers 272 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", 273 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22", 274 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", 275 276 // 64-bit Integer registers 277 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", 278 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", 279 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", 280 281 // 32-bit floating point regsisters 282 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 283 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 284 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 285 286 // 64-bit floating point regsisters 287 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 288 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 289 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 290 291 // Vector registers 292 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", 293 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", 294 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" 295 }; 296 297 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { 298 return llvm::makeArrayRef(GCCRegNames); 299 } 300 301 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { 302 {{"w31"}, "wsp"}, 303 {{"x31"}, "sp"}, 304 // GCC rN registers are aliases of xN registers. 305 {{"r0"}, "x0"}, 306 {{"r1"}, "x1"}, 307 {{"r2"}, "x2"}, 308 {{"r3"}, "x3"}, 309 {{"r4"}, "x4"}, 310 {{"r5"}, "x5"}, 311 {{"r6"}, "x6"}, 312 {{"r7"}, "x7"}, 313 {{"r8"}, "x8"}, 314 {{"r9"}, "x9"}, 315 {{"r10"}, "x10"}, 316 {{"r11"}, "x11"}, 317 {{"r12"}, "x12"}, 318 {{"r13"}, "x13"}, 319 {{"r14"}, "x14"}, 320 {{"r15"}, "x15"}, 321 {{"r16"}, "x16"}, 322 {{"r17"}, "x17"}, 323 {{"r18"}, "x18"}, 324 {{"r19"}, "x19"}, 325 {{"r20"}, "x20"}, 326 {{"r21"}, "x21"}, 327 {{"r22"}, "x22"}, 328 {{"r23"}, "x23"}, 329 {{"r24"}, "x24"}, 330 {{"r25"}, "x25"}, 331 {{"r26"}, "x26"}, 332 {{"r27"}, "x27"}, 333 {{"r28"}, "x28"}, 334 {{"r29", "x29"}, "fp"}, 335 {{"r30", "x30"}, "lr"}, 336 // The S/D/Q and W/X registers overlap, but aren't really aliases; we 337 // don't want to substitute one of these for a different-sized one. 338 }; 339 340 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { 341 return llvm::makeArrayRef(GCCRegAliases); 342 } 343 344 bool AArch64TargetInfo::validateAsmConstraint( 345 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 346 switch (*Name) { 347 default: 348 return false; 349 case 'w': // Floating point and SIMD registers (V0-V31) 350 Info.setAllowsRegister(); 351 return true; 352 case 'I': // Constant that can be used with an ADD instruction 353 case 'J': // Constant that can be used with a SUB instruction 354 case 'K': // Constant that can be used with a 32-bit logical instruction 355 case 'L': // Constant that can be used with a 64-bit logical instruction 356 case 'M': // Constant that can be used as a 32-bit MOV immediate 357 case 'N': // Constant that can be used as a 64-bit MOV immediate 358 case 'Y': // Floating point constant zero 359 case 'Z': // Integer constant zero 360 return true; 361 case 'Q': // A memory reference with base register and no offset 362 Info.setAllowsMemory(); 363 return true; 364 case 'S': // A symbolic address 365 Info.setAllowsRegister(); 366 return true; 367 case 'U': 368 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. 369 // Utf: A memory address suitable for ldp/stp in TF mode. 370 // Usa: An absolute symbolic address. 371 // Ush: The high part (bits 32:12) of a pc-relative symbolic address. 372 llvm_unreachable("FIXME: Unimplemented support for U* constraints."); 373 case 'z': // Zero register, wzr or xzr 374 Info.setAllowsRegister(); 375 return true; 376 case 'x': // Floating point and SIMD registers (V0-V15) 377 Info.setAllowsRegister(); 378 return true; 379 } 380 return false; 381 } 382 383 bool AArch64TargetInfo::validateConstraintModifier( 384 StringRef Constraint, char Modifier, unsigned Size, 385 std::string &SuggestedModifier) const { 386 // Strip off constraint modifiers. 387 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 388 Constraint = Constraint.substr(1); 389 390 switch (Constraint[0]) { 391 default: 392 return true; 393 case 'z': 394 case 'r': { 395 switch (Modifier) { 396 case 'x': 397 case 'w': 398 // For now assume that the person knows what they're 399 // doing with the modifier. 400 return true; 401 default: 402 // By default an 'r' constraint will be in the 'x' 403 // registers. 404 if (Size == 64) 405 return true; 406 407 SuggestedModifier = "w"; 408 return false; 409 } 410 } 411 } 412 } 413 414 const char *AArch64TargetInfo::getClobbers() const { return ""; } 415 416 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 417 if (RegNo == 0) 418 return 0; 419 if (RegNo == 1) 420 return 1; 421 return -1; 422 } 423 424 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, 425 const TargetOptions &Opts) 426 : AArch64TargetInfo(Triple, Opts) {} 427 428 void AArch64leTargetInfo::setDataLayout() { 429 if (getTriple().isOSBinFormatMachO()) 430 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); 431 else 432 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 433 } 434 435 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, 436 MacroBuilder &Builder) const { 437 Builder.defineMacro("__AARCH64EL__"); 438 AArch64TargetInfo::getTargetDefines(Opts, Builder); 439 } 440 441 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, 442 const TargetOptions &Opts) 443 : AArch64TargetInfo(Triple, Opts) {} 444 445 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, 446 MacroBuilder &Builder) const { 447 Builder.defineMacro("__AARCH64EB__"); 448 Builder.defineMacro("__AARCH_BIG_ENDIAN"); 449 Builder.defineMacro("__ARM_BIG_ENDIAN"); 450 AArch64TargetInfo::getTargetDefines(Opts, Builder); 451 } 452 453 void AArch64beTargetInfo::setDataLayout() { 454 assert(!getTriple().isOSBinFormatMachO()); 455 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); 456 } 457 458 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, 459 const TargetOptions &Opts) 460 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { 461 462 // This is an LLP64 platform. 463 // int:4, long:4, long long:8, long double:8. 464 IntWidth = IntAlign = 32; 465 LongWidth = LongAlign = 32; 466 DoubleAlign = LongLongAlign = 64; 467 LongDoubleWidth = LongDoubleAlign = 64; 468 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 469 IntMaxType = SignedLongLong; 470 Int64Type = SignedLongLong; 471 SizeType = UnsignedLongLong; 472 PtrDiffType = SignedLongLong; 473 IntPtrType = SignedLongLong; 474 } 475 476 void WindowsARM64TargetInfo::setDataLayout() { 477 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); 478 } 479 480 TargetInfo::BuiltinVaListKind 481 WindowsARM64TargetInfo::getBuiltinVaListKind() const { 482 return TargetInfo::CharPtrBuiltinVaList; 483 } 484 485 TargetInfo::CallingConvCheckResult 486 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { 487 switch (CC) { 488 case CC_X86StdCall: 489 case CC_X86ThisCall: 490 case CC_X86FastCall: 491 case CC_X86VectorCall: 492 return CCCR_Ignore; 493 case CC_C: 494 case CC_OpenCLKernel: 495 case CC_PreserveMost: 496 case CC_PreserveAll: 497 case CC_Win64: 498 return CCCR_OK; 499 default: 500 return CCCR_Warning; 501 } 502 } 503 504 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, 505 const TargetOptions &Opts) 506 : WindowsARM64TargetInfo(Triple, Opts) { 507 TheCXXABI.set(TargetCXXABI::Microsoft); 508 } 509 510 void MicrosoftARM64TargetInfo::getVisualStudioDefines( 511 const LangOptions &Opts, MacroBuilder &Builder) const { 512 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder); 513 Builder.defineMacro("_M_ARM64", "1"); 514 } 515 516 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, 517 MacroBuilder &Builder) const { 518 WindowsTargetInfo::getTargetDefines(Opts, Builder); 519 getVisualStudioDefines(Opts, Builder); 520 } 521 522 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, 523 const TargetOptions &Opts) 524 : WindowsARM64TargetInfo(Triple, Opts) { 525 TheCXXABI.set(TargetCXXABI::GenericAArch64); 526 } 527 528 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, 529 const TargetOptions &Opts) 530 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { 531 Int64Type = SignedLongLong; 532 UseSignedCharForObjCBool = false; 533 534 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; 535 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 536 537 TheCXXABI.set(TargetCXXABI::iOS64); 538 } 539 540 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, 541 const llvm::Triple &Triple, 542 MacroBuilder &Builder) const { 543 Builder.defineMacro("__AARCH64_SIMD__"); 544 Builder.defineMacro("__ARM64_ARCH_8__"); 545 Builder.defineMacro("__ARM_NEON__"); 546 Builder.defineMacro("__LITTLE_ENDIAN__"); 547 Builder.defineMacro("__REGISTER_PREFIX__", ""); 548 Builder.defineMacro("__arm64", "1"); 549 Builder.defineMacro("__arm64__", "1"); 550 551 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 552 } 553 554 TargetInfo::BuiltinVaListKind 555 DarwinAArch64TargetInfo::getBuiltinVaListKind() const { 556 return TargetInfo::CharPtrBuiltinVaList; 557 } 558 559 // 64-bit RenderScript is aarch64 560 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, 561 const TargetOptions &Opts) 562 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), 563 Triple.getOSName(), 564 Triple.getEnvironmentName()), 565 Opts) { 566 IsRenderScriptTarget = true; 567 } 568 569 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, 570 MacroBuilder &Builder) const { 571 Builder.defineMacro("__RENDERSCRIPT__"); 572 AArch64leTargetInfo::getTargetDefines(Opts, Builder); 573 } 574