551 lines · c
1//===--- PPC.h - Declare PPC target feature support -------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file declares PPC TargetInfo objects.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H14#define LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H15 16#include "OSTargets.h"17#include "clang/Basic/TargetInfo.h"18#include "clang/Basic/TargetOptions.h"19#include "llvm/ADT/StringSwitch.h"20#include "llvm/Support/Compiler.h"21#include "llvm/TargetParser/Triple.h"22 23namespace clang {24namespace targets {25 26// PPC abstract base class27class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {28 29 /// Flags for architecture specific defines.30 typedef enum {31 ArchDefineNone = 0,32 ArchDefineName = 1 << 0, // <name> is substituted for arch name.33 ArchDefinePpcgr = 1 << 1,34 ArchDefinePpcsq = 1 << 2,35 ArchDefine440 = 1 << 3,36 ArchDefine603 = 1 << 4,37 ArchDefine604 = 1 << 5,38 ArchDefinePwr4 = 1 << 6,39 ArchDefinePwr5 = 1 << 7,40 ArchDefinePwr5x = 1 << 8,41 ArchDefinePwr6 = 1 << 9,42 ArchDefinePwr6x = 1 << 10,43 ArchDefinePwr7 = 1 << 11,44 ArchDefinePwr8 = 1 << 12,45 ArchDefinePwr9 = 1 << 13,46 ArchDefinePwr10 = 1 << 14,47 ArchDefinePwr11 = 1 << 15,48 ArchDefineFuture = 1 << 16,49 ArchDefineA2 = 1 << 17,50 ArchDefineE500 = 1 << 1851 } ArchDefineTypes;52 53 ArchDefineTypes ArchDefs = ArchDefineNone;54 static const char *const GCCRegNames[];55 static const TargetInfo::GCCRegAlias GCCRegAliases[];56 std::string CPU;57 enum PPCFloatABI { HardFloat, SoftFloat } FloatABI;58 59 // Target cpu features.60 bool HasAltivec = false;61 bool HasMMA = false;62 bool HasROPProtect = false;63 bool HasVSX = false;64 bool HasP8Vector = false;65 bool HasP8Crypto = false;66 bool HasHTM = false;67 bool HasP9Vector = false;68 bool HasSPE = false;69 bool HasFrsqrte = false;70 bool HasFrsqrtes = false;71 bool HasP10Vector = false;72 bool HasPCRelativeMemops = false;73 bool HasQuadwordAtomics = false;74 bool UseLongCalls = false;75 76protected:77 std::string ABI;78 79public:80 PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)81 : TargetInfo(Triple) {82 SuitableAlign = 128;83 LongDoubleWidth = LongDoubleAlign = 128;84 LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();85 HasStrictFP = true;86 HasIbm128 = true;87 HasUnalignedAccess = true;88 }89 90 // Set the language option for altivec based on our value.91 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts,92 const TargetInfo *Aux) override;93 94 // Note: GCC recognizes the following additional cpus:95 // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801,96 // 821, 823, 8540, e300c2, e300c3, e500mc64, e6500, 860, cell, titan, rs64.97 bool isValidCPUName(StringRef Name) const override;98 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;99 100 bool setCPU(const std::string &Name) override {101 bool CPUKnown = isValidCPUName(Name);102 if (CPUKnown) {103 CPU = Name;104 105 // CPU identification.106 ArchDefs =107 (ArchDefineTypes)llvm::StringSwitch<int>(CPU)108 .Case("440", ArchDefineName)109 .Case("450", ArchDefineName | ArchDefine440)110 .Case("601", ArchDefineName)111 .Case("602", ArchDefineName | ArchDefinePpcgr)112 .Case("603", ArchDefineName | ArchDefinePpcgr)113 .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)114 .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr)115 .Case("604", ArchDefineName | ArchDefinePpcgr)116 .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr)117 .Case("620", ArchDefineName | ArchDefinePpcgr)118 .Case("630", ArchDefineName | ArchDefinePpcgr)119 .Case("7400", ArchDefineName | ArchDefinePpcgr)120 .Case("7450", ArchDefineName | ArchDefinePpcgr)121 .Case("750", ArchDefineName | ArchDefinePpcgr)122 .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |123 ArchDefinePpcsq)124 .Case("a2", ArchDefineA2)125 .Cases({"power3", "pwr3"}, ArchDefinePpcgr)126 .Cases({"power4", "pwr4"},127 ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)128 .Cases({"power5", "pwr5"}, ArchDefinePwr5 | ArchDefinePwr4 |129 ArchDefinePpcgr | ArchDefinePpcsq)130 .Cases({"power5x", "pwr5x"},131 ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |132 ArchDefinePpcgr | ArchDefinePpcsq)133 .Cases({"power6", "pwr6"}, ArchDefinePwr6 | ArchDefinePwr5x |134 ArchDefinePwr5 | ArchDefinePwr4 |135 ArchDefinePpcgr | ArchDefinePpcsq)136 .Cases({"power6x", "pwr6x"},137 ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |138 ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |139 ArchDefinePpcsq)140 .Cases({"power7", "pwr7"}, ArchDefinePwr7 | ArchDefinePwr6 |141 ArchDefinePwr5x | ArchDefinePwr5 |142 ArchDefinePwr4 | ArchDefinePpcgr |143 ArchDefinePpcsq)144 // powerpc64le automatically defaults to at least power8.145 .Cases({"power8", "pwr8", "ppc64le"},146 ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 |147 ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |148 ArchDefinePpcgr | ArchDefinePpcsq)149 .Cases({"power9", "pwr9"},150 ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |151 ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |152 ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)153 .Cases({"power10", "pwr10"},154 ArchDefinePwr10 | ArchDefinePwr9 | ArchDefinePwr8 |155 ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x |156 ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |157 ArchDefinePpcsq)158 .Cases({"power11", "pwr11"},159 ArchDefinePwr11 | ArchDefinePwr10 | ArchDefinePwr9 |160 ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 |161 ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |162 ArchDefinePpcgr | ArchDefinePpcsq)163 .Case("future",164 ArchDefineFuture | ArchDefinePwr11 | ArchDefinePwr10 |165 ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |166 ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |167 ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)168 .Cases({"8548", "e500"}, ArchDefineE500)169 .Default(ArchDefineNone);170 }171 return CPUKnown;172 }173 174 StringRef getABI() const override { return ABI; }175 176 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;177 178 bool isCLZForZeroUndef() const override { return false; }179 180 void getTargetDefines(const LangOptions &Opts,181 MacroBuilder &Builder) const override;182 183 bool184 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,185 StringRef CPU,186 const std::vector<std::string> &FeaturesVec) const override;187 188 void addP10SpecificFeatures(llvm::StringMap<bool> &Features) const;189 void addP11SpecificFeatures(llvm::StringMap<bool> &Features) const;190 void addFutureSpecificFeatures(llvm::StringMap<bool> &Features) const;191 192 bool handleTargetFeatures(std::vector<std::string> &Features,193 DiagnosticsEngine &Diags) override;194 195 bool hasFeature(StringRef Feature) const override;196 197 void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,198 bool Enabled) const override;199 200 bool supportsTargetAttributeTune() const override { return true; }201 202 ArrayRef<const char *> getGCCRegNames() const override;203 204 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;205 206 ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;207 208 bool validateAsmConstraint(const char *&Name,209 TargetInfo::ConstraintInfo &Info) const override {210 switch (*Name) {211 default:212 return false;213 case 'O': // Zero214 break;215 case 'f': // Floating point register216 // Don't use floating point registers on soft float ABI.217 if (FloatABI == SoftFloat)218 return false;219 [[fallthrough]];220 case 'b': // Base register221 Info.setAllowsRegister();222 break;223 // FIXME: The following are added to allow parsing.224 // I just took a guess at what the actions should be.225 // Also, is more specific checking needed? I.e. specific registers?226 case 'd': // Floating point register (containing 64-bit value)227 case 'v': // Altivec vector register228 // Don't use floating point and altivec vector registers229 // on soft float ABI230 if (FloatABI == SoftFloat)231 return false;232 Info.setAllowsRegister();233 break;234 case 'w':235 switch (Name[1]) {236 case 'd': // VSX vector register to hold vector double data237 case 'f': // VSX vector register to hold vector float data238 case 's': // VSX vector register to hold scalar double data239 case 'w': // VSX vector register to hold scalar double data240 case 'a': // Any VSX register241 case 'c': // An individual CR bit242 case 'i': // FP or VSX register to hold 64-bit integers data243 break;244 default:245 return false;246 }247 Info.setAllowsRegister();248 Name++; // Skip over 'w'.249 break;250 case 'h': // `MQ', `CTR', or `LINK' register251 case 'q': // `MQ' register252 case 'c': // `CTR' register253 case 'l': // `LINK' register254 case 'x': // `CR' register (condition register) number 0255 case 'y': // `CR' register (condition register)256 case 'z': // `XER[CA]' carry bit (part of the XER register)257 Info.setAllowsRegister();258 break;259 case 'I': // Signed 16-bit constant260 case 'J': // Unsigned 16-bit constant shifted left 16 bits261 // (use `L' instead for SImode constants)262 case 'K': // Unsigned 16-bit constant263 case 'L': // Signed 16-bit constant shifted left 16 bits264 case 'M': // Constant larger than 31265 case 'N': // Exact power of 2266 case 'P': // Constant whose negation is a signed 16-bit constant267 case 'G': // Floating point constant that can be loaded into a268 // register with one instruction per word269 case 'H': // Integer/Floating point constant that can be loaded270 // into a register using three instructions271 break;272 case 'm': // Memory operand. Note that on PowerPC targets, m can273 // include addresses that update the base register. It274 // is therefore only safe to use `m' in an asm statement275 // if that asm statement accesses the operand exactly once.276 // The asm statement must also use `%U<opno>' as a277 // placeholder for the "update" flag in the corresponding278 // load or store instruction. For example:279 // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));280 // is correct but:281 // asm ("st %1,%0" : "=m" (mem) : "r" (val));282 // is not. Use es rather than m if you don't want the base283 // register to be updated.284 case 'e':285 if (Name[1] != 's')286 return false;287 // es: A "stable" memory operand; that is, one which does not288 // include any automodification of the base register. Unlike289 // `m', this constraint can be used in asm statements that290 // might access the operand several times, or that might not291 // access it at all.292 Info.setAllowsMemory();293 Name++; // Skip over 'e'.294 break;295 case 'Q': // Memory operand that is an offset from a register (it is296 // usually better to use `m' or `es' in asm statements)297 Info.setAllowsRegister();298 [[fallthrough]];299 case 'Z': // Memory operand that is an indexed or indirect from a300 // register (it is usually better to use `m' or `es' in301 // asm statements)302 Info.setAllowsMemory();303 break;304 case 'a': // Address operand that is an indexed or indirect from a305 // register (`p' is preferable for asm statements)306 // TODO: Add full support for this constraint307 return false;308 case 'R': // AIX TOC entry309 case 'S': // Constant suitable as a 64-bit mask operand310 case 'T': // Constant suitable as a 32-bit mask operand311 case 'U': // System V Release 4 small data area reference312 case 't': // AND masks that can be performed by two rldic{l, r}313 // instructions314 case 'W': // Vector constant that does not require memory315 case 'j': // Vector constant that is all zeros.316 break;317 // End FIXME.318 }319 return true;320 }321 322 std::string convertConstraint(const char *&Constraint) const override {323 std::string R;324 switch (*Constraint) {325 case 'e':326 case 'w':327 // Two-character constraint; add "^" hint for later parsing.328 R = std::string("^") + std::string(Constraint, 2);329 Constraint++;330 break;331 default:332 return TargetInfo::convertConstraint(Constraint);333 }334 return R;335 }336 337 std::string_view getClobbers() const override { return ""; }338 int getEHDataRegisterNumber(unsigned RegNo) const override {339 if (RegNo == 0)340 return 3;341 if (RegNo == 1)342 return 4;343 return -1;344 }345 346 bool hasSjLjLowering() const override { return true; }347 348 const char *getLongDoubleMangling() const override {349 if (LongDoubleWidth == 64)350 return "e";351 return LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble()352 ? "g"353 : "u9__ieee128";354 }355 const char *getFloat128Mangling() const override { return "u9__ieee128"; }356 const char *getIbm128Mangling() const override { return "g"; }357 358 bool hasBitIntType() const override { return true; }359 360 bool isSPRegName(StringRef RegName) const override {361 return RegName == "r1" || RegName == "x1";362 }363 364 // We support __builtin_cpu_supports/__builtin_cpu_is on targets that365 // have Glibc since it is Glibc that provides the HWCAP[2] in the auxv.366 static constexpr int MINIMUM_AIX_OS_MAJOR = 7;367 static constexpr int MINIMUM_AIX_OS_MINOR = 2;368 bool supportsCpuSupports() const override {369 llvm::Triple Triple = getTriple();370 // AIX 7.2 is the minimum requirement to support __builtin_cpu_supports().371 return Triple.isOSGlibc() ||372 (Triple.isOSAIX() &&373 !Triple.isOSVersionLT(MINIMUM_AIX_OS_MAJOR, MINIMUM_AIX_OS_MINOR));374 }375 376 bool supportsCpuIs() const override {377 llvm::Triple Triple = getTriple();378 // AIX 7.2 is the minimum requirement to support __builtin_cpu_is().379 return Triple.isOSGlibc() ||380 (Triple.isOSAIX() &&381 !Triple.isOSVersionLT(MINIMUM_AIX_OS_MAJOR, MINIMUM_AIX_OS_MINOR));382 }383 bool validateCpuSupports(StringRef Feature) const override;384 bool validateCpuIs(StringRef Name) const override;385};386 387class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {388public:389 PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)390 : PPCTargetInfo(Triple, Opts) {391 if (Triple.isOSAIX())392 resetDataLayout("E-m:a-p:32:32-Fi32-i64:64-n32");393 else if (Triple.getArch() == llvm::Triple::ppcle)394 resetDataLayout("e-m:e-p:32:32-Fn32-i64:64-n32");395 else396 resetDataLayout("E-m:e-p:32:32-Fn32-i64:64-n32");397 398 switch (getTriple().getOS()) {399 case llvm::Triple::Linux:400 case llvm::Triple::FreeBSD:401 case llvm::Triple::NetBSD:402 SizeType = UnsignedInt;403 PtrDiffType = SignedInt;404 IntPtrType = SignedInt;405 break;406 case llvm::Triple::AIX:407 SizeType = UnsignedLong;408 PtrDiffType = SignedLong;409 IntPtrType = SignedLong;410 LongDoubleWidth = 64;411 LongDoubleAlign = DoubleAlign = 32;412 LongDoubleFormat = &llvm::APFloat::IEEEdouble();413 break;414 default:415 break;416 }417 418 if (Triple.isOSFreeBSD() || Triple.isOSNetBSD() || Triple.isOSOpenBSD() ||419 Triple.isMusl()) {420 LongDoubleWidth = LongDoubleAlign = 64;421 LongDoubleFormat = &llvm::APFloat::IEEEdouble();422 }423 424 // PPC32 supports atomics up to 4 bytes.425 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;426 }427 428 BuiltinVaListKind getBuiltinVaListKind() const override {429 // This is the ELF definition430 return TargetInfo::PowerABIBuiltinVaList;431 }432 433 std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {434 return std::make_pair(32, 32);435 }436};437 438// Note: ABI differences may eventually require us to have a separate439// TargetInfo for little endian.440class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {441public:442 PPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)443 : PPCTargetInfo(Triple, Opts) {444 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;445 IntMaxType = SignedLong;446 Int64Type = SignedLong;447 448 if (Triple.isOSAIX()) {449 // TODO: Set appropriate ABI for AIX platform.450 LongDoubleWidth = 64;451 LongDoubleAlign = DoubleAlign = 32;452 LongDoubleFormat = &llvm::APFloat::IEEEdouble();453 } else if ((Triple.getArch() == llvm::Triple::ppc64le) ||454 Triple.isPPC64ELFv2ABI()) {455 ABI = "elfv2";456 } else {457 ABI = "elfv1";458 }459 460 if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) {461 LongDoubleWidth = LongDoubleAlign = 64;462 LongDoubleFormat = &llvm::APFloat::IEEEdouble();463 }464 465 // Newer PPC64 instruction sets support atomics up to 16 bytes.466 MaxAtomicPromoteWidth = 128;467 // Baseline PPC64 supports inlining atomics up to 8 bytes.468 MaxAtomicInlineWidth = 64;469 470 calculateDataLayout();471 }472 473 void setMaxAtomicWidth() override {474 // For power8 and up, backend is able to inline 16-byte atomic lock free475 // code.476 // TODO: We should allow AIX to inline quadword atomics in the future.477 if (!getTriple().isOSAIX() && hasFeature("quadword-atomics"))478 MaxAtomicInlineWidth = 128;479 }480 481 BuiltinVaListKind getBuiltinVaListKind() const override {482 return TargetInfo::CharPtrBuiltinVaList;483 }484 485 void calculateDataLayout() {486 std::string DataLayout;487 488 if (getTriple().isOSAIX()) {489 DataLayout = "E-m:a-Fi64-i64:64-i128:128-n32:64";490 } else if ((getTriple().getArch() == llvm::Triple::ppc64le)) {491 DataLayout = "e-m:e-Fn32-i64:64-i128:128-n32:64";492 } else {493 DataLayout = "E-m:e";494 if (ABI == "elfv2") {495 DataLayout += "-Fn32";496 } else {497 DataLayout += "-Fi64";498 }499 DataLayout += "-i64:64-i128:128-n32:64";500 }501 502 if (getTriple().isOSAIX() || getTriple().isOSLinux())503 DataLayout += "-S128-v256:256:256-v512:512:512";504 resetDataLayout(DataLayout);505 }506 507 // PPC64 Linux-specific ABI options.508 bool setABI(const std::string &Name) override {509 if (Name == "elfv1" || Name == "elfv2") {510 ABI = Name;511 calculateDataLayout();512 return true;513 }514 return false;515 }516 517 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {518 switch (CC) {519 case CC_Swift:520 return CCCR_OK;521 case CC_SwiftAsync:522 return CCCR_Error;523 default:524 return CCCR_Warning;525 }526 }527 528 std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {529 return std::make_pair(128, 128);530 }531};532 533class LLVM_LIBRARY_VISIBILITY AIXPPC32TargetInfo :534 public AIXTargetInfo<PPC32TargetInfo> {535public:536 using AIXTargetInfo::AIXTargetInfo;537 BuiltinVaListKind getBuiltinVaListKind() const override {538 return TargetInfo::CharPtrBuiltinVaList;539 }540};541 542class LLVM_LIBRARY_VISIBILITY AIXPPC64TargetInfo :543 public AIXTargetInfo<PPC64TargetInfo> {544public:545 using AIXTargetInfo::AIXTargetInfo;546};547 548} // namespace targets549} // namespace clang550#endif // LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H551