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