2017-07-22 06:37:03 +08:00
|
|
|
//===--- 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;
|
2017-12-27 16:16:54 +08:00
|
|
|
bool HasVAES = false;
|
2017-07-22 06:37:03 +08:00
|
|
|
bool HasPCLMUL = false;
|
2017-12-27 17:00:31 +08:00
|
|
|
bool HasVPCLMULQDQ = false;
|
2017-12-27 16:37:47 +08:00
|
|
|
bool HasGFNI = false;
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
2017-12-27 18:37:51 +08:00
|
|
|
bool HasAVX512VNNI = false;
|
2017-07-22 06:37:03 +08:00
|
|
|
bool HasAVX512ER = false;
|
|
|
|
bool HasAVX512PF = false;
|
|
|
|
bool HasAVX512DQ = false;
|
2017-12-27 18:01:00 +08:00
|
|
|
bool HasAVX512BITALG = false;
|
2017-07-22 06:37:03 +08:00
|
|
|
bool HasAVX512BW = false;
|
|
|
|
bool HasAVX512VL = false;
|
|
|
|
bool HasAVX512VBMI = false;
|
[x86][icelake][vbmi2]
added vbmi2 feature recognition
added intrinsics support for vbmi2 instructions
_mm[128,256,512]_mask[z]_compress_epi[16,32]
_mm[128,256,512]_mask_compressstoreu_epi[16,32]
_mm[128,256,512]_mask[z]_expand_epi[16,32]
_mm[128,256,512]_mask[z]_expandloadu_epi[16,32]
_mm[128,256,512]_mask[z]_sh[l,r]di_epi[16,32,64]
_mm[128,256,512]_mask_sh[l,r]dv_epi[16,32,64]
matching a similar work on the backend (D40206)
Differential Revision: https://reviews.llvm.org/D41557
llvm-svn: 321487
2017-12-27 19:25:07 +08:00
|
|
|
bool HasAVX512VBMI2 = false;
|
2017-07-22 06:37:03 +08:00
|
|
|
bool HasAVX512IFMA = false;
|
|
|
|
bool HasSHA = false;
|
|
|
|
bool HasMPX = false;
|
2017-11-26 20:34:54 +08:00
|
|
|
bool HasSHSTK = false;
|
|
|
|
bool HasIBT = false;
|
2017-07-22 06:37:03 +08:00
|
|
|
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,
|
2017-11-16 06:25:39 +08:00
|
|
|
#define PROC(ENUM, STRING, IS64BIT) CK_##ENUM,
|
|
|
|
#include "clang/Basic/X86Target.def"
|
2017-07-22 06:37:03 +08:00
|
|
|
} CPU = CK_Generic;
|
|
|
|
|
2017-10-24 00:20:15 +08:00
|
|
|
bool checkCPUKind(CPUKind Kind) const;
|
2017-07-22 06:37:03 +08:00
|
|
|
|
|
|
|
CPUKind getCPUKind(StringRef CPU) const;
|
|
|
|
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
std::string getCPUKindCanonicalName(CPUKind Kind) const;
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
|
|
|
|
2017-08-11 04:28:30 +08:00
|
|
|
bool validateCpuIs(StringRef Name) const override;
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
2017-08-24 17:07:34 +08:00
|
|
|
// Double letters Y<x> constraints
|
|
|
|
case 'Y':
|
|
|
|
if ((++I != E) && ((*I == '0') || (*I == 'z')))
|
|
|
|
return "xmm0";
|
2017-07-22 06:37:03 +08:00
|
|
|
default:
|
2017-08-24 17:07:34 +08:00
|
|
|
break;
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
[CodeGen][X86] Fix handling of __fp16 vectors.
This commit fixes a bug in IRGen where it generates completely broken
code for __fp16 vectors on X86. For example when the following code is
compiled:
half4 hv0, hv1, hv2; // these are vectors of __fp16.
void foo221() {
hv0 = hv1 + hv2;
}
clang generates the following IR, in which two i16 vectors are added:
@hv1 = common global <4 x i16> zeroinitializer, align 8
@hv2 = common global <4 x i16> zeroinitializer, align 8
@hv0 = common global <4 x i16> zeroinitializer, align 8
define void @foo221() {
%0 = load <4 x i16>, <4 x i16>* @hv1, align 8
%1 = load <4 x i16>, <4 x i16>* @hv2, align 8
%add = add <4 x i16> %0, %1
store <4 x i16> %add, <4 x i16>* @hv0, align 8
ret void
}
To fix the bug, this commit uses the code committed in r314056, which
modified clang to promote and truncate __fp16 vectors to and from float
vectors in the AST. It also fixes another IRGen bug where a short value
is assigned to an __fp16 variable without any integer-to-floating-point
conversion, as shown in the following example:
__fp16 a;
short b;
void foo1() {
a = b;
}
@b = common global i16 0, align 2
@a = common global i16 0, align 2
define void @foo1() #0 {
%0 = load i16, i16* @b, align 2
store i16 %0, i16* @a, align 2
ret void
}
rdar://problem/20625184
Differential Revision: https://reviews.llvm.org/D40112
llvm-svn: 320215
2017-12-09 08:02:37 +08:00
|
|
|
bool useFP16ConversionIntrinsics() const override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
bool supportsMultiVersioning() const override {
|
|
|
|
return getTriple().isOSBinFormatELF();
|
|
|
|
}
|
|
|
|
unsigned multiVersionSortPriority(StringRef Name) const override;
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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 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) {
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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) {
|
2017-10-07 07:09:55 +08:00
|
|
|
this->WCharType = TargetInfo::UnsignedShort;
|
2017-07-22 06:37:03 +08:00
|
|
|
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; }
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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;
|
2017-09-23 00:30:00 +08:00
|
|
|
MaxAtomicInlineWidth = 64;
|
2017-07-22 06:37:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-09-23 00:30:00 +08:00
|
|
|
void setMaxAtomicWidth() override {
|
|
|
|
if (hasFeature("cx16"))
|
|
|
|
MaxAtomicInlineWidth = 128;
|
|
|
|
}
|
|
|
|
|
2017-07-22 06:37:03 +08:00
|
|
|
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) {
|
|
|
|
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:
|
2017-09-27 03:26:01 +08:00
|
|
|
case CC_PreserveMost:
|
|
|
|
case CC_PreserveAll:
|
2017-07-22 06:37:03 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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) {
|
2017-10-07 07:09:55 +08:00
|
|
|
this->WCharType = TargetInfo::UnsignedShort;
|
2017-07-22 06:37:03 +08:00
|
|
|
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-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();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool useFloat128ManglingForLongDouble() const override { return true; }
|
|
|
|
};
|
|
|
|
} // namespace targets
|
|
|
|
} // namespace clang
|
|
|
|
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
|