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