915 lines
28 KiB
C++
915 lines
28 KiB
C++
//===--- 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 { 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");
|
|
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
|