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