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