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