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