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