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