diff options
Diffstat (limited to 'clang/lib/Basic/Targets/X86.h')
-rw-r--r-- | clang/lib/Basic/Targets/X86.h | 1150 |
1 files changed, 1150 insertions, 0 deletions
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h new file mode 100644 index 00000000000..2a5661eccaa --- /dev/null +++ b/clang/lib/Basic/Targets/X86.h @@ -0,0 +1,1150 @@ +//===--- X86.h - Declare X86 target feature support -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares X86 TargetInfo objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_X86_H +#define LLVM_CLANG_LIB_BASIC_TARGETS_X86_H + +#include "OSTargets.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Compiler.h" + +namespace clang { +namespace targets { + +// X86 target abstract base class; x86-32 and x86-64 are very close, so +// most of the implementation can be shared. +class LLVM_LIBRARY_VISIBILITY 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 HasLWP = false; + bool HasFMA = false; + bool HasF16C = false; + bool HasAVX512CD = false; + bool HasAVX512VPOPCNTDQ = 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 HasCLZERO = false; + bool HasPKU = false; + bool HasCLFLUSHOPT = false; + bool HasCLWB = 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 + /// i386-generation processors. + //@{ + CK_i386, + //@} + + /// \name i486 + /// i486-generation processors. + //@{ + CK_i486, + CK_WinChipC6, + CK_WinChip2, + CK_C3, + //@} + + /// \name i586 + /// i586-generation processors, P5 microarchitecture based. + //@{ + CK_i586, + CK_Pentium, + CK_PentiumMMX, + //@} + + /// \name i686 + /// i686-generation processors, P6 / Pentium M microarchitecture based. + //@{ + CK_i686, + CK_PentiumPro, + CK_Pentium2, + CK_Pentium3, + CK_Pentium3M, + CK_PentiumM, + CK_C3_2, + + /// This enumerator is a bit odd, as GCC no longer accepts -march=yonah. + /// Clang however has some logic to support this. + // FIXME: Warn, deprecate, and potentially remove this. + CK_Yonah, + //@} + + /// \name Netburst + /// Netburst microarchitecture based processors. + //@{ + CK_Pentium4, + CK_Pentium4M, + CK_Prescott, + CK_Nocona, + //@} + + /// \name Core + /// Core microarchitecture based processors. + //@{ + CK_Core2, + + /// This enumerator, like \see CK_Yonah, is a bit odd. It is another + /// codename which GCC no longer accepts as an option to -march, but Clang + /// has some logic for recognizing it. + // FIXME: Warn, deprecate, and potentially remove this. + CK_Penryn, + //@} + + /// \name Atom + /// Atom processors + //@{ + CK_Bonnell, + CK_Silvermont, + CK_Goldmont, + //@} + + /// \name Nehalem + /// Nehalem microarchitecture based processors. + CK_Nehalem, + + /// \name Westmere + /// Westmere microarchitecture based processors. + CK_Westmere, + + /// \name Sandy Bridge + /// Sandy Bridge microarchitecture based processors. + CK_SandyBridge, + + /// \name Ivy Bridge + /// Ivy Bridge microarchitecture based processors. + CK_IvyBridge, + + /// \name Haswell + /// Haswell microarchitecture based processors. + CK_Haswell, + + /// \name Broadwell + /// Broadwell microarchitecture based processors. + CK_Broadwell, + + /// \name Skylake Client + /// Skylake client microarchitecture based processors. + CK_SkylakeClient, + + /// \name Skylake Server + /// Skylake server microarchitecture based processors. + CK_SkylakeServer, + + /// \name Cannonlake Client + /// Cannonlake client microarchitecture based processors. + CK_Cannonlake, + + /// \name Knights Landing + /// Knights Landing processor. + CK_KNL, + + /// \name Lakemont + /// Lakemont microarchitecture based processors. + CK_Lakemont, + + /// \name K6 + /// K6 architecture processors. + //@{ + CK_K6, + CK_K6_2, + CK_K6_3, + //@} + + /// \name K7 + /// K7 architecture processors. + //@{ + CK_Athlon, + CK_AthlonThunderbird, + CK_Athlon4, + CK_AthlonXP, + CK_AthlonMP, + //@} + + /// \name K8 + /// K8 architecture processors. + //@{ + CK_Athlon64, + CK_Athlon64SSE3, + CK_AthlonFX, + CK_K8, + CK_K8SSE3, + CK_Opteron, + CK_OpteronSSE3, + CK_AMDFAM10, + //@} + + /// \name Bobcat + /// Bobcat architecture processors. + //@{ + CK_BTVER1, + CK_BTVER2, + //@} + + /// \name Bulldozer + /// Bulldozer architecture processors. + //@{ + CK_BDVER1, + CK_BDVER2, + CK_BDVER3, + CK_BDVER4, + //@} + + /// \name zen + /// Zen architecture processors. + //@{ + CK_ZNVER1, + //@} + + /// This specification is deprecated and will be removed in the future. + /// Users should prefer \see CK_K8. + // FIXME: Warn on this when the CPU is set to it. + //@{ + CK_x86_64, + //@} + + /// \name Geode + /// Geode processors. + //@{ + CK_Geode + //@} + } CPU = CK_Generic; + + bool checkCPUKind(CPUKind Kind) const { + // Perform any per-CPU checks necessary to determine if this CPU is + // acceptable. + // FIXME: This results in terrible diagnostics. Clang just says the CPU is + // invalid without explaining *why*. + switch (Kind) { + case CK_Generic: + // No processor selected! + return false; + + case CK_i386: + case CK_i486: + case CK_WinChipC6: + case CK_WinChip2: + case CK_C3: + case CK_i586: + case CK_Pentium: + case CK_PentiumMMX: + case CK_i686: + case CK_PentiumPro: + case CK_Pentium2: + case CK_Pentium3: + case CK_Pentium3M: + case CK_PentiumM: + case CK_Yonah: + case CK_C3_2: + case CK_Pentium4: + case CK_Pentium4M: + case CK_Lakemont: + case CK_Prescott: + case CK_K6: + case CK_K6_2: + case CK_K6_3: + case CK_Athlon: + case CK_AthlonThunderbird: + case CK_Athlon4: + case CK_AthlonXP: + case CK_AthlonMP: + case CK_Geode: + // Only accept certain architectures when compiling in 32-bit mode. + if (getTriple().getArch() != llvm::Triple::x86) + return false; + + LLVM_FALLTHROUGH; + case CK_Nocona: + case CK_Core2: + case CK_Penryn: + case CK_Bonnell: + case CK_Silvermont: + case CK_Goldmont: + case CK_Nehalem: + case CK_Westmere: + case CK_SandyBridge: + case CK_IvyBridge: + case CK_Haswell: + case CK_Broadwell: + case CK_SkylakeClient: + case CK_SkylakeServer: + case CK_Cannonlake: + case CK_KNL: + case CK_Athlon64: + case CK_Athlon64SSE3: + case CK_AthlonFX: + case CK_K8: + case CK_K8SSE3: + case CK_Opteron: + case CK_OpteronSSE3: + case CK_AMDFAM10: + case CK_BTVER1: + case CK_BTVER2: + case CK_BDVER1: + case CK_BDVER2: + case CK_BDVER3: + case CK_BDVER4: + case CK_ZNVER1: + case CK_x86_64: + return true; + } + llvm_unreachable("Unhandled CPU kind"); + } + + CPUKind getCPUKind(StringRef CPU) const; + + enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default; + +public: + X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &) + : TargetInfo(Triple) { + LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); + } + + unsigned getFloatEvalMethod() const override { + // X87 evaluates with 80 bits "long double" precision. + return SSELevel == NoSSE ? 2 : 0; + } + + ArrayRef<const char *> getGCCRegNames() const override; + + ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { + return None; + } + + ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; + + bool validateCpuSupports(StringRef Name) const override; + + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override; + + bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize, + bool &HasSizeMismatch) const override { + // esp and ebp are the only 32-bit registers the x86 backend can currently + // handle. + if (RegName.equals("esp") || RegName.equals("ebp")) { + // Check that the register size is 32-bit. + HasSizeMismatch = RegSize != 32; + return true; + } + + return false; + } + + bool validateOutputSize(StringRef Constraint, unsigned Size) const override; + + bool validateInputSize(StringRef Constraint, unsigned Size) const override; + + virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const; + + std::string convertConstraint(const char *&Constraint) const override; + const char *getClobbers() const override { + return "~{dirflag},~{fpsr},~{flags}"; + } + + StringRef getConstraintRegister(const StringRef &Constraint, + const StringRef &Expression) const override { + StringRef::iterator I, E; + for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) { + if (isalpha(*I)) + break; + } + if (I == E) + return ""; + switch (*I) { + // For the register constraints, return the matching register name + case 'a': + return "ax"; + case 'b': + return "bx"; + case 'c': + return "cx"; + case 'd': + return "dx"; + case 'S': + return "si"; + case 'D': + return "di"; + // In case the constraint is 'r' we need to return Expression + case 'r': + return Expression; + default: + // Default value if there is no constraint for the register + return ""; + } + return ""; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; + + static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level, + bool Enabled); + + static void setMMXLevel(llvm::StringMap<bool> &Features, MMX3DNowEnum Level, + bool Enabled); + + static void setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level, + bool Enabled); + + void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, + bool Enabled) const override { + setFeatureEnabledImpl(Features, Name, Enabled); + } + + // This exists purely to cut down on the number of virtual calls in + // initFeatureMap which calls this repeatedly. + static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features, + StringRef Name, bool Enabled); + + bool + initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, + StringRef CPU, + const std::vector<std::string> &FeaturesVec) const override; + + bool isValidFeatureName(StringRef Name) const override; + + bool hasFeature(StringRef Feature) const override; + + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override; + + StringRef getABI() const override { + if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F) + return "avx512"; + if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX) + return "avx"; + if (getTriple().getArch() == llvm::Triple::x86 && + MMX3DNowLevel == NoMMX3DNow) + return "no-mmx"; + return ""; + } + + bool isValidCPUName(StringRef Name) const override { + return checkCPUKind(getCPUKind(Name)); + } + + bool setCPU(const std::string &Name) override { + return checkCPUKind(CPU = getCPUKind(Name)); + } + + bool setFPMath(StringRef Name) override; + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + // Most of the non-ARM calling conventions are i386 conventions. + switch (CC) { + case CC_X86ThisCall: + case CC_X86FastCall: + case CC_X86StdCall: + case CC_X86VectorCall: + case CC_X86RegCall: + case CC_C: + case CC_Swift: + case CC_X86Pascal: + case CC_IntelOclBicc: + case CC_OpenCLKernel: + return CCCR_OK; + default: + return CCCR_Warning; + } + } + + CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + return MT == CCMT_Member ? CC_X86ThisCall : CC_C; + } + + bool hasSjLjLowering() const override { return true; } + + void setSupportedOpenCLOpts() override { + getSupportedOpenCLOpts().supportAll(); + } +}; + +// X86-32 generic target +class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo { +public: + X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : X86TargetInfo(Triple, Opts) { + DoubleAlign = LongLongAlign = 32; + LongDoubleWidth = 96; + LongDoubleAlign = 32; + SuitableAlign = 128; + resetDataLayout("e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"); + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + IntPtrType = SignedInt; + RegParmMax = 3; + + // Use fpret for all types. + RealTypeUsesObjCFPRet = + ((1 << TargetInfo::Float) | (1 << TargetInfo::Double) | + (1 << TargetInfo::LongDouble)); + + // x86-32 has atomics up to 8 bytes + // FIXME: Check that we actually have cmpxchg8b before setting + // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.) + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } + + int getEHDataRegisterNumber(unsigned RegNo) const override { + if (RegNo == 0) + return 0; + if (RegNo == 1) + return 2; + return -1; + } + + bool validateOperandSize(StringRef Constraint, unsigned Size) const override { + switch (Constraint[0]) { + default: + break; + case 'R': + case 'q': + case 'Q': + case 'a': + case 'b': + case 'c': + case 'd': + case 'S': + case 'D': + return Size <= 32; + case 'A': + return Size <= 64; + } + + return X86TargetInfo::validateOperandSize(Constraint, Size); + } + + ArrayRef<Builtin::Info> getTargetBuiltins() const override; +}; + +class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo + : public NetBSDTargetInfo<X86_32TargetInfo> { +public: + NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {} + + unsigned getFloatEvalMethod() const override { + unsigned Major, Minor, Micro; + getTriple().getOSVersion(Major, Minor, Micro); + // New NetBSD uses the default rounding mode. + if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0) + return X86_32TargetInfo::getFloatEvalMethod(); + // NetBSD before 6.99.26 defaults to "double" rounding. + return 1; + } +}; + +class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo + : public OpenBSDTargetInfo<X86_32TargetInfo> { +public: + OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) { + SizeType = UnsignedLong; + IntPtrType = SignedLong; + PtrDiffType = SignedLong; + } +}; + +class LLVM_LIBRARY_VISIBILITY BitrigI386TargetInfo + : public BitrigTargetInfo<X86_32TargetInfo> { +public: + BitrigI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : BitrigTargetInfo<X86_32TargetInfo>(Triple, Opts) { + SizeType = UnsignedLong; + IntPtrType = SignedLong; + PtrDiffType = SignedLong; + } +}; + +class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo + : public DarwinTargetInfo<X86_32TargetInfo> { +public: + DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) { + LongDoubleWidth = 128; + LongDoubleAlign = 128; + SuitableAlign = 128; + MaxVectorAlign = 256; + // The watchOS simulator uses the builtin bool type for Objective-C. + llvm::Triple T = llvm::Triple(Triple); + if (T.isWatchOS()) + UseSignedCharForObjCBool = false; + SizeType = UnsignedLong; + IntPtrType = SignedLong; + resetDataLayout("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"); + HasAlignMac68kSupport = true; + } + + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { + if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features, + Diags)) + return false; + // We now know the features we have: we can decide how to align vectors. + MaxVectorAlign = + hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128; + return true; + } +}; + +// x86-32 Windows target +class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo + : public WindowsTargetInfo<X86_32TargetInfo> { +public: + WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) { + WCharType = UnsignedShort; + DoubleAlign = LongLongAlign = 64; + bool IsWinCOFF = + getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); + resetDataLayout(IsWinCOFF + ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" + : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder); + } +}; + +// x86-32 Windows Visual Studio target +class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo + : public WindowsX86_32TargetInfo { +public: + MicrosoftX86_32TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsX86_32TargetInfo(Triple, Opts) { + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder); + WindowsX86_32TargetInfo::getVisualStudioDefines(Opts, Builder); + // The value of the following reflects processor type. + // 300=386, 400=486, 500=Pentium, 600=Blend (default) + // We lost the original triple, so we use the default. + Builder.defineMacro("_M_IX86", "600"); + } +}; + +static void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) { + // Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang + // supports __declspec natively under -fms-extensions, but we define a no-op + // __declspec macro anyway for pre-processor compatibility. + if (Opts.MicrosoftExt) + Builder.defineMacro("__declspec", "__declspec"); + else + Builder.defineMacro("__declspec(a)", "__attribute__((a))"); + + if (!Opts.MicrosoftExt) { + // Provide macros for all the calling convention keywords. Provide both + // single and double underscore prefixed variants. These are available on + // x64 as well as x86, even though they have no effect. + const char *CCs[] = {"cdecl", "stdcall", "fastcall", "thiscall", "pascal"}; + for (const char *CC : CCs) { + std::string GCCSpelling = "__attribute__((__"; + GCCSpelling += CC; + GCCSpelling += "__))"; + Builder.defineMacro(Twine("_") + CC, GCCSpelling); + Builder.defineMacro(Twine("__") + CC, GCCSpelling); + } + } +} + +// x86-32 MinGW target +class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo + : public WindowsX86_32TargetInfo { +public: + MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : WindowsX86_32TargetInfo(Triple, Opts) { + HasFloat128 = true; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder); + DefineStd(Builder, "WIN32", Opts); + DefineStd(Builder, "WINNT", Opts); + Builder.defineMacro("_X86_"); + addMinGWDefines(Opts, Builder); + } +}; + +// x86-32 Cygwin target +class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo { +public: + CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : X86_32TargetInfo(Triple, Opts) { + WCharType = UnsignedShort; + DoubleAlign = LongLongAlign = 64; + resetDataLayout("e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + X86_32TargetInfo::getTargetDefines(Opts, Builder); + Builder.defineMacro("_X86_"); + Builder.defineMacro("__CYGWIN__"); + Builder.defineMacro("__CYGWIN32__"); + addCygMingDefines(Opts, Builder); + DefineStd(Builder, "unix", Opts); + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + } +}; + +// x86-32 Haiku target +class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo + : public HaikuTargetInfo<X86_32TargetInfo> { +public: + HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {} + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder); + Builder.defineMacro("__INTEL__"); + } +}; + +// X86-32 MCU target +class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo { +public: + MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : X86_32TargetInfo(Triple, Opts) { + LongDoubleWidth = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + resetDataLayout("e-m:e-p:32:32-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32"); + WIntType = UnsignedInt; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + // On MCU we support only C calling convention. + return CC == CC_C ? CCCR_OK : CCCR_Warning; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + X86_32TargetInfo::getTargetDefines(Opts, Builder); + Builder.defineMacro("__iamcu"); + Builder.defineMacro("__iamcu__"); + } + + bool allowsLargerPreferedTypeAlignment() const override { return false; } +}; + +// RTEMS Target +template <typename Target> +class LLVM_LIBRARY_VISIBILITY RTEMSTargetInfo : public OSTargetInfo<Target> { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // RTEMS defines; list based off of gcc output + + Builder.defineMacro("__rtems__"); + Builder.defineMacro("__ELF__"); + } + +public: + RTEMSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo<Target>(Triple, Opts) { + switch (Triple.getArch()) { + default: + case llvm::Triple::x86: + // 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; + } + } +}; + +// x86-32 RTEMS target +class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo { +public: + RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : X86_32TargetInfo(Triple, Opts) { + SizeType = UnsignedLong; + IntPtrType = SignedLong; + PtrDiffType = SignedLong; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + X86_32TargetInfo::getTargetDefines(Opts, Builder); + Builder.defineMacro("__INTEL__"); + Builder.defineMacro("__rtems__"); + } +}; + +// x86-64 generic target +class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo { +public: + X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : X86TargetInfo(Triple, Opts) { + const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32; + bool IsWinCOFF = + getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); + LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64; + LongDoubleWidth = 128; + LongDoubleAlign = 128; + LargeArrayMinWidth = 128; + LargeArrayAlign = 128; + SuitableAlign = 128; + SizeType = IsX32 ? UnsignedInt : UnsignedLong; + PtrDiffType = IsX32 ? SignedInt : SignedLong; + IntPtrType = IsX32 ? SignedInt : SignedLong; + IntMaxType = IsX32 ? SignedLongLong : SignedLong; + Int64Type = IsX32 ? SignedLongLong : SignedLong; + RegParmMax = 6; + + // Pointers are 32-bit in x32. + resetDataLayout(IsX32 + ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128" + : IsWinCOFF ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128" + : "e-m:e-i64:64-f80:128-n8:16:32:64-S128"); + + // Use fpret only for long double. + RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble); + + // Use fp2ret for _Complex long double. + ComplexLongDoubleUsesFP2Ret = true; + + // Make __builtin_ms_va_list available. + HasBuiltinMSVaList = true; + + // x86-64 has atomics up to 16 bytes. + MaxAtomicPromoteWidth = 128; + MaxAtomicInlineWidth = 128; + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::X86_64ABIBuiltinVaList; + } + + int getEHDataRegisterNumber(unsigned RegNo) const override { + if (RegNo == 0) + return 0; + if (RegNo == 1) + return 1; + return -1; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + case CC_C: + case CC_Swift: + case CC_X86VectorCall: + case CC_IntelOclBicc: + case CC_Win64: + case CC_PreserveMost: + case CC_PreserveAll: + case CC_X86RegCall: + case CC_OpenCLKernel: + return CCCR_OK; + default: + return CCCR_Warning; + } + } + + CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + return CC_C; + } + + // for x32 we need it here explicitly + bool hasInt128Type() const override { return true; } + + unsigned getUnwindWordWidth() const override { return 64; } + + unsigned getRegisterWidth() const override { return 64; } + + bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize, + bool &HasSizeMismatch) const override { + // rsp and rbp are the only 64-bit registers the x86 backend can currently + // handle. + if (RegName.equals("rsp") || RegName.equals("rbp")) { + // Check that the register size is 64-bit. + HasSizeMismatch = RegSize != 64; + return true; + } + + // Check if the register is a 32-bit register the backend can handle. + return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize, + HasSizeMismatch); + } + + ArrayRef<Builtin::Info> getTargetBuiltins() const override; +}; + +// x86-64 Windows target +class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo + : public WindowsTargetInfo<X86_64TargetInfo> { +public: + WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) { + WCharType = UnsignedShort; + LongWidth = LongAlign = 32; + DoubleAlign = LongLongAlign = 64; + IntMaxType = SignedLongLong; + Int64Type = SignedLongLong; + SizeType = UnsignedLongLong; + PtrDiffType = SignedLongLong; + IntPtrType = SignedLongLong; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsTargetInfo<X86_64TargetInfo>::getTargetDefines(Opts, Builder); + Builder.defineMacro("_WIN64"); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + case CC_X86StdCall: + case CC_X86ThisCall: + case CC_X86FastCall: + return CCCR_Ignore; + case CC_C: + case CC_X86VectorCall: + case CC_IntelOclBicc: + case CC_X86_64SysV: + case CC_Swift: + case CC_X86RegCall: + case CC_OpenCLKernel: + return CCCR_OK; + default: + return CCCR_Warning; + } + } +}; + +// x86-64 Windows Visual Studio target +class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo + : public WindowsX86_64TargetInfo { +public: + MicrosoftX86_64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsX86_64TargetInfo(Triple, Opts) { + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder); + WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder); + Builder.defineMacro("_M_X64", "100"); + Builder.defineMacro("_M_AMD64", "100"); + } +}; + +// x86-64 MinGW target +class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo + : public WindowsX86_64TargetInfo { +public: + MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : WindowsX86_64TargetInfo(Triple, Opts) { + // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks + // with x86 FP ops. Weird. + LongDoubleWidth = LongDoubleAlign = 128; + LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); + HasFloat128 = true; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder); + DefineStd(Builder, "WIN64", Opts); + Builder.defineMacro("__MINGW64__"); + addMinGWDefines(Opts, Builder); + + // GCC defines this macro when it is using __gxx_personality_seh0. + if (!Opts.SjLjExceptions) + Builder.defineMacro("__SEH__"); + } +}; + +// x86-64 Cygwin target +class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo { +public: + CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : X86_64TargetInfo(Triple, Opts) { + TLSSupported = false; + WCharType = UnsignedShort; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + X86_64TargetInfo::getTargetDefines(Opts, Builder); + Builder.defineMacro("__x86_64__"); + Builder.defineMacro("__CYGWIN__"); + Builder.defineMacro("__CYGWIN64__"); + addCygMingDefines(Opts, Builder); + DefineStd(Builder, "unix", Opts); + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + + // GCC defines this macro when it is using __gxx_personality_seh0. + if (!Opts.SjLjExceptions) + Builder.defineMacro("__SEH__"); + } +}; + +class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo + : public DarwinTargetInfo<X86_64TargetInfo> { +public: + DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) { + Int64Type = SignedLongLong; + // The 64-bit iOS simulator uses the builtin bool type for Objective-C. + llvm::Triple T = llvm::Triple(Triple); + if (T.isiOS()) + UseSignedCharForObjCBool = false; + resetDataLayout("e-m:o-i64:64-f80:128-n8:16:32:64-S128"); + } + + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override { + if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features, + Diags)) + return false; + // We now know the features we have: we can decide how to align vectors. + MaxVectorAlign = + hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128; + return true; + } +}; + +class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo + : public OpenBSDTargetInfo<X86_64TargetInfo> { +public: + OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) { + IntMaxType = SignedLongLong; + Int64Type = SignedLongLong; + } +}; + +class LLVM_LIBRARY_VISIBILITY BitrigX86_64TargetInfo + : public BitrigTargetInfo<X86_64TargetInfo> { +public: + BitrigX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : BitrigTargetInfo<X86_64TargetInfo>(Triple, Opts) { + IntMaxType = SignedLongLong; + Int64Type = SignedLongLong; + } +}; + +// x86_32 Android target +class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo + : public LinuxTargetInfo<X86_32TargetInfo> { +public: + AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) { + SuitableAlign = 32; + LongDoubleWidth = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } +}; + +// x86_64 Android target +class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo + : public LinuxTargetInfo<X86_64TargetInfo> { +public: + AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) { + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + } + + bool useFloat128ManglingForLongDouble() const override { return true; } +}; +} // namespace targets +} // namespace clang +#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H |