1//===--- X86.h - Declare X86 target feature support -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file declares X86 TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
14#define LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
15
16#include "OSTargets.h"
17#include "clang/Basic/TargetInfo.h"
18#include "clang/Basic/TargetOptions.h"
19#include "llvm/ADT/Triple.h"
20#include "llvm/Support/Compiler.h"
21#include "llvm/Support/X86TargetParser.h"
22
23namespace clang {
24namespace targets {
25
26static const unsigned X86AddrSpaceMap[] = {
27    0,   // Default
28    0,   // opencl_global
29    0,   // opencl_local
30    0,   // opencl_constant
31    0,   // opencl_private
32    0,   // opencl_generic
33    0,   // cuda_device
34    0,   // cuda_constant
35    0,   // cuda_shared
36    270, // ptr32_sptr
37    271, // ptr32_uptr
38    272  // ptr64
39};
40
41// X86 target abstract base class; x86-32 and x86-64 are very close, so
42// most of the implementation can be shared.
43class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
44
45  enum X86SSEEnum {
46    NoSSE,
47    SSE1,
48    SSE2,
49    SSE3,
50    SSSE3,
51    SSE41,
52    SSE42,
53    AVX,
54    AVX2,
55    AVX512F
56  } SSELevel = NoSSE;
57  enum MMX3DNowEnum {
58    NoMMX3DNow,
59    MMX,
60    AMD3DNow,
61    AMD3DNowAthlon
62  } MMX3DNowLevel = NoMMX3DNow;
63  enum XOPEnum { NoXOP, SSE4A, FMA4, XOP } XOPLevel = NoXOP;
64  enum AddrSpace { ptr32_sptr = 270, ptr32_uptr = 271, ptr64 = 272 };
65
66  bool HasAES = false;
67  bool HasVAES = false;
68  bool HasPCLMUL = false;
69  bool HasVPCLMULQDQ = false;
70  bool HasGFNI = false;
71  bool HasLZCNT = false;
72  bool HasRDRND = false;
73  bool HasFSGSBASE = false;
74  bool HasBMI = false;
75  bool HasBMI2 = false;
76  bool HasPOPCNT = false;
77  bool HasRTM = false;
78  bool HasPRFCHW = false;
79  bool HasRDSEED = false;
80  bool HasADX = false;
81  bool HasTBM = false;
82  bool HasLWP = false;
83  bool HasFMA = false;
84  bool HasF16C = false;
85  bool HasAVX512CD = false;
86  bool HasAVX512VPOPCNTDQ = false;
87  bool HasAVX512VNNI = false;
88  bool HasAVX512BF16 = false;
89  bool HasAVX512ER = false;
90  bool HasAVX512PF = false;
91  bool HasAVX512DQ = false;
92  bool HasAVX512BITALG = false;
93  bool HasAVX512BW = false;
94  bool HasAVX512VL = false;
95  bool HasAVX512VBMI = false;
96  bool HasAVX512VBMI2 = false;
97  bool HasAVX512IFMA = false;
98  bool HasAVX512VP2INTERSECT = false;
99  bool HasSHA = false;
100  bool HasSHSTK = false;
101  bool HasSGX = false;
102  bool HasCX8 = false;
103  bool HasCX16 = false;
104  bool HasFXSR = false;
105  bool HasXSAVE = false;
106  bool HasXSAVEOPT = false;
107  bool HasXSAVEC = false;
108  bool HasXSAVES = false;
109  bool HasMWAITX = false;
110  bool HasCLZERO = false;
111  bool HasCLDEMOTE = false;
112  bool HasPCONFIG = false;
113  bool HasPKU = false;
114  bool HasCLFLUSHOPT = false;
115  bool HasCLWB = false;
116  bool HasMOVBE = false;
117  bool HasPREFETCHWT1 = false;
118  bool HasRDPID = false;
119  bool HasRetpolineExternalThunk = false;
120  bool HasLAHFSAHF = false;
121  bool HasWBNOINVD = false;
122  bool HasWAITPKG = false;
123  bool HasMOVDIRI = false;
124  bool HasMOVDIR64B = false;
125  bool HasPTWRITE = false;
126  bool HasINVPCID = false;
127  bool HasENQCMD = false;
128  bool HasAMXTILE = false;
129  bool HasAMXINT8 = false;
130  bool HasAMXBF16 = false;
131  bool HasSERIALIZE = false;
132  bool HasTSXLDTRK = false;
133
134protected:
135  llvm::X86::CPUKind CPU = llvm::X86::CK_None;
136
137  enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
138
139public:
140  X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
141      : TargetInfo(Triple) {
142    LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
143    AddrSpaceMap = &X86AddrSpaceMap;
144    HasStrictFP = true;
145  }
146
147  const char *getLongDoubleMangling() const override {
148    return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e";
149  }
150
151  unsigned getFloatEvalMethod() const override {
152    // X87 evaluates with 80 bits "long double" precision.
153    return SSELevel == NoSSE ? 2 : 0;
154  }
155
156  ArrayRef<const char *> getGCCRegNames() const override;
157
158  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
159    return None;
160  }
161
162  ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
163
164  bool isSPRegName(StringRef RegName) const override {
165    return RegName.equals("esp") || RegName.equals("rsp");
166  }
167
168  bool validateCpuSupports(StringRef Name) const override;
169
170  bool validateCpuIs(StringRef Name) const override;
171
172  bool validateCPUSpecificCPUDispatch(StringRef Name) const override;
173
174  char CPUSpecificManglingCharacter(StringRef Name) const override;
175
176  void getCPUSpecificCPUDispatchFeatures(
177      StringRef Name,
178      llvm::SmallVectorImpl<StringRef> &Features) const override;
179
180  Optional<unsigned> getCPUCacheLineSize() const override;
181
182  bool validateAsmConstraint(const char *&Name,
183                             TargetInfo::ConstraintInfo &info) const override;
184
185  bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
186                                      bool &HasSizeMismatch) const override {
187    // esp and ebp are the only 32-bit registers the x86 backend can currently
188    // handle.
189    if (RegName.equals("esp") || RegName.equals("ebp")) {
190      // Check that the register size is 32-bit.
191      HasSizeMismatch = RegSize != 32;
192      return true;
193    }
194
195    return false;
196  }
197
198  bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
199                          StringRef Constraint, unsigned Size) const override;
200
201  bool validateInputSize(const llvm::StringMap<bool> &FeatureMap,
202                         StringRef Constraint, unsigned Size) const override;
203
204  virtual bool
205  checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
206    return true;
207  };
208
209  virtual bool
210  checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override {
211    return true;
212  };
213
214  virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
215                                   StringRef Constraint, unsigned Size) const;
216
217  std::string convertConstraint(const char *&Constraint) const override;
218  const char *getClobbers() const override {
219    return "~{dirflag},~{fpsr},~{flags}";
220  }
221
222  StringRef getConstraintRegister(StringRef Constraint,
223                                  StringRef Expression) const override {
224    StringRef::iterator I, E;
225    for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
226      if (isalpha(*I) || *I == '@')
227        break;
228    }
229    if (I == E)
230      return "";
231    switch (*I) {
232    // For the register constraints, return the matching register name
233    case 'a':
234      return "ax";
235    case 'b':
236      return "bx";
237    case 'c':
238      return "cx";
239    case 'd':
240      return "dx";
241    case 'S':
242      return "si";
243    case 'D':
244      return "di";
245    // In case the constraint is 'r' we need to return Expression
246    case 'r':
247      return Expression;
248    // Double letters Y<x> constraints
249    case 'Y':
250      if ((++I != E) && ((*I == '0') || (*I == 'z')))
251        return "xmm0";
252      break;
253    default:
254      break;
255    }
256    return "";
257  }
258
259  bool useFP16ConversionIntrinsics() const override {
260    return false;
261  }
262
263  void getTargetDefines(const LangOptions &Opts,
264                        MacroBuilder &Builder) const override;
265
266  void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
267                         bool Enabled) const final;
268
269  bool
270  initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
271                 StringRef CPU,
272                 const std::vector<std::string> &FeaturesVec) const override;
273
274  bool isValidFeatureName(StringRef Name) const override;
275
276  bool hasFeature(StringRef Feature) const final;
277
278  bool handleTargetFeatures(std::vector<std::string> &Features,
279                            DiagnosticsEngine &Diags) override;
280
281  StringRef getABI() const override {
282    if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
283      return "avx512";
284    if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
285      return "avx";
286    if (getTriple().getArch() == llvm::Triple::x86 &&
287        MMX3DNowLevel == NoMMX3DNow)
288      return "no-mmx";
289    return "";
290  }
291
292  bool isValidCPUName(StringRef Name) const override {
293    bool Only64Bit = getTriple().getArch() != llvm::Triple::x86;
294    return llvm::X86::parseArchX86(Name, Only64Bit) != llvm::X86::CK_None;
295  }
296
297  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
298
299  bool setCPU(const std::string &Name) override {
300    bool Only64Bit = getTriple().getArch() != llvm::Triple::x86;
301    CPU = llvm::X86::parseArchX86(Name, Only64Bit);
302    return CPU != llvm::X86::CK_None;
303  }
304
305  unsigned multiVersionSortPriority(StringRef Name) const override;
306
307  bool setFPMath(StringRef Name) override;
308
309  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
310    // Most of the non-ARM calling conventions are i386 conventions.
311    switch (CC) {
312    case CC_X86ThisCall:
313    case CC_X86FastCall:
314    case CC_X86StdCall:
315    case CC_X86VectorCall:
316    case CC_X86RegCall:
317    case CC_C:
318    case CC_PreserveMost:
319    case CC_Swift:
320    case CC_X86Pascal:
321    case CC_IntelOclBicc:
322    case CC_OpenCLKernel:
323      return CCCR_OK;
324    default:
325      return CCCR_Warning;
326    }
327  }
328
329  CallingConv getDefaultCallingConv() const override {
330    return CC_C;
331  }
332
333  bool hasSjLjLowering() const override { return true; }
334
335  void setSupportedOpenCLOpts() override {
336    getSupportedOpenCLOpts().supportAll();
337  }
338
339  uint64_t getPointerWidthV(unsigned AddrSpace) const override {
340    if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr)
341      return 32;
342    if (AddrSpace == ptr64)
343      return 64;
344    return PointerWidth;
345  }
346
347  uint64_t getPointerAlignV(unsigned AddrSpace) const override {
348    return getPointerWidthV(AddrSpace);
349  }
350};
351
352// X86-32 generic target
353class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
354public:
355  X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
356      : X86TargetInfo(Triple, Opts) {
357    DoubleAlign = LongLongAlign = 32;
358    LongDoubleWidth = 96;
359    LongDoubleAlign = 32;
360    SuitableAlign = 128;
361    resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
362                    "f80:32-n8:16:32-S128");
363    SizeType = UnsignedInt;
364    PtrDiffType = SignedInt;
365    IntPtrType = SignedInt;
366    RegParmMax = 3;
367
368    // Use fpret for all types.
369    RealTypeUsesObjCFPRet =
370        ((1 << TargetInfo::Float) | (1 << TargetInfo::Double) |
371         (1 << TargetInfo::LongDouble));
372
373    // x86-32 has atomics up to 8 bytes
374    MaxAtomicPromoteWidth = 64;
375    MaxAtomicInlineWidth = 32;
376  }
377
378  BuiltinVaListKind getBuiltinVaListKind() const override {
379    return TargetInfo::CharPtrBuiltinVaList;
380  }
381
382  int getEHDataRegisterNumber(unsigned RegNo) const override {
383    if (RegNo == 0)
384      return 0;
385    if (RegNo == 1)
386      return 2;
387    return -1;
388  }
389
390  bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
391                           StringRef Constraint, unsigned Size) const override {
392    switch (Constraint[0]) {
393    default:
394      break;
395    case 'R':
396    case 'q':
397    case 'Q':
398    case 'a':
399    case 'b':
400    case 'c':
401    case 'd':
402    case 'S':
403    case 'D':
404      return Size <= 32;
405    case 'A':
406      return Size <= 64;
407    }
408
409    return X86TargetInfo::validateOperandSize(FeatureMap, Constraint, Size);
410  }
411
412  void setMaxAtomicWidth() override {
413    if (hasFeature("cx8"))
414      MaxAtomicInlineWidth = 64;
415  }
416
417  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
418
419  bool hasExtIntType() const override { return true; }
420};
421
422class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo
423    : public NetBSDTargetInfo<X86_32TargetInfo> {
424public:
425  NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
426      : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
427
428  unsigned getFloatEvalMethod() const override {
429    unsigned Major, Minor, Micro;
430    getTriple().getOSVersion(Major, Minor, Micro);
431    // New NetBSD uses the default rounding mode.
432    if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0)
433      return X86_32TargetInfo::getFloatEvalMethod();
434    // NetBSD before 6.99.26 defaults to "double" rounding.
435    return 1;
436  }
437};
438
439class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
440    : public OpenBSDTargetInfo<X86_32TargetInfo> {
441public:
442  OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
443      : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
444    SizeType = UnsignedLong;
445    IntPtrType = SignedLong;
446    PtrDiffType = SignedLong;
447  }
448};
449
450class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
451    : public DarwinTargetInfo<X86_32TargetInfo> {
452public:
453  DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
454      : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
455    LongDoubleWidth = 128;
456    LongDoubleAlign = 128;
457    SuitableAlign = 128;
458    MaxVectorAlign = 256;
459    // The watchOS simulator uses the builtin bool type for Objective-C.
460    llvm::Triple T = llvm::Triple(Triple);
461    if (T.isWatchOS())
462      UseSignedCharForObjCBool = false;
463    SizeType = UnsignedLong;
464    IntPtrType = SignedLong;
465    resetDataLayout("e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
466                    "f80:128-n8:16:32-S128");
467    HasAlignMac68kSupport = true;
468  }
469
470  bool handleTargetFeatures(std::vector<std::string> &Features,
471                            DiagnosticsEngine &Diags) override {
472    if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
473                                                                  Diags))
474      return false;
475    // We now know the features we have: we can decide how to align vectors.
476    MaxVectorAlign =
477        hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
478    return true;
479  }
480};
481
482// x86-32 Windows target
483class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
484    : public WindowsTargetInfo<X86_32TargetInfo> {
485public:
486  WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
487      : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
488    DoubleAlign = LongLongAlign = 64;
489    bool IsWinCOFF =
490        getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
491    resetDataLayout(IsWinCOFF ? "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:"
492                                "64-i64:64-f80:32-n8:16:32-a:0:32-S32"
493                              : "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:"
494                                "64-i64:64-f80:32-n8:16:32-a:0:32-S32");
495  }
496};
497
498// x86-32 Windows Visual Studio target
499class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
500    : public WindowsX86_32TargetInfo {
501public:
502  MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
503                            const TargetOptions &Opts)
504      : WindowsX86_32TargetInfo(Triple, Opts) {
505    LongDoubleWidth = LongDoubleAlign = 64;
506    LongDoubleFormat = &llvm::APFloat::IEEEdouble();
507  }
508
509  void getTargetDefines(const LangOptions &Opts,
510                        MacroBuilder &Builder) const override {
511    WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
512    // The value of the following reflects processor type.
513    // 300=386, 400=486, 500=Pentium, 600=Blend (default)
514    // We lost the original triple, so we use the default.
515    Builder.defineMacro("_M_IX86", "600");
516  }
517};
518
519// x86-32 MinGW target
520class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
521    : public WindowsX86_32TargetInfo {
522public:
523  MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
524      : WindowsX86_32TargetInfo(Triple, Opts) {
525    HasFloat128 = true;
526  }
527
528  void getTargetDefines(const LangOptions &Opts,
529                        MacroBuilder &Builder) const override {
530    WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
531    Builder.defineMacro("_X86_");
532  }
533};
534
535// x86-32 Cygwin target
536class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
537public:
538  CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
539      : X86_32TargetInfo(Triple, Opts) {
540    this->WCharType = TargetInfo::UnsignedShort;
541    DoubleAlign = LongLongAlign = 64;
542    resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:"
543                    "32-n8:16:32-a:0:32-S32");
544  }
545
546  void getTargetDefines(const LangOptions &Opts,
547                        MacroBuilder &Builder) const override {
548    X86_32TargetInfo::getTargetDefines(Opts, Builder);
549    Builder.defineMacro("_X86_");
550    Builder.defineMacro("__CYGWIN__");
551    Builder.defineMacro("__CYGWIN32__");
552    addCygMingDefines(Opts, Builder);
553    DefineStd(Builder, "unix", Opts);
554    if (Opts.CPlusPlus)
555      Builder.defineMacro("_GNU_SOURCE");
556  }
557};
558
559// x86-32 Haiku target
560class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
561    : public HaikuTargetInfo<X86_32TargetInfo> {
562public:
563  HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
564      : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
565
566  void getTargetDefines(const LangOptions &Opts,
567                        MacroBuilder &Builder) const override {
568    HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
569    Builder.defineMacro("__INTEL__");
570  }
571};
572
573// X86-32 MCU target
574class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
575public:
576  MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
577      : X86_32TargetInfo(Triple, Opts) {
578    LongDoubleWidth = 64;
579    LongDoubleFormat = &llvm::APFloat::IEEEdouble();
580    resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-f64:"
581                    "32-f128:32-n8:16:32-a:0:32-S32");
582    WIntType = UnsignedInt;
583  }
584
585  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
586    // On MCU we support only C calling convention.
587    return CC == CC_C ? CCCR_OK : CCCR_Warning;
588  }
589
590  void getTargetDefines(const LangOptions &Opts,
591                        MacroBuilder &Builder) const override {
592    X86_32TargetInfo::getTargetDefines(Opts, Builder);
593    Builder.defineMacro("__iamcu");
594    Builder.defineMacro("__iamcu__");
595  }
596
597  bool allowsLargerPreferedTypeAlignment() const override { return false; }
598};
599
600// x86-32 RTEMS target
601class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
602public:
603  RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
604      : X86_32TargetInfo(Triple, Opts) {
605    SizeType = UnsignedLong;
606    IntPtrType = SignedLong;
607    PtrDiffType = SignedLong;
608  }
609
610  void getTargetDefines(const LangOptions &Opts,
611                        MacroBuilder &Builder) const override {
612    X86_32TargetInfo::getTargetDefines(Opts, Builder);
613    Builder.defineMacro("__INTEL__");
614    Builder.defineMacro("__rtems__");
615  }
616};
617
618// x86-64 generic target
619class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
620public:
621  X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
622      : X86TargetInfo(Triple, Opts) {
623    const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
624    bool IsWinCOFF =
625        getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
626    LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
627    LongDoubleWidth = 128;
628    LongDoubleAlign = 128;
629    LargeArrayMinWidth = 128;
630    LargeArrayAlign = 128;
631    SuitableAlign = 128;
632    SizeType = IsX32 ? UnsignedInt : UnsignedLong;
633    PtrDiffType = IsX32 ? SignedInt : SignedLong;
634    IntPtrType = IsX32 ? SignedInt : SignedLong;
635    IntMaxType = IsX32 ? SignedLongLong : SignedLong;
636    Int64Type = IsX32 ? SignedLongLong : SignedLong;
637    RegParmMax = 6;
638
639    // Pointers are 32-bit in x32.
640    resetDataLayout(IsX32 ? "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-"
641                            "i64:64-f80:128-n8:16:32:64-S128"
642                          : IsWinCOFF ? "e-m:w-p270:32:32-p271:32:32-p272:64:"
643                                        "64-i64:64-f80:128-n8:16:32:64-S128"
644                                      : "e-m:e-p270:32:32-p271:32:32-p272:64:"
645                                        "64-i64:64-f80:128-n8:16:32:64-S128");
646
647    // Use fpret only for long double.
648    RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
649
650    // Use fp2ret for _Complex long double.
651    ComplexLongDoubleUsesFP2Ret = true;
652
653    // Make __builtin_ms_va_list available.
654    HasBuiltinMSVaList = true;
655
656    // x86-64 has atomics up to 16 bytes.
657    MaxAtomicPromoteWidth = 128;
658    MaxAtomicInlineWidth = 64;
659  }
660
661  BuiltinVaListKind getBuiltinVaListKind() const override {
662    return TargetInfo::X86_64ABIBuiltinVaList;
663  }
664
665  int getEHDataRegisterNumber(unsigned RegNo) const override {
666    if (RegNo == 0)
667      return 0;
668    if (RegNo == 1)
669      return 1;
670    return -1;
671  }
672
673  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
674    switch (CC) {
675    case CC_C:
676    case CC_Swift:
677    case CC_X86VectorCall:
678    case CC_IntelOclBicc:
679    case CC_Win64:
680    case CC_PreserveMost:
681    case CC_PreserveAll:
682    case CC_X86RegCall:
683    case CC_OpenCLKernel:
684      return CCCR_OK;
685    default:
686      return CCCR_Warning;
687    }
688  }
689
690  CallingConv getDefaultCallingConv() const override {
691    return CC_C;
692  }
693
694  // for x32 we need it here explicitly
695  bool hasInt128Type() const override { return true; }
696
697  unsigned getUnwindWordWidth() const override { return 64; }
698
699  unsigned getRegisterWidth() const override { return 64; }
700
701  bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
702                                      bool &HasSizeMismatch) const override {
703    // rsp and rbp are the only 64-bit registers the x86 backend can currently
704    // handle.
705    if (RegName.equals("rsp") || RegName.equals("rbp")) {
706      // Check that the register size is 64-bit.
707      HasSizeMismatch = RegSize != 64;
708      return true;
709    }
710
711    // Check if the register is a 32-bit register the backend can handle.
712    return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
713                                                         HasSizeMismatch);
714  }
715
716  void setMaxAtomicWidth() override {
717    if (hasFeature("cx16"))
718      MaxAtomicInlineWidth = 128;
719  }
720
721  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
722
723  bool hasExtIntType() const override { return true; }
724};
725
726// x86-64 Windows target
727class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
728    : public WindowsTargetInfo<X86_64TargetInfo> {
729public:
730  WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
731      : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
732    LongWidth = LongAlign = 32;
733    DoubleAlign = LongLongAlign = 64;
734    IntMaxType = SignedLongLong;
735    Int64Type = SignedLongLong;
736    SizeType = UnsignedLongLong;
737    PtrDiffType = SignedLongLong;
738    IntPtrType = SignedLongLong;
739  }
740
741  BuiltinVaListKind getBuiltinVaListKind() const override {
742    return TargetInfo::CharPtrBuiltinVaList;
743  }
744
745  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
746    switch (CC) {
747    case CC_X86StdCall:
748    case CC_X86ThisCall:
749    case CC_X86FastCall:
750      return CCCR_Ignore;
751    case CC_C:
752    case CC_X86VectorCall:
753    case CC_IntelOclBicc:
754    case CC_PreserveMost:
755    case CC_PreserveAll:
756    case CC_X86_64SysV:
757    case CC_Swift:
758    case CC_X86RegCall:
759    case CC_OpenCLKernel:
760      return CCCR_OK;
761    default:
762      return CCCR_Warning;
763    }
764  }
765};
766
767// x86-64 Windows Visual Studio target
768class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
769    : public WindowsX86_64TargetInfo {
770public:
771  MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
772                            const TargetOptions &Opts)
773      : WindowsX86_64TargetInfo(Triple, Opts) {
774    LongDoubleWidth = LongDoubleAlign = 64;
775    LongDoubleFormat = &llvm::APFloat::IEEEdouble();
776  }
777
778  void getTargetDefines(const LangOptions &Opts,
779                        MacroBuilder &Builder) const override {
780    WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
781    Builder.defineMacro("_M_X64", "100");
782    Builder.defineMacro("_M_AMD64", "100");
783  }
784
785  TargetInfo::CallingConvKind
786  getCallingConvKind(bool ClangABICompat4) const override {
787    return CCK_MicrosoftWin64;
788  }
789};
790
791// x86-64 MinGW target
792class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
793    : public WindowsX86_64TargetInfo {
794public:
795  MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
796      : WindowsX86_64TargetInfo(Triple, Opts) {
797    // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
798    // with x86 FP ops. Weird.
799    LongDoubleWidth = LongDoubleAlign = 128;
800    LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
801    HasFloat128 = true;
802  }
803};
804
805// x86-64 Cygwin target
806class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
807public:
808  CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
809      : X86_64TargetInfo(Triple, Opts) {
810    this->WCharType = TargetInfo::UnsignedShort;
811    TLSSupported = false;
812  }
813
814  void getTargetDefines(const LangOptions &Opts,
815                        MacroBuilder &Builder) const override {
816    X86_64TargetInfo::getTargetDefines(Opts, Builder);
817    Builder.defineMacro("__x86_64__");
818    Builder.defineMacro("__CYGWIN__");
819    Builder.defineMacro("__CYGWIN64__");
820    addCygMingDefines(Opts, Builder);
821    DefineStd(Builder, "unix", Opts);
822    if (Opts.CPlusPlus)
823      Builder.defineMacro("_GNU_SOURCE");
824  }
825};
826
827class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
828    : public DarwinTargetInfo<X86_64TargetInfo> {
829public:
830  DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
831      : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
832    Int64Type = SignedLongLong;
833    // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
834    llvm::Triple T = llvm::Triple(Triple);
835    if (T.isiOS())
836      UseSignedCharForObjCBool = false;
837    resetDataLayout("e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:"
838                    "16:32:64-S128");
839  }
840
841  bool handleTargetFeatures(std::vector<std::string> &Features,
842                            DiagnosticsEngine &Diags) override {
843    if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
844                                                                  Diags))
845      return false;
846    // We now know the features we have: we can decide how to align vectors.
847    MaxVectorAlign =
848        hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
849    return true;
850  }
851};
852
853class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
854    : public OpenBSDTargetInfo<X86_64TargetInfo> {
855public:
856  OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
857      : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
858    IntMaxType = SignedLongLong;
859    Int64Type = SignedLongLong;
860  }
861};
862
863// x86_32 Android target
864class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
865    : public LinuxTargetInfo<X86_32TargetInfo> {
866public:
867  AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
868      : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
869    SuitableAlign = 32;
870    LongDoubleWidth = 64;
871    LongDoubleFormat = &llvm::APFloat::IEEEdouble();
872  }
873};
874
875// x86_64 Android target
876class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
877    : public LinuxTargetInfo<X86_64TargetInfo> {
878public:
879  AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
880      : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
881    LongDoubleFormat = &llvm::APFloat::IEEEquad();
882  }
883};
884} // namespace targets
885} // namespace clang
886#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
887