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