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