| //===--- X86.h - Declare X86 target feature support -------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // 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" |
| #include "llvm/Support/X86TargetParser.h" |
| |
| namespace clang { |
| namespace targets { |
| |
| static const unsigned X86AddrSpaceMap[] = { |
| 0, // Default |
| 0, // opencl_global |
| 0, // opencl_local |
| 0, // opencl_constant |
| 0, // opencl_private |
| 0, // opencl_generic |
| 0, // opencl_global_device |
| 0, // opencl_global_host |
| 0, // cuda_device |
| 0, // cuda_constant |
| 0, // cuda_shared |
| 0, // sycl_global |
| 0, // sycl_global_device |
| 0, // sycl_global_host |
| 0, // sycl_local |
| 0, // sycl_private |
| 270, // ptr32_sptr |
| 271, // ptr32_uptr |
| 272 // ptr64 |
| }; |
| |
| // 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; |
| enum AddrSpace { ptr32_sptr = 270, ptr32_uptr = 271, ptr64 = 272 }; |
| |
| bool HasAES = false; |
| bool HasVAES = false; |
| bool HasPCLMUL = false; |
| bool HasVPCLMULQDQ = false; |
| bool HasGFNI = 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 HasAVX512VNNI = false; |
| bool HasAVX512FP16 = false; |
| bool HasAVX512BF16 = false; |
| bool HasAVX512ER = false; |
| bool HasAVX512PF = false; |
| bool HasAVX512DQ = false; |
| bool HasAVX512BITALG = false; |
| bool HasAVX512BW = false; |
| bool HasAVX512VL = false; |
| bool HasAVX512VBMI = false; |
| bool HasAVX512VBMI2 = false; |
| bool HasAVX512IFMA = false; |
| bool HasAVX512VP2INTERSECT = false; |
| bool HasSHA = false; |
| bool HasSHSTK = false; |
| bool HasSGX = false; |
| bool HasCX8 = 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 HasCLDEMOTE = false; |
| bool HasPCONFIG = false; |
| bool HasPKU = false; |
| bool HasCLFLUSHOPT = false; |
| bool HasCLWB = false; |
| bool HasMOVBE = false; |
| bool HasPREFETCHWT1 = false; |
| bool HasRDPID = false; |
| bool HasRetpolineExternalThunk = false; |
| bool HasLAHFSAHF = false; |
| bool HasWBNOINVD = false; |
| bool HasWAITPKG = false; |
| bool HasMOVDIRI = false; |
| bool HasMOVDIR64B = false; |
| bool HasPTWRITE = false; |
| bool HasINVPCID = false; |
| bool HasENQCMD = false; |
| bool HasKL = false; // For key locker |
| bool HasWIDEKL = false; // For wide key locker |
| bool HasHRESET = false; |
| bool HasAVXVNNI = false; |
| bool HasAMXTILE = false; |
| bool HasAMXINT8 = false; |
| bool HasAMXBF16 = false; |
| bool HasSERIALIZE = false; |
| bool HasTSXLDTRK = false; |
| bool HasUINTR = false; |
| bool HasCRC32 = false; |
| bool HasX87 = false; |
| |
| protected: |
| llvm::X86::CPUKind CPU = llvm::X86::CK_None; |
| |
| 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(); |
| AddrSpaceMap = &X86AddrSpaceMap; |
| HasStrictFP = true; |
| |
| bool IsWinCOFF = |
| getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); |
| if (IsWinCOFF) |
| MaxVectorAlign = MaxTLSAlign = 8192u * getCharWidth(); |
| } |
| |
| const char *getLongDoubleMangling() const override { |
| return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e"; |
| } |
| |
| 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 isSPRegName(StringRef RegName) const override { |
| return RegName.equals("esp") || RegName.equals("rsp"); |
| } |
| |
| bool validateCpuSupports(StringRef Name) const override; |
| |
| bool validateCpuIs(StringRef Name) const override; |
| |
| bool validateCPUSpecificCPUDispatch(StringRef Name) const override; |
| |
| char CPUSpecificManglingCharacter(StringRef Name) const override; |
| |
| void getCPUSpecificCPUDispatchFeatures( |
| StringRef Name, |
| llvm::SmallVectorImpl<StringRef> &Features) const override; |
| |
| Optional<unsigned> getCPUCacheLineSize() 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(const llvm::StringMap<bool> &FeatureMap, |
| StringRef Constraint, unsigned Size) const override; |
| |
| bool validateInputSize(const llvm::StringMap<bool> &FeatureMap, |
| StringRef Constraint, unsigned Size) const override; |
| |
| virtual bool |
| checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override { |
| return true; |
| }; |
| |
| virtual bool |
| checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override { |
| return true; |
| }; |
| |
| virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap, |
| StringRef Constraint, unsigned Size) const; |
| |
| std::string convertConstraint(const char *&Constraint) const override; |
| const char *getClobbers() const override { |
| return "~{dirflag},~{fpsr},~{flags}"; |
| } |
| |
| StringRef getConstraintRegister(StringRef Constraint, |
| StringRef Expression) const override { |
| StringRef::iterator I, E; |
| for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) { |
| if (isalpha(*I) || *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; |
| // Double letters Y<x> constraints |
| case 'Y': |
| if ((++I != E) && ((*I == '0') || (*I == 'z'))) |
| return "xmm0"; |
| break; |
| default: |
| break; |
| } |
| return ""; |
| } |
| |
| bool useFP16ConversionIntrinsics() const override { |
| return false; |
| } |
| |
| void getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const override; |
| |
| void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, |
| bool Enabled) const final; |
| |
| 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 final; |
| |
| 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 supportsTargetAttributeTune() const override { |
| return true; |
| } |
| |
| bool isValidCPUName(StringRef Name) const override { |
| bool Only64Bit = getTriple().getArch() != llvm::Triple::x86; |
| return llvm::X86::parseArchX86(Name, Only64Bit) != llvm::X86::CK_None; |
| } |
| |
| bool isValidTuneCPUName(StringRef Name) const override { |
| if (Name == "generic") |
| return true; |
| |
| // Allow 32-bit only CPUs regardless of 64-bit mode unlike isValidCPUName. |
| // NOTE: gcc rejects 32-bit mtune CPUs in 64-bit mode. But being lenient |
| // since mtune was ignored by clang for so long. |
| return llvm::X86::parseTuneCPU(Name) != llvm::X86::CK_None; |
| } |
| |
| void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
| void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override; |
| |
| bool setCPU(const std::string &Name) override { |
| bool Only64Bit = getTriple().getArch() != llvm::Triple::x86; |
| CPU = llvm::X86::parseArchX86(Name, Only64Bit); |
| return CPU != llvm::X86::CK_None; |
| } |
| |
| unsigned multiVersionSortPriority(StringRef Name) const override; |
| |
| bool setFPMath(StringRef Name) override; |
| |
| bool supportsExtendIntArgs() const override { |
| return getTriple().getArch() != llvm::Triple::x86; |
| } |
| |
| 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_PreserveMost: |
| case CC_Swift: |
| case CC_X86Pascal: |
| case CC_IntelOclBicc: |
| case CC_OpenCLKernel: |
| return CCCR_OK; |
| case CC_SwiftAsync: |
| return CCCR_Error; |
| default: |
| return CCCR_Warning; |
| } |
| } |
| |
| bool checkArithmeticFenceSupported() const override { return true; } |
| |
| CallingConv getDefaultCallingConv() const override { |
| return CC_C; |
| } |
| |
| bool hasSjLjLowering() const override { return true; } |
| |
| void setSupportedOpenCLOpts() override { supportAllOpenCLOpts(); } |
| |
| uint64_t getPointerWidthV(unsigned AddrSpace) const override { |
| if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr) |
| return 32; |
| if (AddrSpace == ptr64) |
| return 64; |
| return PointerWidth; |
| } |
| |
| uint64_t getPointerAlignV(unsigned AddrSpace) const override { |
| return getPointerWidthV(AddrSpace); |
| } |
| }; |
| |
| // 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( |
| Triple.isOSBinFormatMachO() |
| ? "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-" |
| "f80:32-n8:16:32-S128" |
| : "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-" |
| "f80:32-n8:16:32-S128", |
| Triple.isOSBinFormatMachO() ? "_" : ""); |
| SizeType = UnsignedInt; |
| PtrDiffType = SignedInt; |
| IntPtrType = SignedInt; |
| RegParmMax = 3; |
| |
| // Use fpret for all types. |
| RealTypeUsesObjCFPRet = |
| ((1 << (int)FloatModeKind::Float) | (1 << (int)FloatModeKind::Double) | |
| (1 << (int)FloatModeKind::LongDouble)); |
| |
| // x86-32 has atomics up to 8 bytes |
| MaxAtomicPromoteWidth = 64; |
| MaxAtomicInlineWidth = 32; |
| } |
| |
| 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(const llvm::StringMap<bool> &FeatureMap, |
| 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(FeatureMap, Constraint, Size); |
| } |
| |
| void setMaxAtomicWidth() override { |
| if (hasFeature("cx8")) |
| MaxAtomicInlineWidth = 64; |
| } |
| |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override; |
| |
| bool hasExtIntType() const override { return true; } |
| }; |
| |
| 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 { |
| VersionTuple OsVersion = getTriple().getOSVersion(); |
| // New NetBSD uses the default rounding mode. |
| if (OsVersion >= VersionTuple(6, 99, 26) || OsVersion.getMajor() == 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 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-p270:32:32-p271:32:32-p272:64:64-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) { |
| DoubleAlign = LongLongAlign = 64; |
| bool IsWinCOFF = |
| getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); |
| resetDataLayout(IsWinCOFF ? "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:" |
| "64-i64:64-f80:32-n8:16:32-a:0:32-S32" |
| : "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:" |
| "64-i64:64-f80:32-n8:16:32-a:0:32-S32", |
| IsWinCOFF ? "_" : ""); |
| } |
| }; |
| |
| // 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); |
| // 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"); |
| } |
| }; |
| |
| // 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); |
| Builder.defineMacro("_X86_"); |
| } |
| }; |
| |
| // 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) { |
| this->WCharType = TargetInfo::UnsignedShort; |
| DoubleAlign = LongLongAlign = 64; |
| resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-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-p270:32:32-p271:32:32-p272:64:64-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; } |
| }; |
| |
| // 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().isX32(); |
| 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-p270:32:32-p271:32:32-p272:64:64-" |
| "i64:64-f80:128-n8:16:32:64-S128" |
| : IsWinCOFF ? "e-m:w-p270:32:32-p271:32:32-p272:64:" |
| "64-i64:64-f80:128-n8:16:32:64-S128" |
| : "e-m:e-p270:32:32-p271:32:32-p272:64:" |
| "64-i64:64-f80:128-n8:16:32:64-S128"); |
| |
| // Use fpret only for long double. |
| RealTypeUsesObjCFPRet = (1 << (int)FloatModeKind::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 = 64; |
| } |
| |
| 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_SwiftAsync: |
| 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() 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); |
| } |
| |
| void setMaxAtomicWidth() override { |
| if (hasFeature("cx16")) |
| MaxAtomicInlineWidth = 128; |
| } |
| |
| ArrayRef<Builtin::Info> getTargetBuiltins() const override; |
| |
| bool hasExtIntType() const override { return true; } |
| }; |
| |
| // 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) { |
| LongWidth = LongAlign = 32; |
| DoubleAlign = LongLongAlign = 64; |
| IntMaxType = SignedLongLong; |
| Int64Type = SignedLongLong; |
| SizeType = UnsignedLongLong; |
| PtrDiffType = SignedLongLong; |
| IntPtrType = SignedLongLong; |
| } |
| |
| 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_PreserveMost: |
| case CC_PreserveAll: |
| case CC_X86_64SysV: |
| case CC_Swift: |
| case CC_SwiftAsync: |
| 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); |
| Builder.defineMacro("_M_X64", "100"); |
| Builder.defineMacro("_M_AMD64", "100"); |
| } |
| |
| TargetInfo::CallingConvKind |
| getCallingConvKind(bool ClangABICompat4) const override { |
| return CCK_MicrosoftWin64; |
| } |
| }; |
| |
| // 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; |
| } |
| }; |
| |
| // 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) { |
| this->WCharType = TargetInfo::UnsignedShort; |
| TLSSupported = false; |
| } |
| |
| 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"); |
| } |
| }; |
| |
| 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-p270:32:32-p271:32:32-p272:64:64-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; |
| } |
| }; |
| |
| // 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(); |
| } |
| }; |
| } // namespace targets |
| } // namespace clang |
| #endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H |