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