xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/X86.h (revision fe815331bb40604ba31312acf7e4619674631777)
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 
23 namespace clang {
24 namespace targets {
25 
26 static 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.
43 class 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 
134 protected:
135   llvm::X86::CPUKind CPU = llvm::X86::CK_None;
136 
137   enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
138 
139 public:
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
353 class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
354 public:
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 
422 class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo
423     : public NetBSDTargetInfo<X86_32TargetInfo> {
424 public:
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 
439 class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
440     : public OpenBSDTargetInfo<X86_32TargetInfo> {
441 public:
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 
450 class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
451     : public DarwinTargetInfo<X86_32TargetInfo> {
452 public:
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
483 class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
484     : public WindowsTargetInfo<X86_32TargetInfo> {
485 public:
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
499 class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
500     : public WindowsX86_32TargetInfo {
501 public:
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
520 class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
521     : public WindowsX86_32TargetInfo {
522 public:
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
536 class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
537 public:
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
560 class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
561     : public HaikuTargetInfo<X86_32TargetInfo> {
562 public:
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
574 class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
575 public:
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
601 class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
602 public:
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
619 class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
620 public:
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
727 class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
728     : public WindowsTargetInfo<X86_64TargetInfo> {
729 public:
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
768 class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
769     : public WindowsX86_64TargetInfo {
770 public:
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
792 class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
793     : public WindowsX86_64TargetInfo {
794 public:
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
806 class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
807 public:
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 
827 class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
828     : public DarwinTargetInfo<X86_64TargetInfo> {
829 public:
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 
853 class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
854     : public OpenBSDTargetInfo<X86_64TargetInfo> {
855 public:
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
864 class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
865     : public LinuxTargetInfo<X86_32TargetInfo> {
866 public:
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
876 class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
877     : public LinuxTargetInfo<X86_64TargetInfo> {
878 public:
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