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