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