1 //===--- PPC.cpp - Implement PPC target feature support -------------------===// 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 // This file implements PPC TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "PPC.h" 14 #include "clang/Basic/Diagnostic.h" 15 #include "clang/Basic/MacroBuilder.h" 16 #include "clang/Basic/TargetBuiltins.h" 17 18 using namespace clang; 19 using namespace clang::targets; 20 21 const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { 22 #define BUILTIN(ID, TYPE, ATTRS) \ 23 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 24 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 25 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 26 #include "clang/Basic/BuiltinsPPC.def" 27 }; 28 29 /// handleTargetFeatures - Perform initialization based on the user 30 /// configured set of features. 31 bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 32 DiagnosticsEngine &Diags) { 33 FloatABI = HardFloat; 34 for (const auto &Feature : Features) { 35 if (Feature == "+altivec") { 36 HasAltivec = true; 37 } else if (Feature == "+vsx") { 38 HasVSX = true; 39 } else if (Feature == "+bpermd") { 40 HasBPERMD = true; 41 } else if (Feature == "+extdiv") { 42 HasExtDiv = true; 43 } else if (Feature == "+power8-vector") { 44 HasP8Vector = true; 45 } else if (Feature == "+crypto") { 46 HasP8Crypto = true; 47 } else if (Feature == "+direct-move") { 48 HasDirectMove = true; 49 } else if (Feature == "+qpx") { 50 HasQPX = true; 51 } else if (Feature == "+htm") { 52 HasHTM = true; 53 } else if (Feature == "+float128") { 54 HasFloat128 = true; 55 } else if (Feature == "+power9-vector") { 56 HasP9Vector = true; 57 } else if (Feature == "+spe") { 58 HasSPE = true; 59 LongDoubleWidth = LongDoubleAlign = 64; 60 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 61 } else if (Feature == "-hard-float") { 62 FloatABI = SoftFloat; 63 } 64 // TODO: Finish this list and add an assert that we've handled them 65 // all. 66 } 67 68 return true; 69 } 70 71 /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific 72 /// #defines that are not tied to a specific subtarget. 73 void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, 74 MacroBuilder &Builder) const { 75 // Target identification. 76 Builder.defineMacro("__ppc__"); 77 Builder.defineMacro("__PPC__"); 78 Builder.defineMacro("_ARCH_PPC"); 79 Builder.defineMacro("__powerpc__"); 80 Builder.defineMacro("__POWERPC__"); 81 if (PointerWidth == 64) { 82 Builder.defineMacro("_ARCH_PPC64"); 83 Builder.defineMacro("__powerpc64__"); 84 Builder.defineMacro("__ppc64__"); 85 Builder.defineMacro("__PPC64__"); 86 } 87 88 // Target properties. 89 if (getTriple().getArch() == llvm::Triple::ppc64le) { 90 Builder.defineMacro("_LITTLE_ENDIAN"); 91 } else { 92 if (!getTriple().isOSNetBSD() && 93 !getTriple().isOSOpenBSD()) 94 Builder.defineMacro("_BIG_ENDIAN"); 95 } 96 97 // ABI options. 98 if (ABI == "elfv1" || ABI == "elfv1-qpx") 99 Builder.defineMacro("_CALL_ELF", "1"); 100 if (ABI == "elfv2") 101 Builder.defineMacro("_CALL_ELF", "2"); 102 103 // This typically is only for a new enough linker (bfd >= 2.16.2 or gold), but 104 // our support post-dates this and it should work on all 64-bit ppc linux 105 // platforms. It is guaranteed to work on all elfv2 platforms. 106 if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64) 107 Builder.defineMacro("_CALL_LINUX", "1"); 108 109 // Subtarget options. 110 if (!getTriple().isOSAIX()){ 111 Builder.defineMacro("__NATURAL_ALIGNMENT__"); 112 } 113 Builder.defineMacro("__REGISTER_PREFIX__", ""); 114 115 // FIXME: Should be controlled by command line option. 116 if (LongDoubleWidth == 128) { 117 Builder.defineMacro("__LONG_DOUBLE_128__"); 118 Builder.defineMacro("__LONGDOUBLE128"); 119 } 120 121 // Define this for elfv2 (64-bit only) or 64-bit darwin. 122 if (ABI == "elfv2" || 123 (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64)) 124 Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16"); 125 126 if (ArchDefs & ArchDefineName) 127 Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper())); 128 if (ArchDefs & ArchDefinePpcgr) 129 Builder.defineMacro("_ARCH_PPCGR"); 130 if (ArchDefs & ArchDefinePpcsq) 131 Builder.defineMacro("_ARCH_PPCSQ"); 132 if (ArchDefs & ArchDefine440) 133 Builder.defineMacro("_ARCH_440"); 134 if (ArchDefs & ArchDefine603) 135 Builder.defineMacro("_ARCH_603"); 136 if (ArchDefs & ArchDefine604) 137 Builder.defineMacro("_ARCH_604"); 138 if (ArchDefs & ArchDefinePwr4) 139 Builder.defineMacro("_ARCH_PWR4"); 140 if (ArchDefs & ArchDefinePwr5) 141 Builder.defineMacro("_ARCH_PWR5"); 142 if (ArchDefs & ArchDefinePwr5x) 143 Builder.defineMacro("_ARCH_PWR5X"); 144 if (ArchDefs & ArchDefinePwr6) 145 Builder.defineMacro("_ARCH_PWR6"); 146 if (ArchDefs & ArchDefinePwr6x) 147 Builder.defineMacro("_ARCH_PWR6X"); 148 if (ArchDefs & ArchDefinePwr7) 149 Builder.defineMacro("_ARCH_PWR7"); 150 if (ArchDefs & ArchDefinePwr8) 151 Builder.defineMacro("_ARCH_PWR8"); 152 if (ArchDefs & ArchDefinePwr9) 153 Builder.defineMacro("_ARCH_PWR9"); 154 if (ArchDefs & ArchDefineA2) 155 Builder.defineMacro("_ARCH_A2"); 156 if (ArchDefs & ArchDefineA2q) { 157 Builder.defineMacro("_ARCH_A2Q"); 158 Builder.defineMacro("_ARCH_QP"); 159 } 160 161 if (getTriple().getVendor() == llvm::Triple::BGQ) { 162 Builder.defineMacro("__bg__"); 163 Builder.defineMacro("__THW_BLUEGENE__"); 164 Builder.defineMacro("__bgq__"); 165 Builder.defineMacro("__TOS_BGQ__"); 166 } 167 168 if (HasAltivec) { 169 Builder.defineMacro("__VEC__", "10206"); 170 Builder.defineMacro("__ALTIVEC__"); 171 } 172 if (HasSPE) { 173 Builder.defineMacro("__SPE__"); 174 Builder.defineMacro("__NO_FPRS__"); 175 } 176 if (HasVSX) 177 Builder.defineMacro("__VSX__"); 178 if (HasP8Vector) 179 Builder.defineMacro("__POWER8_VECTOR__"); 180 if (HasP8Crypto) 181 Builder.defineMacro("__CRYPTO__"); 182 if (HasHTM) 183 Builder.defineMacro("__HTM__"); 184 if (HasFloat128) 185 Builder.defineMacro("__FLOAT128__"); 186 if (HasP9Vector) 187 Builder.defineMacro("__POWER9_VECTOR__"); 188 189 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 190 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 191 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 192 if (PointerWidth == 64) 193 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 194 195 // We have support for the bswap intrinsics so we can define this. 196 Builder.defineMacro("__HAVE_BSWAP__", "1"); 197 198 // FIXME: The following are not yet generated here by Clang, but are 199 // generated by GCC: 200 // 201 // _SOFT_FLOAT_ 202 // __RECIP_PRECISION__ 203 // __APPLE_ALTIVEC__ 204 // __RECIP__ 205 // __RECIPF__ 206 // __RSQRTE__ 207 // __RSQRTEF__ 208 // _SOFT_DOUBLE_ 209 // __NO_LWSYNC__ 210 // __CMODEL_MEDIUM__ 211 // __CMODEL_LARGE__ 212 // _CALL_SYSV 213 // _CALL_DARWIN 214 } 215 216 // Handle explicit options being passed to the compiler here: if we've 217 // explicitly turned off vsx and turned on any of: 218 // - power8-vector 219 // - direct-move 220 // - float128 221 // - power9-vector 222 // then go ahead and error since the customer has expressed an incompatible 223 // set of options. 224 static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags, 225 const std::vector<std::string> &FeaturesVec) { 226 227 if (llvm::find(FeaturesVec, "-vsx") != FeaturesVec.end()) { 228 if (llvm::find(FeaturesVec, "+power8-vector") != FeaturesVec.end()) { 229 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector" 230 << "-mno-vsx"; 231 return false; 232 } 233 234 if (llvm::find(FeaturesVec, "+direct-move") != FeaturesVec.end()) { 235 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move" 236 << "-mno-vsx"; 237 return false; 238 } 239 240 if (llvm::find(FeaturesVec, "+float128") != FeaturesVec.end()) { 241 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" 242 << "-mno-vsx"; 243 return false; 244 } 245 246 if (llvm::find(FeaturesVec, "+power9-vector") != FeaturesVec.end()) { 247 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector" 248 << "-mno-vsx"; 249 return false; 250 } 251 } 252 253 return true; 254 } 255 256 bool PPCTargetInfo::initFeatureMap( 257 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 258 const std::vector<std::string> &FeaturesVec) const { 259 Features["altivec"] = llvm::StringSwitch<bool>(CPU) 260 .Case("7400", true) 261 .Case("g4", true) 262 .Case("7450", true) 263 .Case("g4+", true) 264 .Case("970", true) 265 .Case("g5", true) 266 .Case("pwr6", true) 267 .Case("pwr7", true) 268 .Case("pwr8", true) 269 .Case("pwr9", true) 270 .Case("ppc64", true) 271 .Case("ppc64le", true) 272 .Default(false); 273 274 Features["qpx"] = (CPU == "a2q"); 275 Features["power9-vector"] = (CPU == "pwr9"); 276 Features["crypto"] = llvm::StringSwitch<bool>(CPU) 277 .Case("ppc64le", true) 278 .Case("pwr9", true) 279 .Case("pwr8", true) 280 .Default(false); 281 Features["power8-vector"] = llvm::StringSwitch<bool>(CPU) 282 .Case("ppc64le", true) 283 .Case("pwr9", true) 284 .Case("pwr8", true) 285 .Default(false); 286 Features["bpermd"] = llvm::StringSwitch<bool>(CPU) 287 .Case("ppc64le", true) 288 .Case("pwr9", true) 289 .Case("pwr8", true) 290 .Case("pwr7", true) 291 .Default(false); 292 Features["extdiv"] = llvm::StringSwitch<bool>(CPU) 293 .Case("ppc64le", true) 294 .Case("pwr9", true) 295 .Case("pwr8", true) 296 .Case("pwr7", true) 297 .Default(false); 298 Features["direct-move"] = llvm::StringSwitch<bool>(CPU) 299 .Case("ppc64le", true) 300 .Case("pwr9", true) 301 .Case("pwr8", true) 302 .Default(false); 303 Features["vsx"] = llvm::StringSwitch<bool>(CPU) 304 .Case("ppc64le", true) 305 .Case("pwr9", true) 306 .Case("pwr8", true) 307 .Case("pwr7", true) 308 .Default(false); 309 Features["htm"] = llvm::StringSwitch<bool>(CPU) 310 .Case("ppc64le", true) 311 .Case("pwr9", true) 312 .Case("pwr8", true) 313 .Default(false); 314 315 if (!ppcUserFeaturesCheck(Diags, FeaturesVec)) 316 return false; 317 318 if (!(ArchDefs & ArchDefinePwr9) && (ArchDefs & ArchDefinePpcgr) && 319 llvm::find(FeaturesVec, "+float128") != FeaturesVec.end()) { 320 // We have __float128 on PPC but not power 9 and above. 321 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" << CPU; 322 return false; 323 } 324 325 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 326 } 327 328 bool PPCTargetInfo::hasFeature(StringRef Feature) const { 329 return llvm::StringSwitch<bool>(Feature) 330 .Case("powerpc", true) 331 .Case("altivec", HasAltivec) 332 .Case("vsx", HasVSX) 333 .Case("power8-vector", HasP8Vector) 334 .Case("crypto", HasP8Crypto) 335 .Case("direct-move", HasDirectMove) 336 .Case("qpx", HasQPX) 337 .Case("htm", HasHTM) 338 .Case("bpermd", HasBPERMD) 339 .Case("extdiv", HasExtDiv) 340 .Case("float128", HasFloat128) 341 .Case("power9-vector", HasP9Vector) 342 .Case("spe", HasSPE) 343 .Default(false); 344 } 345 346 void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, 347 StringRef Name, bool Enabled) const { 348 if (Enabled) { 349 // If we're enabling any of the vsx based features then enable vsx and 350 // altivec. We'll diagnose any problems later. 351 bool FeatureHasVSX = llvm::StringSwitch<bool>(Name) 352 .Case("vsx", true) 353 .Case("direct-move", true) 354 .Case("power8-vector", true) 355 .Case("power9-vector", true) 356 .Case("float128", true) 357 .Default(false); 358 if (FeatureHasVSX) 359 Features["vsx"] = Features["altivec"] = true; 360 if (Name == "power9-vector") 361 Features["power8-vector"] = true; 362 Features[Name] = true; 363 } else { 364 // If we're disabling altivec or vsx go ahead and disable all of the vsx 365 // features. 366 if ((Name == "altivec") || (Name == "vsx")) 367 Features["vsx"] = Features["direct-move"] = Features["power8-vector"] = 368 Features["float128"] = Features["power9-vector"] = false; 369 if (Name == "power8-vector") 370 Features["power9-vector"] = false; 371 Features[Name] = false; 372 } 373 } 374 375 const char *const PPCTargetInfo::GCCRegNames[] = { 376 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", 377 "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", 378 "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", 379 "r27", "r28", "r29", "r30", "r31", "f0", "f1", "f2", "f3", 380 "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", 381 "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", 382 "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", 383 "f31", "mq", "lr", "ctr", "ap", "cr0", "cr1", "cr2", "cr3", 384 "cr4", "cr5", "cr6", "cr7", "xer", "v0", "v1", "v2", "v3", 385 "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", 386 "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", 387 "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", 388 "v31", "vrsave", "vscr", "spe_acc", "spefscr", "sfp" 389 }; 390 391 ArrayRef<const char *> PPCTargetInfo::getGCCRegNames() const { 392 return llvm::makeArrayRef(GCCRegNames); 393 } 394 395 const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = { 396 // While some of these aliases do map to different registers 397 // they still share the same register name. 398 {{"0"}, "r0"}, {{"1"}, "r1"}, {{"2"}, "r2"}, {{"3"}, "r3"}, 399 {{"4"}, "r4"}, {{"5"}, "r5"}, {{"6"}, "r6"}, {{"7"}, "r7"}, 400 {{"8"}, "r8"}, {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"}, 401 {{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, {{"15"}, "r15"}, 402 {{"16"}, "r16"}, {{"17"}, "r17"}, {{"18"}, "r18"}, {{"19"}, "r19"}, 403 {{"20"}, "r20"}, {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"}, 404 {{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, {{"27"}, "r27"}, 405 {{"28"}, "r28"}, {{"29"}, "r29"}, {{"30"}, "r30"}, {{"31"}, "r31"}, 406 {{"fr0"}, "f0"}, {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"}, 407 {{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, {{"fr7"}, "f7"}, 408 {{"fr8"}, "f8"}, {{"fr9"}, "f9"}, {{"fr10"}, "f10"}, {{"fr11"}, "f11"}, 409 {{"fr12"}, "f12"}, {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"}, 410 {{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, {{"fr19"}, "f19"}, 411 {{"fr20"}, "f20"}, {{"fr21"}, "f21"}, {{"fr22"}, "f22"}, {{"fr23"}, "f23"}, 412 {{"fr24"}, "f24"}, {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"}, 413 {{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, {{"fr31"}, "f31"}, 414 {{"cc"}, "cr0"}, 415 }; 416 417 ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const { 418 return llvm::makeArrayRef(GCCRegAliases); 419 } 420 421 // PPC ELFABIv2 DWARF Definitoin "Table 2.26. Mappings of Common Registers". 422 // vs0 ~ vs31 is mapping to 32 - 63, 423 // vs32 ~ vs63 is mapping to 77 - 108. 424 const TargetInfo::AddlRegName GCCAddlRegNames[] = { 425 // Table of additional register names to use in user input. 426 {{"vs0"}, 32}, {{"vs1"}, 33}, {{"vs2"}, 34}, {{"vs3"}, 35}, 427 {{"vs4"}, 36}, {{"vs5"}, 37}, {{"vs6"}, 38}, {{"vs7"}, 39}, 428 {{"vs8"}, 40}, {{"vs9"}, 41}, {{"vs10"}, 42}, {{"vs11"}, 43}, 429 {{"vs12"}, 44}, {{"vs13"}, 45}, {{"vs14"}, 46}, {{"vs15"}, 47}, 430 {{"vs16"}, 48}, {{"vs17"}, 49}, {{"vs18"}, 50}, {{"vs19"}, 51}, 431 {{"vs20"}, 52}, {{"vs21"}, 53}, {{"vs22"}, 54}, {{"vs23"}, 55}, 432 {{"vs24"}, 56}, {{"vs25"}, 57}, {{"vs26"}, 58}, {{"vs27"}, 59}, 433 {{"vs28"}, 60}, {{"vs29"}, 61}, {{"vs30"}, 62}, {{"vs31"}, 63}, 434 {{"vs32"}, 77}, {{"vs33"}, 78}, {{"vs34"}, 79}, {{"vs35"}, 80}, 435 {{"vs36"}, 81}, {{"vs37"}, 82}, {{"vs38"}, 83}, {{"vs39"}, 84}, 436 {{"vs40"}, 85}, {{"vs41"}, 86}, {{"vs42"}, 87}, {{"vs43"}, 88}, 437 {{"vs44"}, 89}, {{"vs45"}, 90}, {{"vs46"}, 91}, {{"vs47"}, 92}, 438 {{"vs48"}, 93}, {{"vs49"}, 94}, {{"vs50"}, 95}, {{"vs51"}, 96}, 439 {{"vs52"}, 97}, {{"vs53"}, 98}, {{"vs54"}, 99}, {{"vs55"}, 100}, 440 {{"vs56"}, 101}, {{"vs57"}, 102}, {{"vs58"}, 103}, {{"vs59"}, 104}, 441 {{"vs60"}, 105}, {{"vs61"}, 106}, {{"vs62"}, 107}, {{"vs63"}, 108}, 442 }; 443 444 ArrayRef<TargetInfo::AddlRegName> PPCTargetInfo::getGCCAddlRegNames() const { 445 if (ABI == "elfv2") 446 return llvm::makeArrayRef(GCCAddlRegNames); 447 else 448 return TargetInfo::getGCCAddlRegNames(); 449 } 450 451 static constexpr llvm::StringLiteral ValidCPUNames[] = { 452 {"generic"}, {"440"}, {"450"}, {"601"}, {"602"}, 453 {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"}, 454 {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"}, 455 {"7450"}, {"g4+"}, {"750"}, {"970"}, {"g5"}, 456 {"a2"}, {"a2q"}, {"e500mc"}, {"e5500"}, {"power3"}, 457 {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"}, {"pwr5"}, 458 {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"}, {"power6x"}, 459 {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"}, {"pwr8"}, 460 {"power9"}, {"pwr9"}, {"powerpc"}, {"ppc"}, {"powerpc64"}, 461 {"ppc64"}, {"powerpc64le"}, {"ppc64le"}, 462 }; 463 464 bool PPCTargetInfo::isValidCPUName(StringRef Name) const { 465 return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames); 466 } 467 468 void PPCTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { 469 Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames)); 470 } 471 472 void PPCTargetInfo::adjust(LangOptions &Opts) { 473 if (HasAltivec) 474 Opts.AltiVec = 1; 475 TargetInfo::adjust(Opts); 476 if (LongDoubleFormat != &llvm::APFloat::IEEEdouble()) 477 LongDoubleFormat = Opts.PPCIEEELongDouble 478 ? &llvm::APFloat::IEEEquad() 479 : &llvm::APFloat::PPCDoubleDouble(); 480 } 481 482 ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const { 483 return llvm::makeArrayRef(BuiltinInfo, clang::PPC::LastTSBuiltin - 484 Builtin::FirstTSBuiltin); 485 } 486