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