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