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