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