| //===--- Targets.cpp - Implement target feature support -------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements construction of a TargetInfo object from a |
| // target triple. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Basic/Builtins.h" |
| #include "clang/Basic/Cuda.h" |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "clang/Basic/MacroBuilder.h" |
| #include "clang/Basic/TargetBuiltins.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Basic/TargetOptions.h" |
| #include "clang/Basic/Version.h" |
| #include "clang/Frontend/CodeGenOptions.h" |
| #include "llvm/ADT/APFloat.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/StringSwitch.h" |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/MC/MCSectionMachO.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/TargetParser.h" |
| #include <algorithm> |
| #include <memory> |
| |
| using namespace clang; |
| |
| //===----------------------------------------------------------------------===// |
| // Common code shared among targets. |
| //===----------------------------------------------------------------------===// |
| |
| /// DefineStd - Define a macro name and standard variants. For example if |
| /// MacroName is "unix", then this will define "__unix", "__unix__", and "unix" |
| /// when in GNU mode. |
| static void DefineStd(MacroBuilder &Builder, StringRef MacroName, |
| const LangOptions &Opts) { |
| assert(MacroName[0] != '_' && "Identifier should be in the user's namespace"); |
| |
| // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier |
| // in the user's namespace. |
| if (Opts.GNUMode) |
| Builder.defineMacro(MacroName); |
| |
| // Define __unix. |
| Builder.defineMacro("__" + MacroName); |
| |
| // Define __unix__. |
| Builder.defineMacro("__" + MacroName + "__"); |
| } |
| |
| static void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName, |
| bool Tuning = true) { |
| Builder.defineMacro("__" + CPUName); |
| Builder.defineMacro("__" + CPUName + "__"); |
| if (Tuning) |
| Builder.defineMacro("__tune_" + CPUName + "__"); |
| } |
| |
| static TargetInfo *AllocateTarget(const llvm::Triple &Triple, |
| const TargetOptions &Opts); |
| |
| //===----------------------------------------------------------------------===// |
| // Defines specific to certain operating systems. |
| //===----------------------------------------------------------------------===// |
| |
| namespace { |
| template<typename TgtInfo> |
| class OSTargetInfo : public TgtInfo { |
| protected: |
| virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const=0; |
| public: |
| OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : TgtInfo(Triple, Opts) {} |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override { |
| TgtInfo::getTargetDefines(Opts, Builder); |
| getOSDefines(Opts, TgtInfo::getTriple(), Builder); |
| } |
| |
| }; |
| |
| // CloudABI Target |
| template <typename Target> |
| class CloudABITargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| Builder.defineMacro("__CloudABI__"); |
| Builder.defineMacro("__ELF__"); |
| |
| // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t. |
| Builder.defineMacro("__STDC_ISO_10646__", "201206L"); |
| Builder.defineMacro("__STDC_UTF_16__"); |
| Builder.defineMacro("__STDC_UTF_32__"); |
| } |
| |
| public: |
| CloudABITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) {} |
| }; |
| |
| static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, |
| const llvm::Triple &Triple, |
| StringRef &PlatformName, |
| VersionTuple &PlatformMinVersion) { |
| Builder.defineMacro("__APPLE_CC__", "6000"); |
| Builder.defineMacro("__APPLE__"); |
| Builder.defineMacro("OBJC_NEW_PROPERTIES"); |
| // AddressSanitizer doesn't play well with source fortification, which is on |
| // by default on Darwin. |
| if (Opts.Sanitize.has(SanitizerKind::Address)) |
| Builder.defineMacro("_FORTIFY_SOURCE", "0"); |
| |
| // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode. |
| if (!Opts.ObjC1) { |
| // __weak is always defined, for use in blocks and with objc pointers. |
| Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); |
| Builder.defineMacro("__strong", ""); |
| Builder.defineMacro("__unsafe_unretained", ""); |
| } |
| |
| if (Opts.Static) |
| Builder.defineMacro("__STATIC__"); |
| else |
| Builder.defineMacro("__DYNAMIC__"); |
| |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| |
| // Get the platform type and version number from the triple. |
| unsigned Maj, Min, Rev; |
| if (Triple.isMacOSX()) { |
| Triple.getMacOSXVersion(Maj, Min, Rev); |
| PlatformName = "macos"; |
| } else { |
| Triple.getOSVersion(Maj, Min, Rev); |
| PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); |
| } |
| |
| // If -target arch-pc-win32-macho option specified, we're |
| // generating code for Win32 ABI. No need to emit |
| // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__. |
| if (PlatformName == "win32") { |
| PlatformMinVersion = VersionTuple(Maj, Min, Rev); |
| return; |
| } |
| |
| // Set the appropriate OS version define. |
| if (Triple.isiOS()) { |
| assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); |
| char Str[7]; |
| if (Maj < 10) { |
| Str[0] = '0' + Maj; |
| Str[1] = '0' + (Min / 10); |
| Str[2] = '0' + (Min % 10); |
| Str[3] = '0' + (Rev / 10); |
| Str[4] = '0' + (Rev % 10); |
| Str[5] = '\0'; |
| } else { |
| // Handle versions >= 10. |
| Str[0] = '0' + (Maj / 10); |
| Str[1] = '0' + (Maj % 10); |
| Str[2] = '0' + (Min / 10); |
| Str[3] = '0' + (Min % 10); |
| Str[4] = '0' + (Rev / 10); |
| Str[5] = '0' + (Rev % 10); |
| Str[6] = '\0'; |
| } |
| if (Triple.isTvOS()) |
| Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str); |
| else |
| Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", |
| Str); |
| |
| } else if (Triple.isWatchOS()) { |
| assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); |
| char Str[6]; |
| Str[0] = '0' + Maj; |
| Str[1] = '0' + (Min / 10); |
| Str[2] = '0' + (Min % 10); |
| Str[3] = '0' + (Rev / 10); |
| Str[4] = '0' + (Rev % 10); |
| Str[5] = '\0'; |
| Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str); |
| } else if (Triple.isMacOSX()) { |
| // Note that the Driver allows versions which aren't representable in the |
| // define (because we only get a single digit for the minor and micro |
| // revision numbers). So, we limit them to the maximum representable |
| // version. |
| assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); |
| char Str[7]; |
| if (Maj < 10 || (Maj == 10 && Min < 10)) { |
| Str[0] = '0' + (Maj / 10); |
| Str[1] = '0' + (Maj % 10); |
| Str[2] = '0' + std::min(Min, 9U); |
| Str[3] = '0' + std::min(Rev, 9U); |
| Str[4] = '\0'; |
| } else { |
| // Handle versions > 10.9. |
| Str[0] = '0' + (Maj / 10); |
| Str[1] = '0' + (Maj % 10); |
| Str[2] = '0' + (Min / 10); |
| Str[3] = '0' + (Min % 10); |
| Str[4] = '0' + (Rev / 10); |
| Str[5] = '0' + (Rev % 10); |
| Str[6] = '\0'; |
| } |
| Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); |
| } |
| |
| // Tell users about the kernel if there is one. |
| if (Triple.isOSDarwin()) |
| Builder.defineMacro("__MACH__"); |
| |
| // The Watch ABI uses Dwarf EH. |
| if(Triple.isWatchABI()) |
| Builder.defineMacro("__ARM_DWARF_EH__"); |
| |
| PlatformMinVersion = VersionTuple(Maj, Min, Rev); |
| } |
| |
| template<typename Target> |
| class DarwinTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| getDarwinDefines(Builder, Opts, Triple, this->PlatformName, |
| this->PlatformMinVersion); |
| } |
| |
| public: |
| DarwinTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| // By default, no TLS, and we whitelist permitted architecture/OS |
| // combinations. |
| this->TLSSupported = false; |
| |
| if (Triple.isMacOSX()) |
| this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7); |
| else if (Triple.isiOS()) { |
| // 64-bit iOS supported it from 8 onwards, 32-bit from 9 onwards. |
| if (Triple.getArch() == llvm::Triple::x86_64 || |
| Triple.getArch() == llvm::Triple::aarch64) |
| this->TLSSupported = !Triple.isOSVersionLT(8); |
| else if (Triple.getArch() == llvm::Triple::x86 || |
| Triple.getArch() == llvm::Triple::arm || |
| Triple.getArch() == llvm::Triple::thumb) |
| this->TLSSupported = !Triple.isOSVersionLT(9); |
| } else if (Triple.isWatchOS()) |
| this->TLSSupported = !Triple.isOSVersionLT(2); |
| |
| this->MCountName = "\01mcount"; |
| } |
| |
| std::string isValidSectionSpecifier(StringRef SR) const override { |
| // Let MCSectionMachO validate this. |
| StringRef Segment, Section; |
| unsigned TAA, StubSize; |
| bool HasTAA; |
| return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section, |
| TAA, HasTAA, StubSize); |
| } |
| |
| const char *getStaticInitSectionSpecifier() const override { |
| // FIXME: We should return 0 when building kexts. |
| return "__TEXT,__StaticInit,regular,pure_instructions"; |
| } |
| |
| /// Darwin does not support protected visibility. Darwin's "default" |
| /// is very similar to ELF's "protected"; Darwin requires a "weak" |
| /// attribute on declarations that can be dynamically replaced. |
| bool hasProtectedVisibility() const override { |
| return false; |
| } |
| |
| unsigned getExnObjectAlignment() const override { |
| // The alignment of an exception object is 8-bytes for darwin since |
| // libc++abi doesn't declare _Unwind_Exception with __attribute__((aligned)) |
| // and therefore doesn't guarantee 16-byte alignment. |
| return 64; |
| } |
| }; |
| |
| |
| // DragonFlyBSD Target |
| template<typename Target> |
| class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // DragonFly defines; list based off of gcc output |
| Builder.defineMacro("__DragonFly__"); |
| Builder.defineMacro("__DragonFly_cc_version", "100001"); |
| Builder.defineMacro("__ELF__"); |
| Builder.defineMacro("__KPRINTF_ATTRIBUTE__"); |
| Builder.defineMacro("__tune_i386__"); |
| DefineStd(Builder, "unix", Opts); |
| } |
| public: |
| DragonFlyBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| switch (Triple.getArch()) { |
| default: |
| case llvm::Triple::x86: |
| case llvm::Triple::x86_64: |
| this->MCountName = ".mcount"; |
| break; |
| } |
| } |
| }; |
| |
| #ifndef FREEBSD_CC_VERSION |
| #define FREEBSD_CC_VERSION 0U |
| #endif |
| |
| // FreeBSD Target |
| template<typename Target> |
| class FreeBSDTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // FreeBSD defines; list based off of gcc output |
| |
| unsigned Release = Triple.getOSMajorVersion(); |
| if (Release == 0U) |
| Release = 8U; |
| unsigned CCVersion = FREEBSD_CC_VERSION; |
| if (CCVersion == 0U) |
| CCVersion = Release * 100000U + 1U; |
| |
| Builder.defineMacro("__FreeBSD__", Twine(Release)); |
| Builder.defineMacro("__FreeBSD_cc_version", Twine(CCVersion)); |
| Builder.defineMacro("__KPRINTF_ATTRIBUTE__"); |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__ELF__"); |
| |
| // On FreeBSD, wchar_t contains the number of the code point as |
| // used by the character set of the locale. These character sets are |
| // not necessarily a superset of ASCII. |
| // |
| // FIXME: This is wrong; the macro refers to the numerical values |
| // of wchar_t *literals*, which are not locale-dependent. However, |
| // FreeBSD systems apparently depend on us getting this wrong, and |
| // setting this to 1 is conforming even if all the basic source |
| // character literals have the same encoding as char and wchar_t. |
| Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1"); |
| } |
| public: |
| FreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| switch (Triple.getArch()) { |
| default: |
| case llvm::Triple::x86: |
| case llvm::Triple::x86_64: |
| this->MCountName = ".mcount"; |
| break; |
| case llvm::Triple::mips: |
| case llvm::Triple::mipsel: |
| case llvm::Triple::ppc: |
| case llvm::Triple::ppc64: |
| case llvm::Triple::ppc64le: |
| this->MCountName = "_mcount"; |
| break; |
| case llvm::Triple::arm: |
| this->MCountName = "__mcount"; |
| break; |
| } |
| } |
| }; |
| |
| // GNU/kFreeBSD Target |
| template<typename Target> |
| class KFreeBSDTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // GNU/kFreeBSD defines; list based off of gcc output |
| |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__FreeBSD_kernel__"); |
| Builder.defineMacro("__GLIBC__"); |
| Builder.defineMacro("__ELF__"); |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| if (Opts.CPlusPlus) |
| Builder.defineMacro("_GNU_SOURCE"); |
| } |
| public: |
| KFreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) {} |
| }; |
| |
| // Haiku Target |
| template<typename Target> |
| class HaikuTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // Haiku defines; list based off of gcc output |
| Builder.defineMacro("__HAIKU__"); |
| Builder.defineMacro("__ELF__"); |
| DefineStd(Builder, "unix", Opts); |
| } |
| public: |
| HaikuTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->SizeType = TargetInfo::UnsignedLong; |
| this->IntPtrType = TargetInfo::SignedLong; |
| this->PtrDiffType = TargetInfo::SignedLong; |
| this->ProcessIDType = TargetInfo::SignedLong; |
| this->TLSSupported = false; |
| |
| } |
| }; |
| |
| // Minix Target |
| template<typename Target> |
| class MinixTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // Minix defines |
| |
| Builder.defineMacro("__minix", "3"); |
| Builder.defineMacro("_EM_WSIZE", "4"); |
| Builder.defineMacro("_EM_PSIZE", "4"); |
| Builder.defineMacro("_EM_SSIZE", "2"); |
| Builder.defineMacro("_EM_LSIZE", "4"); |
| Builder.defineMacro("_EM_FSIZE", "4"); |
| Builder.defineMacro("_EM_DSIZE", "8"); |
| Builder.defineMacro("__ELF__"); |
| DefineStd(Builder, "unix", Opts); |
| } |
| public: |
| MinixTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) {} |
| }; |
| |
| // Linux target |
| template<typename Target> |
| class LinuxTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // Linux defines; list based off of gcc output |
| DefineStd(Builder, "unix", Opts); |
| DefineStd(Builder, "linux", Opts); |
| Builder.defineMacro("__gnu_linux__"); |
| Builder.defineMacro("__ELF__"); |
| if (Triple.isAndroid()) { |
| Builder.defineMacro("__ANDROID__", "1"); |
| unsigned Maj, Min, Rev; |
| Triple.getEnvironmentVersion(Maj, Min, Rev); |
| this->PlatformName = "android"; |
| this->PlatformMinVersion = VersionTuple(Maj, Min, Rev); |
| if (Maj) |
| Builder.defineMacro("__ANDROID_API__", Twine(Maj)); |
| } |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| if (Opts.CPlusPlus) |
| Builder.defineMacro("_GNU_SOURCE"); |
| if (this->HasFloat128) |
| Builder.defineMacro("__FLOAT128__"); |
| } |
| public: |
| LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->WIntType = TargetInfo::UnsignedInt; |
| |
| switch (Triple.getArch()) { |
| default: |
| break; |
| case llvm::Triple::ppc: |
| case llvm::Triple::ppc64: |
| case llvm::Triple::ppc64le: |
| this->MCountName = "_mcount"; |
| break; |
| case llvm::Triple::x86: |
| case llvm::Triple::x86_64: |
| case llvm::Triple::systemz: |
| this->HasFloat128 = true; |
| break; |
| } |
| } |
| |
| const char *getStaticInitSectionSpecifier() const override { |
| return ".text.startup"; |
| } |
| }; |
| |
| // NetBSD Target |
| template<typename Target> |
| class NetBSDTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // NetBSD defines; list based off of gcc output |
| Builder.defineMacro("__NetBSD__"); |
| Builder.defineMacro("__unix__"); |
| Builder.defineMacro("__ELF__"); |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| |
| switch (Triple.getArch()) { |
| default: |
| break; |
| case llvm::Triple::arm: |
| case llvm::Triple::armeb: |
| case llvm::Triple::thumb: |
| case llvm::Triple::thumbeb: |
| Builder.defineMacro("__ARM_DWARF_EH__"); |
| break; |
| } |
| } |
| public: |
| NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->MCountName = "_mcount"; |
| } |
| }; |
| |
| // OpenBSD Target |
| template<typename Target> |
| class OpenBSDTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // OpenBSD defines; list based off of gcc output |
| |
| Builder.defineMacro("__OpenBSD__"); |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__ELF__"); |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| } |
| public: |
| OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->TLSSupported = false; |
| |
| switch (Triple.getArch()) { |
| default: |
| case llvm::Triple::x86: |
| case llvm::Triple::x86_64: |
| case llvm::Triple::arm: |
| case llvm::Triple::sparc: |
| this->MCountName = "__mcount"; |
| break; |
| case llvm::Triple::mips64: |
| case llvm::Triple::mips64el: |
| case llvm::Triple::ppc: |
| case llvm::Triple::sparcv9: |
| this->MCountName = "_mcount"; |
| break; |
| } |
| } |
| }; |
| |
| // Bitrig Target |
| template<typename Target> |
| class BitrigTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // Bitrig defines; list based off of gcc output |
| |
| Builder.defineMacro("__Bitrig__"); |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__ELF__"); |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| |
| switch (Triple.getArch()) { |
| default: |
| break; |
| case llvm::Triple::arm: |
| case llvm::Triple::armeb: |
| case llvm::Triple::thumb: |
| case llvm::Triple::thumbeb: |
| Builder.defineMacro("__ARM_DWARF_EH__"); |
| break; |
| } |
| } |
| public: |
| BitrigTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->MCountName = "__mcount"; |
| } |
| }; |
| |
| // PSP Target |
| template<typename Target> |
| class PSPTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // PSP defines; list based on the output of the pspdev gcc toolchain. |
| Builder.defineMacro("PSP"); |
| Builder.defineMacro("_PSP"); |
| Builder.defineMacro("__psp__"); |
| Builder.defineMacro("__ELF__"); |
| } |
| public: |
| PSPTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {} |
| }; |
| |
| // PS3 PPU Target |
| template<typename Target> |
| class PS3PPUTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| // PS3 PPU defines. |
| Builder.defineMacro("__PPC__"); |
| Builder.defineMacro("__PPU__"); |
| Builder.defineMacro("__CELLOS_LV2__"); |
| Builder.defineMacro("__ELF__"); |
| Builder.defineMacro("__LP32__"); |
| Builder.defineMacro("_ARCH_PPC64"); |
| Builder.defineMacro("__powerpc64__"); |
| } |
| public: |
| PS3PPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->LongWidth = this->LongAlign = 32; |
| this->PointerWidth = this->PointerAlign = 32; |
| this->IntMaxType = TargetInfo::SignedLongLong; |
| this->Int64Type = TargetInfo::SignedLongLong; |
| this->SizeType = TargetInfo::UnsignedInt; |
| this->resetDataLayout("E-m:e-p:32:32-i64:64-n32:64"); |
| } |
| }; |
| |
| template <typename Target> |
| class PS4OSTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| Builder.defineMacro("__FreeBSD__", "9"); |
| Builder.defineMacro("__FreeBSD_cc_version", "900001"); |
| Builder.defineMacro("__KPRINTF_ATTRIBUTE__"); |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__ELF__"); |
| Builder.defineMacro("__ORBIS__"); |
| } |
| public: |
| PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->WCharType = this->UnsignedShort; |
| |
| // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits). |
| this->MaxTLSAlign = 256; |
| |
| // On PS4, do not honor explicit bit field alignment, |
| // as in "__attribute__((aligned(2))) int b : 1;". |
| this->UseExplicitBitFieldAlignment = false; |
| |
| switch (Triple.getArch()) { |
| default: |
| case llvm::Triple::x86_64: |
| this->MCountName = ".mcount"; |
| break; |
| } |
| } |
| }; |
| |
| // Solaris target |
| template<typename Target> |
| class SolarisTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| DefineStd(Builder, "sun", Opts); |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__ELF__"); |
| Builder.defineMacro("__svr4__"); |
| Builder.defineMacro("__SVR4"); |
| // Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and |
| // newer, but to 500 for everything else. feature_test.h has a check to |
| // ensure that you are not using C99 with an old version of X/Open or C89 |
| // with a new version. |
| if (Opts.C99) |
| Builder.defineMacro("_XOPEN_SOURCE", "600"); |
| else |
| Builder.defineMacro("_XOPEN_SOURCE", "500"); |
| if (Opts.CPlusPlus) |
| Builder.defineMacro("__C99FEATURES__"); |
| Builder.defineMacro("_LARGEFILE_SOURCE"); |
| Builder.defineMacro("_LARGEFILE64_SOURCE"); |
| Builder.defineMacro("__EXTENSIONS__"); |
| Builder.defineMacro("_REENTRANT"); |
| } |
| public: |
| SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->WCharType = this->SignedInt; |
| // FIXME: WIntType should be SignedLong |
| } |
| }; |
| |
| // Windows target |
| template<typename Target> |
| class WindowsTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| Builder.defineMacro("_WIN32"); |
| } |
| void getVisualStudioDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| if (Opts.CPlusPlus) { |
| if (Opts.RTTIData) |
| Builder.defineMacro("_CPPRTTI"); |
| |
| if (Opts.CXXExceptions) |
| Builder.defineMacro("_CPPUNWIND"); |
| } |
| |
| if (Opts.Bool) |
| Builder.defineMacro("__BOOL_DEFINED"); |
| |
| if (!Opts.CharIsSigned) |
| Builder.defineMacro("_CHAR_UNSIGNED"); |
| |
| // FIXME: POSIXThreads isn't exactly the option this should be defined for, |
| // but it works for now. |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_MT"); |
| |
| if (Opts.MSCompatibilityVersion) { |
| Builder.defineMacro("_MSC_VER", |
| Twine(Opts.MSCompatibilityVersion / 100000)); |
| Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); |
| // FIXME We cannot encode the revision information into 32-bits |
| Builder.defineMacro("_MSC_BUILD", Twine(1)); |
| |
| if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) |
| Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); |
| |
| if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { |
| if (Opts.CPlusPlus1z) |
| Builder.defineMacro("_MSVC_LANG", "201403L"); |
| else if (Opts.CPlusPlus14) |
| Builder.defineMacro("_MSVC_LANG", "201402L"); |
| } |
| } |
| |
| if (Opts.MicrosoftExt) { |
| Builder.defineMacro("_MSC_EXTENSIONS"); |
| |
| if (Opts.CPlusPlus11) { |
| Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED"); |
| Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED"); |
| Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED"); |
| } |
| } |
| |
| Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); |
| } |
| |
| public: |
| WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) {} |
| }; |
| |
| template <typename Target> |
| class NaClTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| if (Opts.CPlusPlus) |
| Builder.defineMacro("_GNU_SOURCE"); |
| |
| DefineStd(Builder, "unix", Opts); |
| Builder.defineMacro("__ELF__"); |
| Builder.defineMacro("__native_client__"); |
| } |
| |
| public: |
| NaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->LongAlign = 32; |
| this->LongWidth = 32; |
| this->PointerAlign = 32; |
| this->PointerWidth = 32; |
| this->IntMaxType = TargetInfo::SignedLongLong; |
| this->Int64Type = TargetInfo::SignedLongLong; |
| this->DoubleAlign = 64; |
| this->LongDoubleWidth = 64; |
| this->LongDoubleAlign = 64; |
| this->LongLongWidth = 64; |
| this->LongLongAlign = 64; |
| this->SizeType = TargetInfo::UnsignedInt; |
| this->PtrDiffType = TargetInfo::SignedInt; |
| this->IntPtrType = TargetInfo::SignedInt; |
| // RegParmMax is inherited from the underlying architecture. |
| this->LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
| if (Triple.getArch() == llvm::Triple::arm) { |
| // Handled in ARM's setABI(). |
| } else if (Triple.getArch() == llvm::Triple::x86) { |
| this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32-S128"); |
| } else if (Triple.getArch() == llvm::Triple::x86_64) { |
| this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32:64-S128"); |
| } else if (Triple.getArch() == llvm::Triple::mipsel) { |
| // Handled on mips' setDataLayout. |
| } else { |
| assert(Triple.getArch() == llvm::Triple::le32); |
| this->resetDataLayout("e-p:32:32-i64:64"); |
| } |
| } |
| }; |
| |
| // Fuchsia Target |
| template<typename Target> |
| class FuchsiaTargetInfo : public OSTargetInfo<Target> { |
| protected: |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const override { |
| Builder.defineMacro("__Fuchsia__"); |
| Builder.defineMacro("__ELF__"); |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| // Required by the libc++ locale support. |
| if (Opts.CPlusPlus) |
| Builder.defineMacro("_GNU_SOURCE"); |
| } |
| public: |
| FuchsiaTargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->MCountName = "__mcount"; |
| } |
| }; |
| |
| // WebAssembly target |
| template <typename Target> |
| class WebAssemblyOSTargetInfo : public OSTargetInfo<Target> { |
| void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
| MacroBuilder &Builder) const final { |
| // A common platform macro. |
| if (Opts.POSIXThreads) |
| Builder.defineMacro("_REENTRANT"); |
| // Follow g++ convention and predefine _GNU_SOURCE for C++. |
| if (Opts.CPlusPlus) |
| Builder.defineMacro("_GNU_SOURCE"); |
| } |
| |
| // As an optimization, group static init code together in a section. |
| const char *getStaticInitSectionSpecifier() const final { |
| return ".text.__startup"; |
| } |
| |
| public: |
| explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : OSTargetInfo<Target>(Triple, Opts) { |
| this->MCountName = "__mcount"; |
| this->TheCXXABI.set(TargetCXXABI::WebAssembly); |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // Specific target implementations. |
| //===----------------------------------------------------------------------===// |
| |
| // PPC abstract base class |
| class PPCTargetInfo : public TargetInfo { |
| static const Builtin::Info BuiltinInfo[]; |
| static const char * const GCCRegNames[]; |
| static const TargetInfo::GCCRegAlias GCCRegAliases[]; |
| std::string CPU; |
| |
| // Target cpu features. |
| bool HasVSX; |
| bool HasP8Vector; |
| bool HasP8Crypto; |
| bool HasDirectMove; |
| bool HasQPX; |
| bool HasHTM; |
| bool HasBPERMD; |
| bool HasExtDiv; |
| bool HasP9Vector; |
| |
| protected: |
| std::string ABI; |
| |
| public: |
| PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
| : TargetInfo(Triple), HasVSX(false), HasP8Vector(false), |
| HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false), |
| HasBPERMD(false), HasExtDiv(false), HasP9Vector(false) { |
| SimdDefaultAlign = 128; |
| LongDoubleWidth = LongDoubleAlign = 128; |
| LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); |
| } |
| |
| /// \brief Flags for architecture specific defines. |
| typedef enum { |
| ArchDefineNone = 0, |
| ArchDefineName = 1 << 0, // <name> is substituted for arch name. |
| ArchDefinePpcgr = 1 << 1, |
| ArchDefinePpcsq = 1 << 2, |
| ArchDefine440 = 1 << 3, |
| ArchDefine603 = 1 << 4, |
| ArchDefine604 = 1 << 5, |
| ArchDefinePwr4 = 1 << 6, |
| ArchDefinePwr5 = 1 << 7, |
| ArchDefinePwr5x = 1 << 8, |
| ArchDefinePwr6 = 1 << 9, |
| ArchDefinePwr6x = 1 << 10, |
| ArchDefinePwr7 = 1 << 11, |
| ArchDefinePwr8 = 1 << 12, |
| ArchDefinePwr9 = 1 << 13, |
| ArchDefineA2 = 1 << 14, |
| ArchDefineA2q = 1 << 15 |
| } ArchDefineTypes; |
| |
| // Note: GCC recognizes the following additional cpus: |
| // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801, |
| // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell, |
| // titan, rs64. |
| bool setCPU(const std::string &Name) override { |
| bool CPUKnown = llvm::StringSwitch<bool>(Name) |
| .Case("generic", true) |
| .Case("440", true) |
| .Case("450", true) |
| .Case("601", true) |
| .Case("602", true) |
| .Case("603", true) |
| .Case("603e", true) |
| .Case("603ev", true) |
| .Case("604", true) |
| .Case("604e", true) |
| .Case("620", true) |
| .Case("630", true) |
| .Case("g3", true) |
| .Case("7400", true) |
| .Case("g4", true) |
| .Case("7450", true) |
| .Case("g4+", true) |
| .Case("750", true) |
| .Case("970", true) |
| .Case("g5", true) |
| .Case("a2", true) |
| .Case("a2q", true) |
| .Case("e500mc", true) |
| .Case("e5500", true) |
| .Case("power3", true) |
| .Case("pwr3", true) |
| .Case("power4", true) |
| .Case("pwr4", true) |
| .Case("power5", true) |
| .Case("pwr5", true) |
| .Case("power5x", true) |
| .Case("pwr5x", true) |
| .Case("power6", true) |
| .Case("pwr6", true) |
| .Case("power6x", true) |
| .Case("pwr6x", true) |
| .Case("power7", true) |
| .Case("pwr7", true) |
| .Case("power8", true) |
| .Case("pwr8", true) |
| .Case("power9", true) |
| .Case("pwr9", true) |
| .Case("powerpc", true) |
| .Case("ppc", true) |
| .Case("powerpc64", true) |
| .Case("ppc64", true) |
| .Case("powerpc64le", true) |
| .Case("ppc64le", true) |
| .Default(false); |
| |
| if (CPUKnown) |
| CPU = Name; |
| |
| return CPUKnown; |
| } |
| |
| |
| StringRef getABI() const override { return ABI; } |
| |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override { |
| return llvm::makeArrayRef(BuiltinInfo, |
| clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin); |
| } |
| |
| bool isCLZForZeroUndef() const override { return false; } |
| |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override; |
| |
| bool |
| initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, |
| StringRef CPU, |
| const std::vector<std::string> &FeaturesVec) const override; |
| |
| bool handleTargetFeatures(std::vector<std::string> &Features, |
| DiagnosticsEngine &Diags) override; |
| bool hasFeature(StringRef Feature) const override; |
| void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, |
| bool Enabled) const override; |
| |
| ArrayRef<const char *> getGCCRegNames() const override; |
| ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; |
| bool validateAsmConstraint(const char *&Name, |
| TargetInfo::ConstraintInfo &Info) const override { |
| switch (*Name) { |
| default: return false; |
| case 'O': // Zero |
| break; |
| case 'b': // Base register |
| case 'f': // Floating point register |
| Info.setAllowsRegister(); |
| break; |
| // FIXME: The following are added to allow parsing. |
| // I just took a guess at what the actions should be. |
| // Also, is more specific checking needed? I.e. specific registers? |
| case 'd': // Floating point register (containing 64-bit value) |
| case 'v': // Altivec vector register |
| Info.setAllowsRegister(); |
| break; |
| case 'w': |
| switch (Name[1]) { |
| case 'd':// VSX vector register to hold vector double data |
| case 'f':// VSX vector register to hold vector float data |
| case 's':// VSX vector register to hold scalar float data |
| case 'a':// Any VSX register |
| case 'c':// An individual CR bit |
| break; |
| default: |
| return false; |
| } |
| Info.setAllowsRegister(); |
| Name++; // Skip over 'w'. |
| break; |
| case 'h': // `MQ', `CTR', or `LINK' register |
| case 'q': // `MQ' register |
| case 'c': // `CTR' register |
| case 'l': // `LINK' register |
| case 'x': // `CR' register (condition register) number 0 |
| case 'y': // `CR' register (condition register) |
| case 'z': // `XER[CA]' carry bit (part of the XER register) |
| Info.setAllowsRegister(); |
| break; |
| case 'I': // Signed 16-bit constant |
| case 'J': // Unsigned 16-bit constant shifted left 16 bits |
| // (use `L' instead for SImode constants) |
| case 'K': // Unsigned 16-bit constant |
| case 'L': // Signed 16-bit constant shifted left 16 bits |
| case 'M': // Constant larger than 31 |
| case 'N': // Exact power of 2 |
| case 'P': // Constant whose negation is a signed 16-bit constant |
| case 'G': // Floating point constant that can be loaded into a |
| // register with one instruction per word |
| case 'H': // Integer/Floating point constant that can be loaded |
| // into a register using three instructions |
| break; |
| case 'm': // Memory operand. Note that on PowerPC targets, m can |
| // include addresses that update the base register. It |
| // is therefore only safe to use `m' in an asm statement |
| // if that asm statement accesses the operand exactly once. |
| // The asm statement must also use `%U<opno>' as a |
| // placeholder for the "update" flag in the corresponding |
| // load or store instruction. For example: |
| // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val)); |
| // is correct but: |
| // asm ("st %1,%0" : "=m" (mem) : "r" (val)); |
| // is not. Use es rather than m if you don't want the base |
| // register to be updated. |
| case 'e': |
| if (Name[1] != 's') |
| return false; |
| // es: A "stable" memory operand; that is, one which does not |
| // include any automodification of the base register. Unlike |
| // `m', this constraint can be used in asm statements that |
| // might access the operand several times, or that might not |
| // access it at all. |
| Info.setAllowsMemory(); |
| Name++; // Skip over 'e'. |
| break; |
| case 'Q': // Memory operand that is an offset from a register (it is |
| // usually better to use `m' or `es' in asm statements) |
| case 'Z': // Memory operand that is an indexed or indirect from a |
| // register (it is usually better to use `m' or `es' in |
| // asm statements) |
| Info.setAllowsMemory(); |
| Info.setAllowsRegister(); |
| break; |
| case 'R': // AIX TOC entry |
| case 'a': // Address operand that is an indexed or indirect from a |
| // register (`p' is preferable for asm statements) |
| case 'S': // Constant suitable as a 64-bit mask operand |
| case 'T': // Constant suitable as a 32-bit mask operand |
| case 'U': // System V Release 4 small data area reference |
| case 't': // AND masks that can be performed by two rldic{l, r} |
| // instructions |
| case 'W': // Vector constant that does not require memory |
| case 'j': // Vector constant that is all zeros. |
| break; |
| // End FIXME. |
| } |
| return true; |
| } |
| std::string convertConstraint(const char *&Constraint) const override { |
| std::string R; |
| switch (*Constraint) { |
| case 'e': |
| case 'w': |
| // Two-character constraint; add "^" hint for later parsing. |
| R = std::string("^") + std::string(Constraint, 2); |
| Constraint++; |
| break; |
| default: |
| return TargetInfo::convertConstraint(Constraint); |
| } |
| return R; |
| } |
| const char *getClobbers() const override { |
| return ""; |
| } |
| int getEHDataRegisterNumber(unsigned RegNo) const override { |
| if (RegNo == 0) return 3; |
| if (RegNo == 1) return 4; |
| return -1; |
| } |
| |
| bool hasSjLjLowering() const override { |
| return true; |
| } |
| |
| bool useFloat128ManglingForLongDouble() const override { |
| return LongDoubleWidth == 128 && |
| LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble() && |
| getTriple().isOSBinFormatELF(); |
| } |
| }; |
| |
| const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, |
| #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ |
| { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr }, |
| #include "clang/Basic/BuiltinsPPC.def" |
| }; |
| |
| /// handleTargetFeatures - Perform initialization based on the user |
| /// configured set of features. |
| bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, |
| DiagnosticsEngine &Diags) { |
| for (const auto &Feature : Features) { |
| if (Feature == "+vsx") { |
| HasVSX = true; |
| } else if (Feature == "+bpermd") { |
| HasBPERMD = true; |
| } else if (Feature == "+extdiv") { |
| HasExtDiv = true; |
| } else if (Feature == "+power8-vector") { |
| HasP8Vector = true; |
| } else if (Feature == "+crypto") { |
| HasP8Crypto = true; |
| } else if (Feature == "+direct-move") { |
| HasDirectMove = true; |
| } else if (Feature == "+qpx") { |
| HasQPX = true; |
| } else if (Feature == "+htm") { |
| HasHTM = true; |
| } else if (Feature == "+float128") { |
| HasFloat128 = true; |
| } else if (Feature == "+power9-vector") { |
| HasP9Vector = true; |
| } |
| // TODO: Finish this list and add an assert that we've handled them |
| // all. |
| } |
| |
| return true; |
| } |
| |
| /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific |
| /// #defines that are not tied to a specific subtarget. |
| void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| // Target identification. |
| Builder.defineMacro("__ppc__"); |
| Builder.defineMacro("__PPC__"); |
| Builder.defineMacro("_ARCH_PPC"); |
| Builder.defineMacro("__powerpc__"); |
| Builder.defineMacro("__POWERPC__"); |
| if (PointerWidth == 64) { |
| Builder.defineMacro("_ARCH_PPC64"); |
| Builder.defineMacro("__powerpc64__"); |
| Builder.defineMacro("__ppc64__"); |
| Builder.defineMacro("__PPC64__"); |
| } |
| |
| // Target properties. |
| if (getTriple().getArch() == llvm::Triple::ppc64le) { |
| Builder.defineMacro("_LITTLE_ENDIAN"); |
| } else { |
| if (getTriple().getOS() != llvm::Triple::NetBSD && |
| getTriple().getOS() != llvm::Triple::OpenBSD) |
| Builder.defineMacro("_BIG_ENDIAN"); |
| } |
| |
| // ABI options. |
| if (ABI == "elfv1" || ABI == "elfv1-qpx") |
| Builder.defineMacro("_CALL_ELF", "1"); |
| if (ABI == "elfv2") |
| Builder.defineMacro("_CALL_ELF", "2"); |
| |
| // Subtarget options. |
| Builder.defineMacro("__NATURAL_ALIGNMENT__"); |
| Builder.defineMacro("__REGISTER_PREFIX__", ""); |
| |
| // FIXME: Should be controlled by command line option. |
| if (LongDoubleWidth == 128) |
| Builder.defineMacro("__LONG_DOUBLE_128__"); |
| |
| if (Opts.AltiVec) { |
| Builder.defineMacro("__VEC__", "10206"); |
| Builder.defineMacro("__ALTIVEC__"); |
| } |
| |
| // CPU identification. |
| ArchDefineTypes defs = (ArchDefineTypes)llvm::StringSwitch<int>(CPU) |
| .Case("440", ArchDefineName) |
| .Case("450", ArchDefineName | ArchDefine440) |
| .Case("601", ArchDefineName) |
| .Case("602", ArchDefineName | ArchDefinePpcgr) |
| .Case("603", ArchDefineName | ArchDefinePpcgr) |
| .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) |
| .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) |
| .Case("604", ArchDefineName | ArchDefinePpcgr) |
| .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr) |
| .Case("620", ArchDefineName | ArchDefinePpcgr) |
| .Case("630", ArchDefineName | ArchDefinePpcgr) |
| .Case("7400", ArchDefineName | ArchDefinePpcgr) |
| .Case("7450", ArchDefineName | ArchDefinePpcgr) |
| .Case("750", ArchDefineName | ArchDefinePpcgr) |
| .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Case("a2", ArchDefineA2) |
| .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q) |
| .Case("pwr3", ArchDefinePpcgr) |
| .Case("pwr4", ArchDefineName | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("pwr5", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Case("pwr5x", ArchDefineName | ArchDefinePwr5 | ArchDefinePwr4 |
| | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("pwr6", ArchDefineName | ArchDefinePwr5x | ArchDefinePwr5 |
| | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("pwr6x", ArchDefineName | ArchDefinePwr6 | ArchDefinePwr5x |
| | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Case("pwr7", ArchDefineName | ArchDefinePwr6x | ArchDefinePwr6 |
| | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
| | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("pwr8", ArchDefineName | ArchDefinePwr7 | ArchDefinePwr6x |
| | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
| | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("pwr9", ArchDefineName | ArchDefinePwr8 | ArchDefinePwr7 |
| | ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
| | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Case("power3", ArchDefinePpcgr) |
| .Case("power4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("power5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Case("power5x", ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
| | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("power6", ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
| | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("power6x", ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
| | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Case("power7", ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 |
| | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
| | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("power8", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x |
| | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
| | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
| .Case("power9", ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |
| | ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x |
| | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
| | ArchDefinePpcsq) |
| .Default(ArchDefineNone); |
| |
| if (defs & ArchDefineName) |
| Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper())); |
| if (defs & ArchDefinePpcgr) |
| Builder.defineMacro("_ARCH_PPCGR"); |
| if (defs & ArchDefinePpcsq) |
| Builder.defineMacro("_ARCH_PPCSQ"); |
| if (defs & ArchDefine440) |
| Builder.defineMacro("_ARCH_440"); |
| if (defs & ArchDefine603) |
| Builder.defineMacro("_ARCH_603"); |
| if (defs & ArchDefine604) |
| Builder.defineMacro("_ARCH_604"); |
| if (defs & ArchDefinePwr4) |
| Builder.defineMacro("_ARCH_PWR4"); |
| if (defs & ArchDefinePwr5) |
| Builder.defineMacro("_ARCH_PWR5"); |
| if (defs & ArchDefinePwr5x) |
| Builder.defineMacro("_ARCH_PWR5X"); |
| if (defs & ArchDefinePwr6) |
| Builder.defineMacro("_ARCH_PWR6"); |
| if (defs & ArchDefinePwr6x) |
| Builder.defineMacro("_ARCH_PWR6X"); |
| if (defs & ArchDefinePwr7) |
| Builder.defineMacro("_ARCH_PWR7"); |
| if (defs & ArchDefinePwr8) |
| Builder.defineMacro("_ARCH_PWR8"); |
| if (defs & ArchDefinePwr9) |
| Builder.defineMacro("_ARCH_PWR9"); |
| if (defs & ArchDefineA2) |
| Builder.defineMacro("_ARCH_A2"); |
| if (defs & ArchDefineA2q) { |
| Builder.defineMacro("_ARCH_A2Q"); |
| Builder.defineMacro("_ARCH_QP"); |
| } |
| |
| if (getTriple().getVendor() == llvm::Triple::BGQ) { |
| Builder.defineMacro("__bg__"); |
| Builder.defineMacro("__THW_BLUEGENE__"); |
| Builder.defineMacro("__bgq__"); |
| Builder.defineMacro("__TOS_BGQ__"); |
| } |
| |
| if (HasVSX) |
| Builder.defineMacro("__VSX__"); |
| if (HasP8Vector) |
| Builder.defineMacro("__POWER8_VECTOR__"); |
| if (HasP8Crypto) |
| Builder.defineMacro("__CRYPTO__"); |
| if (HasHTM) |
| Builder.defineMacro("__HTM__"); |
| if (HasFloat128) |
| Builder.defineMacro("__FLOAT128__"); |
| if (HasP9Vector) |
| Builder.defineMacro("__POWER9_VECTOR__"); |
| |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); |
| if (PointerWidth == 64) |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); |
| |
| // FIXME: The following are not yet generated here by Clang, but are |
| // generated by GCC: |
| // |
| // _SOFT_FLOAT_ |
| // __RECIP_PRECISION__ |
| // __APPLE_ALTIVEC__ |
| // __RECIP__ |
| // __RECIPF__ |
| // __RSQRTE__ |
| // __RSQRTEF__ |
| // _SOFT_DOUBLE_ |
| // __NO_LWSYNC__ |
| // __HAVE_BSWAP__ |
| // __LONGDOUBLE128 |
| // __CMODEL_MEDIUM__ |
| // __CMODEL_LARGE__ |
| // _CALL_SYSV |
| // _CALL_DARWIN |
| // __NO_FPRS__ |
| } |
| |
| // Handle explicit options being passed to the compiler here: if we've |
| // explicitly turned off vsx and turned on any of: |
| // - power8-vector |
| // - direct-move |
| // - float128 |
| // - power9-vector |
| // then go ahead and error since the customer has expressed an incompatible |
| // set of options. |
| static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags, |
| const std::vector<std::string> &FeaturesVec) { |
| |
| if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "-vsx") != |
| FeaturesVec.end()) { |
| if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power8-vector") != |
| FeaturesVec.end()) { |
| Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector" |
| << "-mno-vsx"; |
| return false; |
| } |
| |
| if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+direct-move") != |
| FeaturesVec.end()) { |
| Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move" |
| << "-mno-vsx"; |
| return false; |
| } |
| |
| if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") != |
| FeaturesVec.end()) { |
| Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" |
| << "-mno-vsx"; |
| return false; |
| } |
| |
| if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power9-vector") != |
| FeaturesVec.end()) { |
| Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector" |
| << "-mno-vsx"; |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool PPCTargetInfo::initFeatureMap( |
| llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, |
| const std::vector<std::string> &FeaturesVec) const { |
| Features["altivec"] = llvm::StringSwitch<bool>(CPU) |
| .Case("7400", true) |
| .Case("g4", true) |
| .Case("7450", true) |
| .Case("g4+", true) |
| .Case("970", true) |
| .Case("g5", true) |
| .Case("pwr6", true) |
| .Case("pwr7", true) |
| .Case("pwr8", true) |
| .Case("pwr9", true) |
| .Case("ppc64", true) |
| .Case("ppc64le", true) |
| .Default(false); |
| |
| Features["qpx"] = (CPU == "a2q"); |
| Features["power9-vector"] = (CPU == "pwr9"); |
| Features["crypto"] = llvm::StringSwitch<bool>(CPU) |
| .Case("ppc64le", true) |
| .Case("pwr9", true) |
| .Case("pwr8", true) |
| .Default(false); |
| Features["power8-vector"] = llvm::StringSwitch<bool>(CPU) |
| .Case("ppc64le", true) |
| .Case("pwr9", true) |
| .Case("pwr8", true) |
| .Default(false); |
| Features["bpermd"] = llvm::StringSwitch<bool>(CPU) |
| .Case("ppc64le", true) |
| .Case("pwr9", true) |
| .Case("pwr8", true) |
| .Case("pwr7", true) |
| .Default(false); |
| Features["extdiv"] = llvm::StringSwitch<bool>(CPU) |
| .Case("ppc64le", true) |
| .Case("pwr9", true) |
| .Case("pwr8", true) |
| .Case("pwr7", true) |
| .Default(false); |
| Features["direct-move"] = llvm::StringSwitch<bool>(CPU) |
| .Case("ppc64le", true) |
| .Case("pwr9", true) |
| .Case("pwr8", true) |
| .Default(false); |
| Features["vsx"] = llvm::StringSwitch<bool>(CPU) |
| .Case("ppc64le", true) |
| .Case("pwr9", true) |
| .Case("pwr8", true) |
| .Case("pwr7", true) |
| .Default(false); |
| |
| if (!ppcUserFeaturesCheck(Diags, FeaturesVec)) |
| return false; |
| |
| return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); |
| } |
| |
| bool PPCTargetInfo::hasFeature(StringRef Feature) const { |
| return llvm::StringSwitch<bool>(Feature) |
| .Case("powerpc", true) |
| .Case("vsx", HasVSX) |
| .Case("power8-vector", HasP8Vector) |
| .Case("crypto", HasP8Crypto) |
| .Case("direct-move", HasDirectMove) |
| .Case("qpx", HasQPX) |
| .Case("htm", HasHTM) |
| .Case("bpermd", HasBPERMD) |
| .Case("extdiv", HasExtDiv) |
| .Case("float128", HasFloat128) |
| .Case("power9-vector", HasP9Vector) |
| .Default(false); |
| } |
| |
| void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, |
| StringRef Name, bool Enabled) const { |
| // If we're enabling direct-move or power8-vector go ahead and enable vsx |
| // as well. Do the inverse if we're disabling vsx. We'll diagnose any user |
| // incompatible options. |
| if (Enabled) { |
| if (Name == "direct-move" || |
| Name == "power8-vector" || |
| Name == "float128" || |
| Name == "power9-vector") { |
| // power9-vector is really a superset of power8-vector so encode that. |
| Features[Name] = Features["vsx"] = true; |
| if (Name == "power9-vector") |
| Features["power8-vector"] = true; |
| } else { |
| Features[Name] = true; |
| } |
| } else { |
| if (Name == "vsx") { |
| Features[Name] = Features["direct-move"] = Features["power8-vector"] = |
| Features["float128"] = Features["power9-vector"] = false; |
| } else { |
| Features[Name] = false; |
| } |
| } |
| } |
| |
| const char * const PPCTargetInfo::GCCRegNames[] = { |
| "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
| "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
| "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
| "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", |
| "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
| "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
| "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", |
| "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", |
| "mq", "lr", "ctr", "ap", |
| "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", |
| "xer", |
| "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", |
| "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", |
| "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", |
| "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", |
| "vrsave", "vscr", |
| "spe_acc", "spefscr", |
| "sfp" |
| }; |
| |
| ArrayRef<const char*> PPCTargetInfo::getGCCRegNames() const { |
| return llvm::makeArrayRef(GCCRegNames); |
| } |
| |
| const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = { |
| // While some of these aliases do map to different registers |
| // they still share the same register name. |
| { { "0" }, "r0" }, |
| { { "1"}, "r1" }, |
| { { "2" }, "r2" }, |
| { { "3" }, "r3" }, |
| { { "4" }, "r4" }, |
| { { "5" }, "r5" }, |
| { { "6" }, "r6" }, |
| { { "7" }, "r7" }, |
| { { "8" }, "r8" }, |
| { { "9" }, "r9" }, |
| { { "10" }, "r10" }, |
| { { "11" }, "r11" }, |
| { { "12" }, "r12" }, |
| { { "13" }, "r13" }, |
| { { "14" }, "r14" }, |
| { { "15" }, "r15" }, |
| { { "16" }, "r16" }, |
| { { "17" }, "r17" }, |
| { { "18" }, "r18" }, |
| { { "19" }, "r19" }, |
| { { "20" }, "r20" }, |
| { { "21" }, "r21" }, |
| { { "22" }, "r22" }, |
| { { "23" }, "r23" }, |
| { { "24" }, "r24" }, |
| { { "25" }, "r25" }, |
| { { "26" }, "r26" }, |
| { { "27" }, "r27" }, |
| { { "28" }, "r28" }, |
| { { "29" }, "r29" }, |
| { { "30" }, "r30" }, |
| { { "31" }, "r31" }, |
| { { "fr0" }, "f0" }, |
| { { "fr1" }, "f1" }, |
| { { "fr2" }, "f2" }, |
| { { "fr3" }, "f3" }, |
| { { "fr4" }, "f4" }, |
| { { "fr5" }, "f5" }, |
| { { "fr6" }, "f6" }, |
| { { "fr7" }, "f7" }, |
| { { "fr8" }, "f8" }, |
| { { "fr9" }, "f9" }, |
| { { "fr10" }, "f10" }, |
| { { "fr11" }, "f11" }, |
| { { "fr12" }, "f12" }, |
| { { "fr13" }, "f13" }, |
| { { "fr14" }, "f14" }, |
| { { "fr15" }, "f15" }, |
| { { "fr16" }, "f16" }, |
| { { "fr17" }, "f17" }, |
| { { "fr18" }, "f18" }, |
| { { "fr19" }, "f19" }, |
| { { "fr20" }, "f20" }, |
| { { "fr21" }, "f21" }, |
| { { "fr22" }, "f22" }, |
| { { "fr23" }, "f23" }, |
| { { "fr24" }, "f24" }, |
| { { "fr25" }, "f25" }, |
| { { "fr26" }, "f26" }, |
| { { "fr27" }, "f27" }, |
| { { "fr28" }, "f28" }, |
| { { "fr29" }, "f29" }, |
| { { "fr30" }, "f30" }, |
| { { "fr31" }, "f31" }, |
| { { "cc" }, "cr0" }, |
| }; |
| |
| ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const { |
| return llvm::makeArrayRef(GCCRegAliases); |
| } |
| |
| class PPC32TargetInfo : public PPCTargetInfo { |
| public: |
| PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : PPCTargetInfo(Triple, Opts) { |
| resetDataLayout("E-m:e-p:32:32-i64:64-n32"); |
| |
| switch (getTriple().getOS()) { |
| case llvm::Triple::Linux: |
| case llvm::Triple::FreeBSD: |
| case llvm::Triple::NetBSD: |
| SizeType = UnsignedInt; |
| PtrDiffType = SignedInt; |
| IntPtrType = SignedInt; |
| break; |
| default: |
| break; |
| } |
| |
| if (getTriple().getOS() == llvm::Triple::FreeBSD) { |
| LongDoubleWidth = LongDoubleAlign = 64; |
| LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
| } |
| |
| // PPC32 supports atomics up to 4 bytes. |
| MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; |
| } |
| |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| // This is the ELF definition, and is overridden by the Darwin sub-target |
| return TargetInfo::PowerABIBuiltinVaList; |
| } |
| }; |
| |
| // Note: ABI differences may eventually require us to have a separate |
| // TargetInfo for little endian. |
| class PPC64TargetInfo : public PPCTargetInfo { |
| public: |
| PPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : PPCTargetInfo(Triple, Opts) { |
| LongWidth = LongAlign = PointerWidth = PointerAlign = 64; |
| IntMaxType = SignedLong; |
| Int64Type = SignedLong; |
| |
| if ((Triple.getArch() == llvm::Triple::ppc64le)) { |
| resetDataLayout("e-m:e-i64:64-n32:64"); |
| ABI = "elfv2"; |
| } else { |
| resetDataLayout("E-m:e-i64:64-n32:64"); |
| ABI = "elfv1"; |
| } |
| |
| switch (getTriple().getOS()) { |
| case llvm::Triple::FreeBSD: |
| LongDoubleWidth = LongDoubleAlign = 64; |
| LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
| break; |
| case llvm::Triple::NetBSD: |
| IntMaxType = SignedLongLong; |
| Int64Type = SignedLongLong; |
| break; |
| default: |
| break; |
| } |
| |
| // PPC64 supports atomics up to 8 bytes. |
| MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; |
| } |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| return TargetInfo::CharPtrBuiltinVaList; |
| } |
| // PPC64 Linux-specific ABI options. |
| bool setABI(const std::string &Name) override { |
| if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") { |
| ABI = Name; |
| return true; |
| } |
| return false; |
| } |
| }; |
| |
| class DarwinPPC32TargetInfo : public DarwinTargetInfo<PPC32TargetInfo> { |
| public: |
| DarwinPPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : DarwinTargetInfo<PPC32TargetInfo>(Triple, Opts) { |
| HasAlignMac68kSupport = true; |
| BoolWidth = BoolAlign = 32; //XXX support -mone-byte-bool? |
| PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726 |
| LongLongAlign = 32; |
| SuitableAlign = 128; |
| resetDataLayout("E-m:o-p:32:32-f64:32:64-n32"); |
| } |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| return TargetInfo::CharPtrBuiltinVaList; |
| } |
| }; |
| |
| class DarwinPPC64TargetInfo : public DarwinTargetInfo<PPC64TargetInfo> { |
| public: |
| DarwinPPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : DarwinTargetInfo<PPC64TargetInfo>(Triple, Opts) { |
| HasAlignMac68kSupport = true; |
| SuitableAlign = 128; |
| resetDataLayout("E-m:o-i64:64-n32:64"); |
| } |
| }; |
| |
| static const unsigned NVPTXAddrSpaceMap[] = { |
| 1, // opencl_global |
| 3, // opencl_local |
| 4, // opencl_constant |
| // FIXME: generic has to be added to the target |
| 0, // opencl_generic |
| 1, // cuda_device |
| 4, // cuda_constant |
| 3, // cuda_shared |
| }; |
| |
| class NVPTXTargetInfo : public TargetInfo { |
| static const char *const GCCRegNames[]; |
| static const Builtin::Info BuiltinInfo[]; |
| CudaArch GPU; |
| std::unique_ptr<TargetInfo> HostTarget; |
| |
| public: |
| NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts, |
| unsigned TargetPointerWidth) |
| : TargetInfo(Triple) { |
| assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) && |
| "NVPTX only supports 32- and 64-bit modes."); |
| |
| TLSSupported = false; |
| AddrSpaceMap = &NVPTXAddrSpaceMap; |
| UseAddrSpaceMapMangling = true; |
| |
| // Define available target features |
| // These must be defined in sorted order! |
| NoAsmVariants = true; |
| GPU = CudaArch::SM_20; |
| |
| if (TargetPointerWidth == 32) |
| resetDataLayout("e-p:32:32-i64:64-v16:16-v32:32-n16:32:64"); |
| else |
| resetDataLayout("e-i64:64-v16:16-v32:32-n16:32:64"); |
| |
| // If possible, get a TargetInfo for our host triple, so we can match its |
| // types. |
| llvm::Triple HostTriple(Opts.HostTriple); |
| if (!HostTriple.isNVPTX()) |
| HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts)); |
| |
| // If no host target, make some guesses about the data layout and return. |
| if (!HostTarget) { |
| LongWidth = LongAlign = TargetPointerWidth; |
| PointerWidth = PointerAlign = TargetPointerWidth; |
| switch (TargetPointerWidth) { |
| case 32: |
| SizeType = TargetInfo::UnsignedInt; |
| PtrDiffType = TargetInfo::SignedInt; |
| IntPtrType = TargetInfo::SignedInt; |
| break; |
| case 64: |
| SizeType = TargetInfo::UnsignedLong; |
| PtrDiffType = TargetInfo::SignedLong; |
| IntPtrType = TargetInfo::SignedLong; |
| break; |
| default: |
| llvm_unreachable("TargetPointerWidth must be 32 or 64"); |
| } |
| return; |
| } |
| |
| // Copy properties from host target. |
| PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0); |
| PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0); |
| BoolWidth = HostTarget->getBoolWidth(); |
| BoolAlign = HostTarget->getBoolAlign(); |
| IntWidth = HostTarget->getIntWidth(); |
| IntAlign = HostTarget->getIntAlign(); |
| HalfWidth = HostTarget->getHalfWidth(); |
| HalfAlign = HostTarget->getHalfAlign(); |
| FloatWidth = HostTarget->getFloatWidth(); |
| FloatAlign = HostTarget->getFloatAlign(); |
| DoubleWidth = HostTarget->getDoubleWidth(); |
| DoubleAlign = HostTarget->getDoubleAlign(); |
| LongWidth = HostTarget->getLongWidth(); |
| LongAlign = HostTarget->getLongAlign(); |
| LongLongWidth = HostTarget->getLongLongWidth(); |
| LongLongAlign = HostTarget->getLongLongAlign(); |
| MinGlobalAlign = HostTarget->getMinGlobalAlign(); |
| NewAlign = HostTarget->getNewAlign(); |
| DefaultAlignForAttributeAligned = |
| HostTarget->getDefaultAlignForAttributeAligned(); |
| SizeType = HostTarget->getSizeType(); |
| IntMaxType = HostTarget->getIntMaxType(); |
| PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0); |
| IntPtrType = HostTarget->getIntPtrType(); |
| WCharType = HostTarget->getWCharType(); |
| WIntType = HostTarget->getWIntType(); |
| Char16Type = HostTarget->getChar16Type(); |
| Char32Type = HostTarget->getChar32Type(); |
| Int64Type = HostTarget->getInt64Type(); |
| SigAtomicType = HostTarget->getSigAtomicType(); |
| ProcessIDType = HostTarget->getProcessIDType(); |
| |
| UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment(); |
| UseZeroLengthBitfieldAlignment = |
| HostTarget->useZeroLengthBitfieldAlignment(); |
| UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment(); |
| ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary(); |
| |
| // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and |
| // we need those macros to be identical on host and device, because (among |
| // other things) they affect which standard library classes are defined, and |
| // we need all classes to be defined on both the host and device. |
| MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth(); |
| |
| // Properties intentionally not copied from host: |
| // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the |
| // host/device boundary. |
| // - SuitableAlign: Not visible across the host/device boundary, and may |
| // correctly be different on host/device, e.g. if host has wider vector |
| // types than device. |
| // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same |
| // as its double type, but that's not necessarily true on the host. |
| // TODO: nvcc emits a warning when using long double on device; we should |
| // do the same. |
| } |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override { |
| Builder.defineMacro("__PTX__"); |
| Builder.defineMacro("__NVPTX__"); |
| if (Opts.CUDAIsDevice) { |
| // Set __CUDA_ARCH__ for the GPU specified. |
| std::string CUDAArchCode = [this] { |
| switch (GPU) { |
| case CudaArch::UNKNOWN: |
| assert(false && "No GPU arch when compiling CUDA device code."); |
| return ""; |
| case CudaArch::SM_20: |
| return "200"; |
| case CudaArch::SM_21: |
| return "210"; |
| case CudaArch::SM_30: |
| return "300"; |
| case CudaArch::SM_32: |
| return "320"; |
| case CudaArch::SM_35: |
| return "350"; |
| case CudaArch::SM_37: |
| return "370"; |
| case CudaArch::SM_50: |
| return "500"; |
| case CudaArch::SM_52: |
| return "520"; |
| case CudaArch::SM_53: |
| return "530"; |
| case CudaArch::SM_60: |
| return "600"; |
| case CudaArch::SM_61: |
| return "610"; |
| case CudaArch::SM_62: |
| return "620"; |
| } |
| llvm_unreachable("unhandled CudaArch"); |
| }(); |
| Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode); |
| } |
| } |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override { |
| return llvm::makeArrayRef(BuiltinInfo, |
| clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin); |
| } |
| bool |
| initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, |
| StringRef CPU, |
| const std::vector<std::string> &FeaturesVec) const override { |
| Features["satom"] = GPU >= CudaArch::SM_60; |
| return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); |
| } |
| |
| bool hasFeature(StringRef Feature) const override { |
| return llvm::StringSwitch<bool>(Feature) |
| .Cases("ptx", "nvptx", true) |
| .Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope. |
| .Default(false); |
| } |
| |
| ArrayRef<const char *> getGCCRegNames() const override; |
| ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
| // No aliases. |
| return None; |
| } |
| bool validateAsmConstraint(const char *&Name, |
| TargetInfo::ConstraintInfo &Info) const override { |
| switch (*Name) { |
| default: |
| return false; |
| case 'c': |
| case 'h': |
| case 'r': |
| case 'l': |
| case 'f': |
| case 'd': |
| Info.setAllowsRegister(); |
| return true; |
| } |
| } |
| const char *getClobbers() const override { |
| // FIXME: Is this really right? |
| return ""; |
| } |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| // FIXME: implement |
| return TargetInfo::CharPtrBuiltinVaList; |
| } |
| bool setCPU(const std::string &Name) override { |
| GPU = StringToCudaArch(Name); |
| return GPU != CudaArch::UNKNOWN; |
| } |
| void setSupportedOpenCLOpts() override { |
| auto &Opts = getSupportedOpenCLOpts(); |
| Opts.support("cl_clang_storage_class_specifiers"); |
| Opts.support("cl_khr_gl_sharing"); |
| Opts.support("cl_khr_icd"); |
| |
| Opts.support("cl_khr_fp64"); |
| Opts.support("cl_khr_byte_addressable_store"); |
| Opts.support("cl_khr_global_int32_base_atomics"); |
| Opts.support("cl_khr_global_int32_extended_atomics"); |
| Opts.support("cl_khr_local_int32_base_atomics"); |
| Opts.support("cl_khr_local_int32_extended_atomics"); |
| } |
| |
| CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { |
| // CUDA compilations support all of the host's calling conventions. |
| // |
| // TODO: We should warn if you apply a non-default CC to anything other than |
| // a host function. |
| if (HostTarget) |
| return HostTarget->checkCallingConvention(CC); |
| return CCCR_Warning; |
| } |
| }; |
| |
| const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = { |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, |
| #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ |
| { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr }, |
| #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE }, |
| #include "clang/Basic/BuiltinsNVPTX.def" |
| }; |
| |
| const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"}; |
| |
| ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const { |
| return llvm::makeArrayRef(GCCRegNames); |
| } |
| |
| static const unsigned AMDGPUAddrSpaceMap[] = { |
| 1, // opencl_global |
| 3, // opencl_local |
| 2, // opencl_constant |
| 4, // opencl_generic |
| 1, // cuda_device |
| 2, // cuda_constant |
| 3 // cuda_shared |
| }; |
| |
| // If you edit the description strings, make sure you update |
| // getPointerWidthV(). |
| |
| static const char *const DataLayoutStringR600 = |
| "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" |
| "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"; |
| |
| static const char *const DataLayoutStringSI = |
| "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32" |
| "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" |
| "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"; |
| |
| class AMDGPUTargetInfo final : public TargetInfo { |
| static const Builtin::Info BuiltinInfo[]; |
| static const char * const GCCRegNames[]; |
| |
| /// \brief The GPU profiles supported by the AMDGPU target. |
| enum GPUKind { |
| GK_NONE, |
| GK_R600, |
| GK_R600_DOUBLE_OPS, |
| GK_R700, |
| GK_R700_DOUBLE_OPS, |
| GK_EVERGREEN, |
| GK_EVERGREEN_DOUBLE_OPS, |
| GK_NORTHERN_ISLANDS, |
| GK_CAYMAN, |
| GK_GFX6, |
| GK_GFX7, |
| GK_GFX8 |
| } GPU; |
| |
| bool hasFP64:1; |
| bool hasFMAF:1; |
| bool hasLDEXPF:1; |
| bool hasFullSpeedFP32Denorms:1; |
| |
| static bool isAMDGCN(const llvm::Triple &TT) { |
| return TT.getArch() == llvm::Triple::amdgcn; |
| } |
| |
| public: |
| AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
| : TargetInfo(Triple) , |
| GPU(isAMDGCN(Triple) ? GK_GFX6 : GK_R600), |
| hasFP64(false), |
| hasFMAF(false), |
| hasLDEXPF(false), |
| hasFullSpeedFP32Denorms(false){ |
| if (getTriple().getArch() == llvm::Triple::amdgcn) { |
| hasFP64 = true; |
| hasFMAF = true; |
| hasLDEXPF = true; |
| } |
| |
| resetDataLayout(getTriple().getArch() == llvm::Triple::amdgcn ? |
| DataLayoutStringSI : DataLayoutStringR600); |
| |
| AddrSpaceMap = &AMDGPUAddrSpaceMap; |
| UseAddrSpaceMapMangling = true; |
| } |
| |
| uint64_t getPointerWidthV(unsigned AddrSpace) const override { |
| if (GPU <= GK_CAYMAN) |
| return 32; |
| |
| switch(AddrSpace) { |
| default: |
| return 64; |
| case 0: |
| case 3: |
| case 5: |
| return 32; |
| } |
| } |
| |
| uint64_t getMaxPointerWidth() const override { |
| return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; |
| } |
| |
| const char * getClobbers() const override { |
| return ""; |
| } |
| |
| ArrayRef<const char *> getGCCRegNames() const override; |
| |
| ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
| return None; |
| } |
| |
| bool validateAsmConstraint(const char *&Name, |
| TargetInfo::ConstraintInfo &Info) const override { |
| switch (*Name) { |
| default: break; |
| case 'v': // vgpr |
| case 's': // sgpr |
| Info.setAllowsRegister(); |
| return true; |
| } |
| return false; |
| } |
| |
| bool initFeatureMap(llvm::StringMap<bool> &Features, |
| DiagnosticsEngine &Diags, StringRef CPU, |
| const std::vector<std::string> &FeatureVec) const override; |
| |
| void adjustTargetOptions(const CodeGenOptions &CGOpts, |
| TargetOptions &TargetOpts) const override { |
| bool hasFP32Denormals = false; |
| bool hasFP64Denormals = false; |
| for (auto &I : TargetOpts.FeaturesAsWritten) { |
| if (I == "+fp32-denormals" || I == "-fp32-denormals") |
| hasFP32Denormals = true; |
| if (I == "+fp64-denormals" || I == "-fp64-denormals") |
| hasFP64Denormals = true; |
| } |
| if (!hasFP32Denormals) |
| TargetOpts.Features.push_back((Twine(hasFullSpeedFP32Denorms && |
| !CGOpts.FlushDenorm ? '+' : '-') + Twine("fp32-denormals")).str()); |
| // Always do not flush fp64 denorms. |
| if (!hasFP64Denormals && hasFP64) |
| TargetOpts.Features.push_back("+fp64-denormals"); |
| } |
| |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override { |
| return llvm::makeArrayRef(BuiltinInfo, |
| clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin); |
| } |
| |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override { |
| if (getTriple().getArch() == llvm::Triple::amdgcn) |
| Builder.defineMacro("__AMDGCN__"); |
| else |
| Builder.defineMacro("__R600__"); |
| |
| if (hasFMAF) |
| Builder.defineMacro("__HAS_FMAF__"); |
| if (hasLDEXPF) |
| Builder.defineMacro("__HAS_LDEXPF__"); |
| if (hasFP64) |
| Builder.defineMacro("__HAS_FP64__"); |
| } |
| |
| BuiltinVaListKind getBuiltinVaListKind() const override { |
| return TargetInfo::CharPtrBuiltinVaList; |
| } |
| |
| static GPUKind parseR600Name(StringRef Name) { |
| return llvm::StringSwitch<GPUKind>(Name) |
| .Case("r600" , GK_R600) |
| .Case("rv610", GK_R600) |
| .Case("rv620", GK_R600) |
| .Case("rv630", GK_R600) |
| .Case("rv635", GK_R600) |
| .Case("rs780", GK_R600) |
| .Case("rs880", GK_R600) |
| .Case("rv670", GK_R600_DOUBLE_OPS) |
| .Case("rv710", GK_R700) |
| .Case("rv730", GK_R700) |
| .Case("rv740", GK_R700_DOUBLE_OPS) |
| .Case("rv770", GK_R700_DOUBLE_OPS) |
| .Case("palm", GK_EVERGREEN) |
| .Case("cedar", GK_EVERGREEN) |
| .Case("sumo", GK_EVERGREEN) |
| .Case("sumo2", GK_EVERGREEN) |
| .Case("redwood", GK_EVERGREEN) |
| .Case("juniper", GK_EVERGREEN) |
| .Case("hemlock", GK_EVERGREEN_DOUBLE_OPS) |
| .Case("cypress", GK_EVERGREEN_DOUBLE_OPS) |
| .Case("barts", GK_NORTHERN_ISLANDS) |
| .Case("turks", GK_NORTHERN_ISLANDS) |
| .Case("caicos", GK_NORTHERN_ISLANDS) |
| .Case("cayman", GK_CAYMAN) |
| .Case("aruba", GK_CAYMAN) |
| .Default(GK_NONE); |
| } |
| |
| static GPUKind parseAMDGCNName(StringRef Name) { |
| return llvm::StringSwitch<GPUKind>(Name) |
| .Case("tahiti", GK_GFX6) |
| .Case("pitcairn", GK_GFX6) |
| .Case("verde", GK_GFX6) |
| .Case("oland", GK_GFX6) |
| .Case("hainan", GK_GFX6) |
| .Case("bonaire", GK_GFX7) |
| .Case("kabini", GK_GFX7) |
| .Case("kaveri", GK_GFX7) |
| .Case("hawaii", GK_GFX7) |
| .Case("mullins", GK_GFX7) |
| .Case("gfx700", GK_GFX7) |
| .Case("gfx701", GK_GFX7) |
| .Case("gfx702", GK_GFX7) |
| .Case("tonga", GK_GFX8) |
| .Case("iceland", GK_GFX8) |
| .Case("carrizo", GK_GFX8) |
| .Case("fiji", GK_GFX8) |
| .Case("stoney", GK_GFX8) |
| .Case("polaris10", GK_GFX8) |
| .Case("polaris11", GK_GFX8) |
| .Case("gfx800", GK_GFX8) |
| .Case("gfx801", GK_GFX8) |
| .Case("gfx802", GK_GFX8) |
| .Case("gfx803", GK_GFX8) |
| .Case("gfx804", GK_GFX8) |
| .Case("gfx810", GK_GFX8) |
| .Default(GK_NONE); |
| } |
| |
| bool setCPU(const std::string &Name) override { |
| if (getTriple().getArch() == llvm::Triple::amdgcn) |
| GPU = parseAMDGCNName(Name); |
| else |
| GPU = parseR600Name(Name); |
| |
| return GPU != GK_NONE; |
| } |
| |
| void setSupportedOpenCLOpts() override { |
| auto &Opts = getSupportedOpenCLOpts(); |
| Opts.support("cl_clang_storage_class_specifiers"); |
| Opts.support("cl_khr_icd"); |
| |
| if (hasFP64) |
| Opts.support("cl_khr_fp64"); |
| if (GPU >= GK_EVERGREEN) { |
| Opts.support("cl_khr_byte_addressable_store"); |
| Opts.support("cl_khr_global_int32_base_atomics"); |
| Opts.support("cl_khr_global_int32_extended_atomics"); |
| Opts.support("cl_khr_local_int32_base_atomics"); |
| Opts.support("cl_khr_local_int32_extended_atomics"); |
| } |
| if (GPU >= GK_GFX6) { |
| Opts.support("cl_khr_fp16"); |
| Opts.support("cl_khr_int64_base_atomics"); |
| Opts.support("cl_khr_int64_extended_atomics"); |
| Opts.support("cl_khr_mipmap_image"); |
| Opts.support("cl_khr_subgroups"); |
| Opts.support("cl_khr_3d_image_writes"); |
| Opts.support("cl_amd_media_ops"); |
| Opts.support("cl_amd_media_ops2"); |
| } |
| } |
| |
| LangAS::ID getOpenCLImageAddrSpace() const override { |
| return LangAS::opencl_constant; |
| } |
| |
| CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { |
| switch (CC) { |
| default: |
| return CCCR_Warning; |
| case CC_C: |
| case CC_OpenCLKernel: |
| return CCCR_OK; |
| } |
| } |
| |
| // In amdgcn target the null pointer in global, constant, and generic |
| // address space has value 0 but in private and local address space has |
| // value ~0. |
| uint64_t getNullPointerValue(unsigned AS) const override { |
| return AS != LangAS::opencl_local && AS != 0 ? 0 : ~0; |
| } |
| }; |
| |
| const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = { |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, |
| #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE }, |
| #include "clang/Basic/BuiltinsAMDGPU.def" |
| }; |
| const char * const AMDGPUTargetInfo::GCCRegNames[] = { |
| "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", |
| "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", |
| "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", |
| "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", |
| "v32", "v33", "v34", "v35", "v36", "v37", "v38", "v39", |
| "v40", "v41", "v42", "v43", "v44", "v45", "v46", "v47", |
| "v48", "v49", "v50", "v51", "v52", "v53", "v54", "v55", |
| "v56", "v57", "v58", "v59", "v60", "v61", "v62", "v63", |
| "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71", |
| "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79", |
| "v80", "v81", "v82", "v83", "v84", "v85", "v86", "v87", |
| "v88", "v89", "v90", "v91", "v92", "v93", "v94", "v95", |
| "v96", "v97", "v98", "v99", "v100", "v101", "v102", "v103", |
| "v104", "v105", "v106", "v107", "v108", "v109", "v110", "v111", |
| "v112", "v113", "v114", "v115", "v116", "v117", "v118", "v119", |
| "v120", "v121", "v122", "v123", "v124", "v125", "v126", "v127", |
| "v128", "v129", "v130", "v131", "v132", "v133", "v134", "v135", |
| "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143", |
| "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151", |
| "v152", "v153", "v154", "v155", "v156", "v157", "v158", "v159", |
| "v160", "v161", "v162", "v163", "v164", "v165", "v166", "v167", |
| "v168", "v169", "v170", "v171", "v172", "v173", "v174", "v175", |
| "v176", "v177", "v178", "v179", "v180", "v181", "v182", "v183", |
| "v184", "v185", "v186", "v187", "v188", "v189", "v190", "v191", |
| "v192", "v193", "v194", "v195", "v196", "v197", "v198", "v199", |
| "v200", "v201", "v202", "v203", "v204", "v205", "v206", "v207", |
| "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215", |
| "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223", |
| "v224", "v225", "v226", "v227", "v228", "v229", "v230", "v231", |
| "v232", "v233", "v234", "v235", "v236", "v237", "v238", "v239", |
| "v240", "v241", "v242", "v243", "v244", "v245", "v246", "v247", |
| "v248", "v249", "v250", "v251", "v252", "v253", "v254", "v255", |
| "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
| "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", |
| "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", |
| "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", |
| "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", |
| "s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47", |
| "s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55", |
| "s56", "s57", "s58", "s59", "s60", "s61", "s62", "s63", |
| "s64", "s65", "s66", "s67", "s68", "s69", "s70", "s71", |
| "s72", "s73", "s74", "s75", "s76", "s77", "s78", "s79", |
| "s80", "s81", "s82", "s83", "s84", "s85", "s86", "s87", |
| "s88", "s89", "s90", "s91", "s92", "s93", "s94", "s95", |
| "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103", |
| "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", |
| "s112", "s113", "s114", "s115", "s116", "s117", "s118", "s119", |
| "s120", "s121", "s122", "s123", "s124", "s125", "s126", "s127", |
| "exec", "vcc", "scc", "m0", "flat_scratch", "exec_lo", "exec_hi", |
| "vcc_lo", "vcc_hi", "flat_scratch_lo", "flat_scratch_hi" |
| }; |
| |
| ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const { |
| return llvm::makeArrayRef(GCCRegNames); |
| } |
| |
| bool AMDGPUTargetInfo::initFeatureMap( |
| llvm::StringMap<bool> &Features, |
| DiagnosticsEngine &Diags, StringRef CPU, |
| const std::vector<std::string> &FeatureVec) const { |
| |
| // XXX - What does the member GPU mean if device name string passed here? |
| if (getTriple().getArch() == llvm::Triple::amdgcn) { |
| if (CPU.empty()) |
| CPU = "tahiti"; |
| |
| switch (parseAMDGCNName(CPU)) { |
| case GK_GFX6: |
| case GK_GFX7: |
| break; |
| |
| case GK_GFX8: |
| Features["s-memrealtime"] = true; |
| Features["16-bit-insts"] = true; |
| break; |
| |
| case GK_NONE: |
| return false; |
| default: |
| llvm_unreachable("unhandled subtarget"); |
| } |
| } else { |
| if (CPU.empty()) |
| CPU = "r600"; |
| |
| switch (parseR600Name(CPU)) { |
| case GK_R600: |
| case GK_R700: |
| case GK_EVERGREEN: |
| case GK_NORTHERN_ISLANDS: |
| break; |
| case GK_R600_DOUBLE_OPS: |
| case GK_R700_DOUBLE_OPS: |
| case GK_EVERGREEN_DOUBLE_OPS: |
| case GK_CAYMAN: |
| Features["fp64"] = true; |
| break; |
| case GK_NONE: |
| return false; |
| default: |
| llvm_unreachable("unhandled subtarget"); |
| } |
| } |
| |
| return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec); |
| } |
| |
| const Builtin::Info BuiltinInfoX86[] = { |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, |
| #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE }, |
| #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ |
| { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE }, |
| #include "clang/Basic/BuiltinsX86.def" |
| |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, |
| #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ |
| { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE }, |
| #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ |
| { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE }, |
| #include "clang/Basic/BuiltinsX86_64.def" |
| }; |
| |
| |
| static const char* const GCCRegNames[] = { |
| "ax", "dx", "cx", "bx", "si", "di", "bp", "sp", |
| "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", |
| "argp", "flags", "fpcr", "fpsr", "dirflag", "frame", |
| "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", |
| "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", |
| "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
| "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", |
| "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", |
| "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", |
| "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", |
| "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31", |
| "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", |
| "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31", |
| "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", |
| "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", |
| "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", |
| "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", |
| "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", |
| }; |
| |
| const TargetInfo::AddlRegName AddlRegNames[] = { |
| { { "al", "ah", "eax", "rax" }, 0 }, |
| { { "bl", "bh", "ebx", "rbx" }, 3 }, |
| { { "cl", "ch", "ecx", "rcx" }, 2 }, |
| { { "dl", "dh", "edx", "rdx" }, 1 }, |
| { { "esi", "rsi" }, 4 }, |
| { { "edi", "rdi" }, 5 }, |
| { { "esp", "rsp" }, 7 }, |
| { { "ebp", "rbp" }, 6 }, |
| { { "r8d", "r8w", "r8b" }, 38 }, |
| { { "r9d", "r9w", "r9b" }, 39 }, |
| { { "r10d", "r10w", "r10b" }, 40 }, |
| { { "r11d", "r11w", "r11b" }, 41 }, |
| { { "r12d", "r12w", "r12b" }, 42 }, |
| { { "r13d", "r13w", "r13b" }, 43 }, |
| { { "r14d", "r14w", "r14b" }, 44 }, |
| { { "r15d", "r15w", "r15b" }, 45 }, |
| }; |
| |
| // X86 target abstract base class; x86-32 and x86-64 are very close, so |
| // most of the implementation can be shared. |
| class X86TargetInfo : public TargetInfo { |
| enum X86SSEEnum { |
| NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F |
| } SSELevel = NoSSE; |
| enum MMX3DNowEnum { |
| NoMMX3DNow, MMX, AMD3DNow, AMD3DNowAthlon |
| } MMX3DNowLevel = NoMMX3DNow; |
| enum XOPEnum { |
| NoXOP, |
| SSE4A, |
| FMA4, |
| XOP |
| } XOPLevel = NoXOP; |
| |
| bool HasAES = false; |
| bool HasPCLMUL = false; |
| bool HasLZCNT = false; |
| bool HasRDRND = false; |
| bool HasFSGSBASE = false; |
| bool HasBMI = false; |
| bool HasBMI2 = false; |
| bool HasPOPCNT = false; |
| bool HasRTM = false; |
| bool HasPRFCHW = false; |
| bool HasRDSEED = false; |
| bool HasADX = false; |
| bool HasTBM = false; |
| bool HasFMA = false; |
| bool HasF16C = false; |
| bool HasAVX512CD = false; |
| bool HasAVX512ER = false; |
| bool HasAVX512PF = false; |
| bool HasAVX512DQ = false; |
| bool HasAVX512BW = false; |
| bool HasAVX512VL = false; |
| bool HasAVX512VBMI = false; |
| bool HasAVX512IFMA = false; |
| bool HasSHA = false; |
| bool HasMPX = false; |
| bool HasSGX = false; |
| bool HasCX16 = false; |
| bool HasFXSR = false; |
| bool HasXSAVE = false; |
| bool HasXSAVEOPT = false; |
| bool HasXSAVEC = false; |
| bool HasXSAVES = false; |
| bool HasMWAITX = false; |
| bool HasPKU = false; |
| bool HasCLFLUSHOPT = false; |
| bool HasPCOMMIT = false; |
| bool HasCLWB = false; |
| bool HasUMIP = false; |
| bool HasMOVBE = false; |
| bool HasPREFETCHWT1 = false; |
| |
| /// \brief Enumeration of all of the X86 CPUs supported by Clang. |
| /// |
| /// Each enumeration represents a particular CPU supported by Clang. These |
| /// loosely correspond to the options passed to '-march' or '-mtune' flags. |
| enum CPUKind { |
| CK_Generic, |
| |
| /// \name i386 |
| |