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 static constexpr Builtin::Info BuiltinInfo[] = { 22 #define BUILTIN(ID, TYPE, ATTRS) \ 23 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 24 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 25 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 26 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 27 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, 28 #include "clang/Basic/BuiltinsPPC.def" 29 }; 30 31 /// handleTargetFeatures - Perform initialization based on the user 32 /// configured set of features. 33 bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 34 DiagnosticsEngine &Diags) { 35 FloatABI = HardFloat; 36 for (const auto &Feature : Features) { 37 if (Feature == "+altivec") { 38 HasAltivec = true; 39 } else if (Feature == "+vsx") { 40 HasVSX = true; 41 } else if (Feature == "+crbits") { 42 UseCRBits = true; 43 } else if (Feature == "+bpermd") { 44 HasBPERMD = true; 45 } else if (Feature == "+extdiv") { 46 HasExtDiv = true; 47 } else if (Feature == "+power8-vector") { 48 HasP8Vector = true; 49 } else if (Feature == "+crypto") { 50 HasP8Crypto = true; 51 } else if (Feature == "+direct-move") { 52 HasDirectMove = true; 53 } else if (Feature == "+htm") { 54 HasHTM = true; 55 } else if (Feature == "+float128") { 56 HasFloat128 = !getTriple().isOSAIX(); 57 } else if (Feature == "+power9-vector") { 58 HasP9Vector = true; 59 } else if (Feature == "+power10-vector") { 60 HasP10Vector = true; 61 } else if (Feature == "+pcrelative-memops") { 62 HasPCRelativeMemops = true; 63 } else if (Feature == "+prefix-instrs") { 64 HasPrefixInstrs = true; 65 } else if (Feature == "+spe" || Feature == "+efpu2") { 66 HasStrictFP = false; 67 HasSPE = true; 68 LongDoubleWidth = LongDoubleAlign = 64; 69 LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 70 } else if (Feature == "-hard-float") { 71 FloatABI = SoftFloat; 72 } else if (Feature == "+paired-vector-memops") { 73 PairedVectorMemops = true; 74 } else if (Feature == "+mma") { 75 HasMMA = true; 76 } else if (Feature == "+rop-protect") { 77 HasROPProtect = true; 78 } else if (Feature == "+privileged") { 79 HasPrivileged = true; 80 } else if (Feature == "+aix-small-local-exec-tls") { 81 HasAIXSmallLocalExecTLS = true; 82 } else if (Feature == "+isa-v206-instructions") { 83 IsISA2_06 = true; 84 } else if (Feature == "+isa-v207-instructions") { 85 IsISA2_07 = true; 86 } else if (Feature == "+isa-v30-instructions") { 87 IsISA3_0 = true; 88 } else if (Feature == "+isa-v31-instructions") { 89 IsISA3_1 = true; 90 } else if (Feature == "+quadword-atomics") { 91 HasQuadwordAtomics = true; 92 } 93 // TODO: Finish this list and add an assert that we've handled them 94 // all. 95 } 96 97 return true; 98 } 99 100 static void defineXLCompatMacros(MacroBuilder &Builder) { 101 Builder.defineMacro("__popcntb", "__builtin_ppc_popcntb"); 102 Builder.defineMacro("__poppar4", "__builtin_ppc_poppar4"); 103 Builder.defineMacro("__poppar8", "__builtin_ppc_poppar8"); 104 Builder.defineMacro("__eieio", "__builtin_ppc_eieio"); 105 Builder.defineMacro("__iospace_eieio", "__builtin_ppc_iospace_eieio"); 106 Builder.defineMacro("__isync", "__builtin_ppc_isync"); 107 Builder.defineMacro("__lwsync", "__builtin_ppc_lwsync"); 108 Builder.defineMacro("__iospace_lwsync", "__builtin_ppc_iospace_lwsync"); 109 Builder.defineMacro("__sync", "__builtin_ppc_sync"); 110 Builder.defineMacro("__iospace_sync", "__builtin_ppc_iospace_sync"); 111 Builder.defineMacro("__dcbfl", "__builtin_ppc_dcbfl"); 112 Builder.defineMacro("__dcbflp", "__builtin_ppc_dcbflp"); 113 Builder.defineMacro("__dcbst", "__builtin_ppc_dcbst"); 114 Builder.defineMacro("__dcbt", "__builtin_ppc_dcbt"); 115 Builder.defineMacro("__dcbtst", "__builtin_ppc_dcbtst"); 116 Builder.defineMacro("__dcbz", "__builtin_ppc_dcbz"); 117 Builder.defineMacro("__icbt", "__builtin_ppc_icbt"); 118 Builder.defineMacro("__compare_and_swap", "__builtin_ppc_compare_and_swap"); 119 Builder.defineMacro("__compare_and_swaplp", 120 "__builtin_ppc_compare_and_swaplp"); 121 Builder.defineMacro("__fetch_and_add", "__builtin_ppc_fetch_and_add"); 122 Builder.defineMacro("__fetch_and_addlp", "__builtin_ppc_fetch_and_addlp"); 123 Builder.defineMacro("__fetch_and_and", "__builtin_ppc_fetch_and_and"); 124 Builder.defineMacro("__fetch_and_andlp", "__builtin_ppc_fetch_and_andlp"); 125 Builder.defineMacro("__fetch_and_or", "__builtin_ppc_fetch_and_or"); 126 Builder.defineMacro("__fetch_and_orlp", "__builtin_ppc_fetch_and_orlp"); 127 Builder.defineMacro("__fetch_and_swap", "__builtin_ppc_fetch_and_swap"); 128 Builder.defineMacro("__fetch_and_swaplp", "__builtin_ppc_fetch_and_swaplp"); 129 Builder.defineMacro("__ldarx", "__builtin_ppc_ldarx"); 130 Builder.defineMacro("__lwarx", "__builtin_ppc_lwarx"); 131 Builder.defineMacro("__lharx", "__builtin_ppc_lharx"); 132 Builder.defineMacro("__lbarx", "__builtin_ppc_lbarx"); 133 Builder.defineMacro("__stfiw", "__builtin_ppc_stfiw"); 134 Builder.defineMacro("__stdcx", "__builtin_ppc_stdcx"); 135 Builder.defineMacro("__stwcx", "__builtin_ppc_stwcx"); 136 Builder.defineMacro("__sthcx", "__builtin_ppc_sthcx"); 137 Builder.defineMacro("__stbcx", "__builtin_ppc_stbcx"); 138 Builder.defineMacro("__tdw", "__builtin_ppc_tdw"); 139 Builder.defineMacro("__tw", "__builtin_ppc_tw"); 140 Builder.defineMacro("__trap", "__builtin_ppc_trap"); 141 Builder.defineMacro("__trapd", "__builtin_ppc_trapd"); 142 Builder.defineMacro("__fcfid", "__builtin_ppc_fcfid"); 143 Builder.defineMacro("__fcfud", "__builtin_ppc_fcfud"); 144 Builder.defineMacro("__fctid", "__builtin_ppc_fctid"); 145 Builder.defineMacro("__fctidz", "__builtin_ppc_fctidz"); 146 Builder.defineMacro("__fctiw", "__builtin_ppc_fctiw"); 147 Builder.defineMacro("__fctiwz", "__builtin_ppc_fctiwz"); 148 Builder.defineMacro("__fctudz", "__builtin_ppc_fctudz"); 149 Builder.defineMacro("__fctuwz", "__builtin_ppc_fctuwz"); 150 Builder.defineMacro("__cmpeqb", "__builtin_ppc_cmpeqb"); 151 Builder.defineMacro("__cmprb", "__builtin_ppc_cmprb"); 152 Builder.defineMacro("__setb", "__builtin_ppc_setb"); 153 Builder.defineMacro("__cmpb", "__builtin_ppc_cmpb"); 154 Builder.defineMacro("__mulhd", "__builtin_ppc_mulhd"); 155 Builder.defineMacro("__mulhdu", "__builtin_ppc_mulhdu"); 156 Builder.defineMacro("__mulhw", "__builtin_ppc_mulhw"); 157 Builder.defineMacro("__mulhwu", "__builtin_ppc_mulhwu"); 158 Builder.defineMacro("__maddhd", "__builtin_ppc_maddhd"); 159 Builder.defineMacro("__maddhdu", "__builtin_ppc_maddhdu"); 160 Builder.defineMacro("__maddld", "__builtin_ppc_maddld"); 161 Builder.defineMacro("__rlwnm", "__builtin_ppc_rlwnm"); 162 Builder.defineMacro("__rlwimi", "__builtin_ppc_rlwimi"); 163 Builder.defineMacro("__rldimi", "__builtin_ppc_rldimi"); 164 Builder.defineMacro("__load2r", "__builtin_ppc_load2r"); 165 Builder.defineMacro("__load4r", "__builtin_ppc_load4r"); 166 Builder.defineMacro("__load8r", "__builtin_ppc_load8r"); 167 Builder.defineMacro("__store2r", "__builtin_ppc_store2r"); 168 Builder.defineMacro("__store4r", "__builtin_ppc_store4r"); 169 Builder.defineMacro("__store8r", "__builtin_ppc_store8r"); 170 Builder.defineMacro("__extract_exp", "__builtin_ppc_extract_exp"); 171 Builder.defineMacro("__extract_sig", "__builtin_ppc_extract_sig"); 172 Builder.defineMacro("__mtfsb0", "__builtin_ppc_mtfsb0"); 173 Builder.defineMacro("__mtfsb1", "__builtin_ppc_mtfsb1"); 174 Builder.defineMacro("__mtfsf", "__builtin_ppc_mtfsf"); 175 Builder.defineMacro("__mtfsfi", "__builtin_ppc_mtfsfi"); 176 Builder.defineMacro("__insert_exp", "__builtin_ppc_insert_exp"); 177 Builder.defineMacro("__fmsub", "__builtin_ppc_fmsub"); 178 Builder.defineMacro("__fmsubs", "__builtin_ppc_fmsubs"); 179 Builder.defineMacro("__fnmadd", "__builtin_ppc_fnmadd"); 180 Builder.defineMacro("__fnmadds", "__builtin_ppc_fnmadds"); 181 Builder.defineMacro("__fnmsub", "__builtin_ppc_fnmsub"); 182 Builder.defineMacro("__fnmsubs", "__builtin_ppc_fnmsubs"); 183 Builder.defineMacro("__fre", "__builtin_ppc_fre"); 184 Builder.defineMacro("__fres", "__builtin_ppc_fres"); 185 Builder.defineMacro("__swdiv_nochk", "__builtin_ppc_swdiv_nochk"); 186 Builder.defineMacro("__swdivs_nochk", "__builtin_ppc_swdivs_nochk"); 187 Builder.defineMacro("__alloca", "__builtin_alloca"); 188 Builder.defineMacro("__vcipher", "__builtin_altivec_crypto_vcipher"); 189 Builder.defineMacro("__vcipherlast", "__builtin_altivec_crypto_vcipherlast"); 190 Builder.defineMacro("__vncipher", "__builtin_altivec_crypto_vncipher"); 191 Builder.defineMacro("__vncipherlast", 192 "__builtin_altivec_crypto_vncipherlast"); 193 Builder.defineMacro("__vpermxor", "__builtin_altivec_crypto_vpermxor"); 194 Builder.defineMacro("__vpmsumb", "__builtin_altivec_crypto_vpmsumb"); 195 Builder.defineMacro("__vpmsumd", "__builtin_altivec_crypto_vpmsumd"); 196 Builder.defineMacro("__vpmsumh", "__builtin_altivec_crypto_vpmsumh"); 197 Builder.defineMacro("__vpmsumw", "__builtin_altivec_crypto_vpmsumw"); 198 Builder.defineMacro("__divde", "__builtin_divde"); 199 Builder.defineMacro("__divwe", "__builtin_divwe"); 200 Builder.defineMacro("__divdeu", "__builtin_divdeu"); 201 Builder.defineMacro("__divweu", "__builtin_divweu"); 202 Builder.defineMacro("__alignx", "__builtin_ppc_alignx"); 203 Builder.defineMacro("__bcopy", "bcopy"); 204 Builder.defineMacro("__bpermd", "__builtin_bpermd"); 205 Builder.defineMacro("__cntlz4", "__builtin_clz"); 206 Builder.defineMacro("__cntlz8", "__builtin_clzll"); 207 Builder.defineMacro("__cmplx", "__builtin_complex"); 208 Builder.defineMacro("__cmplxf", "__builtin_complex"); 209 Builder.defineMacro("__cnttz4", "__builtin_ctz"); 210 Builder.defineMacro("__cnttz8", "__builtin_ctzll"); 211 Builder.defineMacro("__darn", "__builtin_darn"); 212 Builder.defineMacro("__darn_32", "__builtin_darn_32"); 213 Builder.defineMacro("__darn_raw", "__builtin_darn_raw"); 214 Builder.defineMacro("__dcbf", "__builtin_dcbf"); 215 Builder.defineMacro("__fence", "__builtin_ppc_fence"); 216 Builder.defineMacro("__fmadd", "__builtin_fma"); 217 Builder.defineMacro("__fmadds", "__builtin_fmaf"); 218 Builder.defineMacro("__abs", "__builtin_abs"); 219 Builder.defineMacro("__labs", "__builtin_labs"); 220 Builder.defineMacro("__llabs", "__builtin_llabs"); 221 Builder.defineMacro("__popcnt4", "__builtin_popcount"); 222 Builder.defineMacro("__popcnt8", "__builtin_popcountll"); 223 Builder.defineMacro("__readflm", "__builtin_readflm"); 224 Builder.defineMacro("__rotatel4", "__builtin_rotateleft32"); 225 Builder.defineMacro("__rotatel8", "__builtin_rotateleft64"); 226 Builder.defineMacro("__rdlam", "__builtin_ppc_rdlam"); 227 Builder.defineMacro("__setflm", "__builtin_setflm"); 228 Builder.defineMacro("__setrnd", "__builtin_setrnd"); 229 Builder.defineMacro("__dcbtstt", "__builtin_ppc_dcbtstt"); 230 Builder.defineMacro("__dcbtt", "__builtin_ppc_dcbtt"); 231 Builder.defineMacro("__mftbu", "__builtin_ppc_mftbu"); 232 Builder.defineMacro("__mfmsr", "__builtin_ppc_mfmsr"); 233 Builder.defineMacro("__mtmsr", "__builtin_ppc_mtmsr"); 234 Builder.defineMacro("__mfspr", "__builtin_ppc_mfspr"); 235 Builder.defineMacro("__mtspr", "__builtin_ppc_mtspr"); 236 Builder.defineMacro("__fric", "__builtin_ppc_fric"); 237 Builder.defineMacro("__frim", "__builtin_ppc_frim"); 238 Builder.defineMacro("__frims", "__builtin_ppc_frims"); 239 Builder.defineMacro("__frin", "__builtin_ppc_frin"); 240 Builder.defineMacro("__frins", "__builtin_ppc_frins"); 241 Builder.defineMacro("__frip", "__builtin_ppc_frip"); 242 Builder.defineMacro("__frips", "__builtin_ppc_frips"); 243 Builder.defineMacro("__friz", "__builtin_ppc_friz"); 244 Builder.defineMacro("__frizs", "__builtin_ppc_frizs"); 245 Builder.defineMacro("__fsel", "__builtin_ppc_fsel"); 246 Builder.defineMacro("__fsels", "__builtin_ppc_fsels"); 247 Builder.defineMacro("__frsqrte", "__builtin_ppc_frsqrte"); 248 Builder.defineMacro("__frsqrtes", "__builtin_ppc_frsqrtes"); 249 Builder.defineMacro("__fsqrt", "__builtin_ppc_fsqrt"); 250 Builder.defineMacro("__fsqrts", "__builtin_ppc_fsqrts"); 251 Builder.defineMacro("__addex", "__builtin_ppc_addex"); 252 Builder.defineMacro("__cmplxl", "__builtin_complex"); 253 Builder.defineMacro("__compare_exp_uo", "__builtin_ppc_compare_exp_uo"); 254 Builder.defineMacro("__compare_exp_lt", "__builtin_ppc_compare_exp_lt"); 255 Builder.defineMacro("__compare_exp_gt", "__builtin_ppc_compare_exp_gt"); 256 Builder.defineMacro("__compare_exp_eq", "__builtin_ppc_compare_exp_eq"); 257 Builder.defineMacro("__test_data_class", "__builtin_ppc_test_data_class"); 258 Builder.defineMacro("__swdiv", "__builtin_ppc_swdiv"); 259 Builder.defineMacro("__swdivs", "__builtin_ppc_swdivs"); 260 Builder.defineMacro("__fnabs", "__builtin_ppc_fnabs"); 261 Builder.defineMacro("__fnabss", "__builtin_ppc_fnabss"); 262 Builder.defineMacro("__builtin_maxfe", "__builtin_ppc_maxfe"); 263 Builder.defineMacro("__builtin_maxfl", "__builtin_ppc_maxfl"); 264 Builder.defineMacro("__builtin_maxfs", "__builtin_ppc_maxfs"); 265 Builder.defineMacro("__builtin_minfe", "__builtin_ppc_minfe"); 266 Builder.defineMacro("__builtin_minfl", "__builtin_ppc_minfl"); 267 Builder.defineMacro("__builtin_minfs", "__builtin_ppc_minfs"); 268 Builder.defineMacro("__builtin_mffs", "__builtin_ppc_mffs"); 269 Builder.defineMacro("__builtin_mffsl", "__builtin_ppc_mffsl"); 270 Builder.defineMacro("__builtin_mtfsf", "__builtin_ppc_mtfsf"); 271 Builder.defineMacro("__builtin_set_fpscr_rn", "__builtin_ppc_set_fpscr_rn"); 272 } 273 274 /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific 275 /// #defines that are not tied to a specific subtarget. 276 void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, 277 MacroBuilder &Builder) const { 278 279 // We define the XLC compatibility macros only on AIX and Linux since XLC 280 // was never available on any other platforms. 281 if (getTriple().isOSAIX() || getTriple().isOSLinux()) 282 defineXLCompatMacros(Builder); 283 284 // Target identification. 285 Builder.defineMacro("__ppc__"); 286 Builder.defineMacro("__PPC__"); 287 Builder.defineMacro("_ARCH_PPC"); 288 Builder.defineMacro("__powerpc__"); 289 Builder.defineMacro("__POWERPC__"); 290 if (PointerWidth == 64) { 291 Builder.defineMacro("_ARCH_PPC64"); 292 Builder.defineMacro("__powerpc64__"); 293 Builder.defineMacro("__PPC64__"); 294 } else if (getTriple().isOSAIX()) { 295 // The XL compilers on AIX define _ARCH_PPC64 for both 32 and 64-bit modes. 296 Builder.defineMacro("_ARCH_PPC64"); 297 } 298 if (getTriple().isOSAIX()) { 299 Builder.defineMacro("__THW_PPC__"); 300 // Define __PPC and __powerpc for AIX XL C/C++ compatibility 301 Builder.defineMacro("__PPC"); 302 Builder.defineMacro("__powerpc"); 303 } 304 305 // Target properties. 306 if (getTriple().getArch() == llvm::Triple::ppc64le || 307 getTriple().getArch() == llvm::Triple::ppcle) { 308 Builder.defineMacro("_LITTLE_ENDIAN"); 309 } else { 310 if (!getTriple().isOSNetBSD() && 311 !getTriple().isOSOpenBSD()) 312 Builder.defineMacro("_BIG_ENDIAN"); 313 } 314 315 // ABI options. 316 if (ABI == "elfv1") 317 Builder.defineMacro("_CALL_ELF", "1"); 318 if (ABI == "elfv2") 319 Builder.defineMacro("_CALL_ELF", "2"); 320 321 // This typically is only for a new enough linker (bfd >= 2.16.2 or gold), but 322 // our support post-dates this and it should work on all 64-bit ppc linux 323 // platforms. It is guaranteed to work on all elfv2 platforms. 324 if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64) 325 Builder.defineMacro("_CALL_LINUX", "1"); 326 327 // Subtarget options. 328 if (!getTriple().isOSAIX()){ 329 Builder.defineMacro("__NATURAL_ALIGNMENT__"); 330 } 331 Builder.defineMacro("__REGISTER_PREFIX__", ""); 332 333 // FIXME: Should be controlled by command line option. 334 if (LongDoubleWidth == 128) { 335 Builder.defineMacro("__LONG_DOUBLE_128__"); 336 Builder.defineMacro("__LONGDOUBLE128"); 337 if (Opts.PPCIEEELongDouble) 338 Builder.defineMacro("__LONG_DOUBLE_IEEE128__"); 339 else 340 Builder.defineMacro("__LONG_DOUBLE_IBM128__"); 341 } 342 343 if (getTriple().isOSAIX() && Opts.LongDoubleSize == 64) { 344 assert(LongDoubleWidth == 64); 345 Builder.defineMacro("__LONGDOUBLE64"); 346 } 347 348 // Define this for elfv2 (64-bit only). 349 if (ABI == "elfv2") 350 Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16"); 351 352 if (ArchDefs & ArchDefineName) 353 Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper())); 354 if (ArchDefs & ArchDefinePpcgr) 355 Builder.defineMacro("_ARCH_PPCGR"); 356 if (ArchDefs & ArchDefinePpcsq) 357 Builder.defineMacro("_ARCH_PPCSQ"); 358 if (ArchDefs & ArchDefine440) 359 Builder.defineMacro("_ARCH_440"); 360 if (ArchDefs & ArchDefine603) 361 Builder.defineMacro("_ARCH_603"); 362 if (ArchDefs & ArchDefine604) 363 Builder.defineMacro("_ARCH_604"); 364 if (ArchDefs & ArchDefinePwr4) 365 Builder.defineMacro("_ARCH_PWR4"); 366 if (ArchDefs & ArchDefinePwr5) 367 Builder.defineMacro("_ARCH_PWR5"); 368 if (ArchDefs & ArchDefinePwr5x) 369 Builder.defineMacro("_ARCH_PWR5X"); 370 if (ArchDefs & ArchDefinePwr6) 371 Builder.defineMacro("_ARCH_PWR6"); 372 if (ArchDefs & ArchDefinePwr6x) 373 Builder.defineMacro("_ARCH_PWR6X"); 374 if (ArchDefs & ArchDefinePwr7) 375 Builder.defineMacro("_ARCH_PWR7"); 376 if (ArchDefs & ArchDefinePwr8) 377 Builder.defineMacro("_ARCH_PWR8"); 378 if (ArchDefs & ArchDefinePwr9) 379 Builder.defineMacro("_ARCH_PWR9"); 380 if (ArchDefs & ArchDefinePwr10) 381 Builder.defineMacro("_ARCH_PWR10"); 382 if (ArchDefs & ArchDefineA2) 383 Builder.defineMacro("_ARCH_A2"); 384 if (ArchDefs & ArchDefineE500) 385 Builder.defineMacro("__NO_LWSYNC__"); 386 if (ArchDefs & ArchDefineFuture) 387 Builder.defineMacro("_ARCH_PWR_FUTURE"); 388 389 if (HasAltivec) { 390 Builder.defineMacro("__VEC__", "10206"); 391 Builder.defineMacro("__ALTIVEC__"); 392 } 393 if (HasSPE) { 394 Builder.defineMacro("__SPE__"); 395 Builder.defineMacro("__NO_FPRS__"); 396 } 397 if (HasVSX) 398 Builder.defineMacro("__VSX__"); 399 if (HasP8Vector) 400 Builder.defineMacro("__POWER8_VECTOR__"); 401 if (HasP8Crypto) 402 Builder.defineMacro("__CRYPTO__"); 403 if (HasHTM) 404 Builder.defineMacro("__HTM__"); 405 if (HasFloat128) 406 Builder.defineMacro("__FLOAT128__"); 407 if (HasP9Vector) 408 Builder.defineMacro("__POWER9_VECTOR__"); 409 if (HasMMA) 410 Builder.defineMacro("__MMA__"); 411 if (HasROPProtect) 412 Builder.defineMacro("__ROP_PROTECT__"); 413 if (HasP10Vector) 414 Builder.defineMacro("__POWER10_VECTOR__"); 415 if (HasPCRelativeMemops) 416 Builder.defineMacro("__PCREL__"); 417 418 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 419 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 420 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 421 if (PointerWidth == 64) 422 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 423 424 // We have support for the bswap intrinsics so we can define this. 425 Builder.defineMacro("__HAVE_BSWAP__", "1"); 426 427 // FIXME: The following are not yet generated here by Clang, but are 428 // generated by GCC: 429 // 430 // _SOFT_FLOAT_ 431 // __RECIP_PRECISION__ 432 // __APPLE_ALTIVEC__ 433 // __RECIP__ 434 // __RECIPF__ 435 // __RSQRTE__ 436 // __RSQRTEF__ 437 // _SOFT_DOUBLE_ 438 // __NO_LWSYNC__ 439 // __CMODEL_MEDIUM__ 440 // __CMODEL_LARGE__ 441 // _CALL_SYSV 442 // _CALL_DARWIN 443 } 444 445 // Handle explicit options being passed to the compiler here: if we've 446 // explicitly turned off vsx and turned on any of: 447 // - power8-vector 448 // - direct-move 449 // - float128 450 // - power9-vector 451 // - paired-vector-memops 452 // - mma 453 // - power10-vector 454 // then go ahead and error since the customer has expressed an incompatible 455 // set of options. 456 static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags, 457 const std::vector<std::string> &FeaturesVec) { 458 459 // vsx was not explicitly turned off. 460 if (!llvm::is_contained(FeaturesVec, "-vsx")) 461 return true; 462 463 auto FindVSXSubfeature = [&](StringRef Feature, StringRef Option) { 464 if (llvm::is_contained(FeaturesVec, Feature)) { 465 Diags.Report(diag::err_opt_not_valid_with_opt) << Option << "-mno-vsx"; 466 return true; 467 } 468 return false; 469 }; 470 471 bool Found = FindVSXSubfeature("+power8-vector", "-mpower8-vector"); 472 Found |= FindVSXSubfeature("+direct-move", "-mdirect-move"); 473 Found |= FindVSXSubfeature("+float128", "-mfloat128"); 474 Found |= FindVSXSubfeature("+power9-vector", "-mpower9-vector"); 475 Found |= FindVSXSubfeature("+paired-vector-memops", "-mpaired-vector-memops"); 476 Found |= FindVSXSubfeature("+mma", "-mmma"); 477 Found |= FindVSXSubfeature("+power10-vector", "-mpower10-vector"); 478 479 // Return false if any vsx subfeatures was found. 480 return !Found; 481 } 482 483 bool PPCTargetInfo::initFeatureMap( 484 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 485 const std::vector<std::string> &FeaturesVec) const { 486 Features["altivec"] = llvm::StringSwitch<bool>(CPU) 487 .Case("7400", true) 488 .Case("g4", true) 489 .Case("7450", true) 490 .Case("g4+", true) 491 .Case("970", true) 492 .Case("g5", true) 493 .Case("pwr6", true) 494 .Case("pwr7", true) 495 .Case("pwr8", true) 496 .Case("pwr9", true) 497 .Case("ppc64", true) 498 .Case("ppc64le", true) 499 .Default(false); 500 501 Features["power9-vector"] = (CPU == "pwr9"); 502 Features["crypto"] = llvm::StringSwitch<bool>(CPU) 503 .Case("ppc64le", true) 504 .Case("pwr9", true) 505 .Case("pwr8", true) 506 .Default(false); 507 Features["power8-vector"] = llvm::StringSwitch<bool>(CPU) 508 .Case("ppc64le", true) 509 .Case("pwr9", true) 510 .Case("pwr8", true) 511 .Default(false); 512 Features["bpermd"] = llvm::StringSwitch<bool>(CPU) 513 .Case("ppc64le", true) 514 .Case("pwr9", true) 515 .Case("pwr8", true) 516 .Case("pwr7", true) 517 .Default(false); 518 Features["extdiv"] = llvm::StringSwitch<bool>(CPU) 519 .Case("ppc64le", true) 520 .Case("pwr9", true) 521 .Case("pwr8", true) 522 .Case("pwr7", true) 523 .Default(false); 524 Features["direct-move"] = llvm::StringSwitch<bool>(CPU) 525 .Case("ppc64le", true) 526 .Case("pwr9", true) 527 .Case("pwr8", true) 528 .Default(false); 529 Features["crbits"] = llvm::StringSwitch<bool>(CPU) 530 .Case("ppc64le", true) 531 .Case("pwr9", true) 532 .Case("pwr8", true) 533 .Default(false); 534 Features["vsx"] = llvm::StringSwitch<bool>(CPU) 535 .Case("ppc64le", true) 536 .Case("pwr9", true) 537 .Case("pwr8", true) 538 .Case("pwr7", true) 539 .Default(false); 540 Features["htm"] = llvm::StringSwitch<bool>(CPU) 541 .Case("ppc64le", true) 542 .Case("pwr9", true) 543 .Case("pwr8", true) 544 .Default(false); 545 546 // ROP Protect is off by default. 547 Features["rop-protect"] = false; 548 // Privileged instructions are off by default. 549 Features["privileged"] = false; 550 551 // The code generated by the -maix-small-local-exec-tls option is turned 552 // off by default. 553 Features["aix-small-local-exec-tls"] = false; 554 555 Features["spe"] = llvm::StringSwitch<bool>(CPU) 556 .Case("8548", true) 557 .Case("e500", true) 558 .Default(false); 559 560 Features["isa-v206-instructions"] = llvm::StringSwitch<bool>(CPU) 561 .Case("ppc64le", true) 562 .Case("pwr9", true) 563 .Case("pwr8", true) 564 .Case("pwr7", true) 565 .Case("a2", true) 566 .Default(false); 567 568 Features["isa-v207-instructions"] = llvm::StringSwitch<bool>(CPU) 569 .Case("ppc64le", true) 570 .Case("pwr9", true) 571 .Case("pwr8", true) 572 .Default(false); 573 574 Features["isa-v30-instructions"] = 575 llvm::StringSwitch<bool>(CPU).Case("pwr9", true).Default(false); 576 577 Features["quadword-atomics"] = 578 getTriple().isArch64Bit() && llvm::StringSwitch<bool>(CPU) 579 .Case("pwr9", true) 580 .Case("pwr8", true) 581 .Default(false); 582 583 // Power10 includes all the same features as Power9 plus any features specific 584 // to the Power10 core. 585 if (CPU == "pwr10" || CPU == "power10") { 586 initFeatureMap(Features, Diags, "pwr9", FeaturesVec); 587 addP10SpecificFeatures(Features); 588 } 589 590 // Future CPU should include all of the features of Power 10 as well as any 591 // additional features (yet to be determined) specific to it. 592 if (CPU == "future") { 593 initFeatureMap(Features, Diags, "pwr10", FeaturesVec); 594 addFutureSpecificFeatures(Features); 595 } 596 597 if (!ppcUserFeaturesCheck(Diags, FeaturesVec)) 598 return false; 599 600 if (!(ArchDefs & ArchDefinePwr7) && (ArchDefs & ArchDefinePpcgr) && 601 llvm::is_contained(FeaturesVec, "+float128")) { 602 // We have __float128 on PPC but not pre-VSX targets. 603 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" << CPU; 604 return false; 605 } 606 607 if (!(ArchDefs & ArchDefinePwr10)) { 608 if (llvm::is_contained(FeaturesVec, "+mma")) { 609 // MMA operations are not available pre-Power10. 610 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mmma" << CPU; 611 return false; 612 } 613 if (llvm::is_contained(FeaturesVec, "+pcrel")) { 614 // PC-Relative instructions are not available pre-Power10, 615 // and these instructions also require prefixed instructions support. 616 Diags.Report(diag::err_opt_not_valid_without_opt) 617 << "-mpcrel" 618 << "-mcpu=pwr10 -mprefixed"; 619 return false; 620 } 621 if (llvm::is_contained(FeaturesVec, "+prefixed")) { 622 // Prefixed instructions are not available pre-Power10. 623 Diags.Report(diag::err_opt_not_valid_without_opt) << "-mprefixed" 624 << "-mcpu=pwr10"; 625 return false; 626 } 627 if (llvm::is_contained(FeaturesVec, "+paired-vector-memops")) { 628 // Paired vector memops are not available pre-Power10. 629 Diags.Report(diag::err_opt_not_valid_without_opt) 630 << "-mpaired-vector-memops" 631 << "-mcpu=pwr10"; 632 return false; 633 } 634 } 635 636 if (!(ArchDefs & ArchDefinePwr8) && 637 llvm::is_contained(FeaturesVec, "+rop-protect")) { 638 // We can turn on ROP Protect on Power 8 and above. 639 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mrop-protect" << CPU; 640 return false; 641 } 642 643 if (!(ArchDefs & ArchDefinePwr8) && 644 llvm::is_contained(FeaturesVec, "+privileged")) { 645 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mprivileged" << CPU; 646 return false; 647 } 648 649 if (llvm::is_contained(FeaturesVec, "+aix-small-local-exec-tls")) { 650 if (!getTriple().isOSAIX() || !getTriple().isArch64Bit()) { 651 Diags.Report(diag::err_opt_not_valid_on_target) 652 << "-maix-small-local-exec-tls"; 653 return false; 654 } 655 } 656 657 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 658 } 659 660 // Add any Power10 specific features. 661 void PPCTargetInfo::addP10SpecificFeatures( 662 llvm::StringMap<bool> &Features) const { 663 Features["htm"] = false; // HTM was removed for P10. 664 Features["paired-vector-memops"] = true; 665 Features["mma"] = true; 666 Features["power10-vector"] = true; 667 Features["pcrelative-memops"] = true; 668 Features["prefix-instrs"] = true; 669 Features["isa-v31-instructions"] = true; 670 } 671 672 // Add features specific to the "Future" CPU. 673 void PPCTargetInfo::addFutureSpecificFeatures( 674 llvm::StringMap<bool> &Features) const {} 675 676 bool PPCTargetInfo::hasFeature(StringRef Feature) const { 677 return llvm::StringSwitch<bool>(Feature) 678 .Case("powerpc", true) 679 .Case("altivec", HasAltivec) 680 .Case("vsx", HasVSX) 681 .Case("crbits", UseCRBits) 682 .Case("power8-vector", HasP8Vector) 683 .Case("crypto", HasP8Crypto) 684 .Case("direct-move", HasDirectMove) 685 .Case("htm", HasHTM) 686 .Case("bpermd", HasBPERMD) 687 .Case("extdiv", HasExtDiv) 688 .Case("float128", HasFloat128) 689 .Case("power9-vector", HasP9Vector) 690 .Case("paired-vector-memops", PairedVectorMemops) 691 .Case("power10-vector", HasP10Vector) 692 .Case("pcrelative-memops", HasPCRelativeMemops) 693 .Case("prefix-instrs", HasPrefixInstrs) 694 .Case("spe", HasSPE) 695 .Case("mma", HasMMA) 696 .Case("rop-protect", HasROPProtect) 697 .Case("privileged", HasPrivileged) 698 .Case("aix-small-local-exec-tls", HasAIXSmallLocalExecTLS) 699 .Case("isa-v206-instructions", IsISA2_06) 700 .Case("isa-v207-instructions", IsISA2_07) 701 .Case("isa-v30-instructions", IsISA3_0) 702 .Case("isa-v31-instructions", IsISA3_1) 703 .Case("quadword-atomics", HasQuadwordAtomics) 704 .Default(false); 705 } 706 707 void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, 708 StringRef Name, bool Enabled) const { 709 if (Enabled) { 710 if (Name == "efpu2") 711 Features["spe"] = true; 712 // If we're enabling any of the vsx based features then enable vsx and 713 // altivec. We'll diagnose any problems later. 714 bool FeatureHasVSX = llvm::StringSwitch<bool>(Name) 715 .Case("vsx", true) 716 .Case("direct-move", true) 717 .Case("power8-vector", true) 718 .Case("power9-vector", true) 719 .Case("paired-vector-memops", true) 720 .Case("power10-vector", true) 721 .Case("float128", true) 722 .Case("mma", true) 723 .Default(false); 724 if (FeatureHasVSX) 725 Features["vsx"] = Features["altivec"] = true; 726 if (Name == "power9-vector") 727 Features["power8-vector"] = true; 728 else if (Name == "power10-vector") 729 Features["power8-vector"] = Features["power9-vector"] = true; 730 if (Name == "pcrel") 731 Features["pcrelative-memops"] = true; 732 else if (Name == "prefixed") 733 Features["prefix-instrs"] = true; 734 else 735 Features[Name] = true; 736 } else { 737 if (Name == "spe") 738 Features["efpu2"] = false; 739 // If we're disabling altivec or vsx go ahead and disable all of the vsx 740 // features. 741 if ((Name == "altivec") || (Name == "vsx")) 742 Features["vsx"] = Features["direct-move"] = Features["power8-vector"] = 743 Features["float128"] = Features["power9-vector"] = 744 Features["paired-vector-memops"] = Features["mma"] = 745 Features["power10-vector"] = false; 746 if (Name == "power8-vector") 747 Features["power9-vector"] = Features["paired-vector-memops"] = 748 Features["mma"] = Features["power10-vector"] = false; 749 else if (Name == "power9-vector") 750 Features["paired-vector-memops"] = Features["mma"] = 751 Features["power10-vector"] = false; 752 if (Name == "pcrel") 753 Features["pcrelative-memops"] = false; 754 else if (Name == "prefixed") 755 Features["prefix-instrs"] = false; 756 else 757 Features[Name] = false; 758 } 759 } 760 761 // Make sure that registers are added in the correct array index which should be 762 // the DWARF number for PPC registers. 763 const char *const PPCTargetInfo::GCCRegNames[] = { 764 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", 765 "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", 766 "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", 767 "r27", "r28", "r29", "r30", "r31", "f0", "f1", "f2", "f3", 768 "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", 769 "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", 770 "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", 771 "f31", "mq", "lr", "ctr", "ap", "cr0", "cr1", "cr2", "cr3", 772 "cr4", "cr5", "cr6", "cr7", "xer", "v0", "v1", "v2", "v3", 773 "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", 774 "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", 775 "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", 776 "v31", "vrsave", "vscr", "spe_acc", "spefscr", "sfp" 777 }; 778 779 ArrayRef<const char *> PPCTargetInfo::getGCCRegNames() const { 780 return llvm::ArrayRef(GCCRegNames); 781 } 782 783 const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = { 784 // While some of these aliases do map to different registers 785 // they still share the same register name. 786 {{"0"}, "r0"}, {{"1", "sp"}, "r1"}, {{"2"}, "r2"}, 787 {{"3"}, "r3"}, {{"4"}, "r4"}, {{"5"}, "r5"}, 788 {{"6"}, "r6"}, {{"7"}, "r7"}, {{"8"}, "r8"}, 789 {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"}, 790 {{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, 791 {{"15"}, "r15"}, {{"16"}, "r16"}, {{"17"}, "r17"}, 792 {{"18"}, "r18"}, {{"19"}, "r19"}, {{"20"}, "r20"}, 793 {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"}, 794 {{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, 795 {{"27"}, "r27"}, {{"28"}, "r28"}, {{"29"}, "r29"}, 796 {{"30"}, "r30"}, {{"31"}, "r31"}, {{"fr0"}, "f0"}, 797 {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"}, 798 {{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, 799 {{"fr7"}, "f7"}, {{"fr8"}, "f8"}, {{"fr9"}, "f9"}, 800 {{"fr10"}, "f10"}, {{"fr11"}, "f11"}, {{"fr12"}, "f12"}, 801 {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"}, 802 {{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, 803 {{"fr19"}, "f19"}, {{"fr20"}, "f20"}, {{"fr21"}, "f21"}, 804 {{"fr22"}, "f22"}, {{"fr23"}, "f23"}, {{"fr24"}, "f24"}, 805 {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"}, 806 {{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, 807 {{"fr31"}, "f31"}, {{"cc"}, "cr0"}, 808 }; 809 810 ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const { 811 return llvm::ArrayRef(GCCRegAliases); 812 } 813 814 // PPC ELFABIv2 DWARF Definition "Table 2.26. Mappings of Common Registers". 815 // vs0 ~ vs31 is mapping to 32 - 63, 816 // vs32 ~ vs63 is mapping to 77 - 108. 817 // And this mapping applies to all OSes which run on powerpc. 818 const TargetInfo::AddlRegName GCCAddlRegNames[] = { 819 // Table of additional register names to use in user input. 820 {{"vs0"}, 32}, {{"vs1"}, 33}, {{"vs2"}, 34}, {{"vs3"}, 35}, 821 {{"vs4"}, 36}, {{"vs5"}, 37}, {{"vs6"}, 38}, {{"vs7"}, 39}, 822 {{"vs8"}, 40}, {{"vs9"}, 41}, {{"vs10"}, 42}, {{"vs11"}, 43}, 823 {{"vs12"}, 44}, {{"vs13"}, 45}, {{"vs14"}, 46}, {{"vs15"}, 47}, 824 {{"vs16"}, 48}, {{"vs17"}, 49}, {{"vs18"}, 50}, {{"vs19"}, 51}, 825 {{"vs20"}, 52}, {{"vs21"}, 53}, {{"vs22"}, 54}, {{"vs23"}, 55}, 826 {{"vs24"}, 56}, {{"vs25"}, 57}, {{"vs26"}, 58}, {{"vs27"}, 59}, 827 {{"vs28"}, 60}, {{"vs29"}, 61}, {{"vs30"}, 62}, {{"vs31"}, 63}, 828 {{"vs32"}, 77}, {{"vs33"}, 78}, {{"vs34"}, 79}, {{"vs35"}, 80}, 829 {{"vs36"}, 81}, {{"vs37"}, 82}, {{"vs38"}, 83}, {{"vs39"}, 84}, 830 {{"vs40"}, 85}, {{"vs41"}, 86}, {{"vs42"}, 87}, {{"vs43"}, 88}, 831 {{"vs44"}, 89}, {{"vs45"}, 90}, {{"vs46"}, 91}, {{"vs47"}, 92}, 832 {{"vs48"}, 93}, {{"vs49"}, 94}, {{"vs50"}, 95}, {{"vs51"}, 96}, 833 {{"vs52"}, 97}, {{"vs53"}, 98}, {{"vs54"}, 99}, {{"vs55"}, 100}, 834 {{"vs56"}, 101}, {{"vs57"}, 102}, {{"vs58"}, 103}, {{"vs59"}, 104}, 835 {{"vs60"}, 105}, {{"vs61"}, 106}, {{"vs62"}, 107}, {{"vs63"}, 108}, 836 }; 837 838 ArrayRef<TargetInfo::AddlRegName> PPCTargetInfo::getGCCAddlRegNames() const { 839 return llvm::ArrayRef(GCCAddlRegNames); 840 } 841 842 static constexpr llvm::StringLiteral ValidCPUNames[] = { 843 {"generic"}, {"440"}, {"450"}, {"601"}, {"602"}, 844 {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"}, 845 {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"}, 846 {"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"}, 847 {"g5"}, {"a2"}, {"e500"}, {"e500mc"}, {"e5500"}, 848 {"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"}, 849 {"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"}, 850 {"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"}, 851 {"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, {"pwr10"}, 852 {"powerpc"}, {"ppc"}, {"ppc32"}, {"powerpc64"}, {"ppc64"}, 853 {"powerpc64le"}, {"ppc64le"}, {"future"}}; 854 855 bool PPCTargetInfo::isValidCPUName(StringRef Name) const { 856 return llvm::is_contained(ValidCPUNames, Name); 857 } 858 859 void PPCTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { 860 Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames)); 861 } 862 863 void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { 864 if (HasAltivec) 865 Opts.AltiVec = 1; 866 TargetInfo::adjust(Diags, Opts); 867 if (LongDoubleFormat != &llvm::APFloat::IEEEdouble()) 868 LongDoubleFormat = Opts.PPCIEEELongDouble 869 ? &llvm::APFloat::IEEEquad() 870 : &llvm::APFloat::PPCDoubleDouble(); 871 Opts.IEEE128 = 1; 872 if (getTriple().isOSAIX() && Opts.EnableAIXQuadwordAtomicsABI && 873 HasQuadwordAtomics) 874 MaxAtomicInlineWidth = 128; 875 } 876 877 ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const { 878 return llvm::ArrayRef(BuiltinInfo, 879 clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin); 880 } 881