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