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