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