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