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