|  | //===--- 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 | 
|  | 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 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; | 
|  |  | 
|  | 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; | 
|  |  | 
|  | 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; | 
|  | default: | 
|  | return CCCR_Warning; | 
|  | } | 
|  | } | 
|  |  | 
|  | CallingConv getDefaultCallingConv() const override { | 
|  | return CC_C; | 
|  | } | 
|  |  | 
|  | bool hasSjLjLowering() const override { return true; } | 
|  |  | 
|  | void setSupportedOpenCLOpts() override { | 
|  | getSupportedOpenCLOpts().supportAll(); | 
|  | } | 
|  |  | 
|  | 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"); | 
|  | 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 | 
|  | 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 { | 
|  | 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 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"); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // 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().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-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 << 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 = 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_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_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 |