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