xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/X86.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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   bool HasMMX = false;
71   enum XOPEnum { NoXOP, SSE4A, FMA4, XOP } XOPLevel = NoXOP;
72   enum AddrSpace { ptr32_sptr = 270, ptr32_uptr = 271, ptr64 = 272 };
73 
74   bool HasAES = false;
75   bool HasVAES = false;
76   bool HasPCLMUL = false;
77   bool HasVPCLMULQDQ = false;
78   bool HasGFNI = false;
79   bool HasLZCNT = false;
80   bool HasRDRND = false;
81   bool HasFSGSBASE = false;
82   bool HasBMI = false;
83   bool HasBMI2 = false;
84   bool HasPOPCNT = false;
85   bool HasRTM = false;
86   bool HasPRFCHW = false;
87   bool HasRDSEED = false;
88   bool HasADX = false;
89   bool HasTBM = false;
90   bool HasLWP = false;
91   bool HasFMA = false;
92   bool HasF16C = false;
93   bool HasAVX10_1 = false;
94   bool HasAVX10_1_512 = false;
95   bool HasEVEX512 = false;
96   bool HasAVX512CD = false;
97   bool HasAVX512VPOPCNTDQ = false;
98   bool HasAVX512VNNI = false;
99   bool HasAVX512FP16 = false;
100   bool HasAVX512BF16 = false;
101   bool HasAVX512DQ = false;
102   bool HasAVX512BITALG = false;
103   bool HasAVX512BW = false;
104   bool HasAVX512VL = false;
105   bool HasAVX512VBMI = false;
106   bool HasAVX512VBMI2 = false;
107   bool HasAVXIFMA = false;
108   bool HasAVX512IFMA = false;
109   bool HasAVX512VP2INTERSECT = false;
110   bool HasSHA = false;
111   bool HasSHA512 = false;
112   bool HasSHSTK = false;
113   bool HasSM3 = false;
114   bool HasSGX = false;
115   bool HasSM4 = false;
116   bool HasCX8 = false;
117   bool HasCX16 = false;
118   bool HasFXSR = false;
119   bool HasXSAVE = false;
120   bool HasXSAVEOPT = false;
121   bool HasXSAVEC = false;
122   bool HasXSAVES = false;
123   bool HasMWAITX = false;
124   bool HasCLZERO = false;
125   bool HasCLDEMOTE = false;
126   bool HasPCONFIG = false;
127   bool HasPKU = false;
128   bool HasCLFLUSHOPT = false;
129   bool HasCLWB = false;
130   bool HasMOVBE = false;
131   bool HasPREFETCHI = false;
132   bool HasRDPID = false;
133   bool HasRDPRU = false;
134   bool HasRetpolineExternalThunk = false;
135   bool HasLAHFSAHF = false;
136   bool HasWBNOINVD = false;
137   bool HasWAITPKG = false;
138   bool HasMOVDIRI = false;
139   bool HasMOVDIR64B = false;
140   bool HasPTWRITE = false;
141   bool HasINVPCID = false;
142   bool HasENQCMD = false;
143   bool HasAVXVNNIINT16 = false;
144   bool HasAMXFP16 = false;
145   bool HasCMPCCXADD = false;
146   bool HasRAOINT = false;
147   bool HasAVXVNNIINT8 = false;
148   bool HasAVXNECONVERT = false;
149   bool HasKL = false;      // For key locker
150   bool HasWIDEKL = false; // For wide key locker
151   bool HasHRESET = false;
152   bool HasAVXVNNI = false;
153   bool HasAMXTILE = false;
154   bool HasAMXINT8 = false;
155   bool HasAMXBF16 = false;
156   bool HasAMXCOMPLEX = false;
157   bool HasSERIALIZE = false;
158   bool HasTSXLDTRK = false;
159   bool HasUSERMSR = false;
160   bool HasUINTR = false;
161   bool HasCRC32 = false;
162   bool HasX87 = false;
163   bool HasEGPR = false;
164   bool HasPush2Pop2 = false;
165   bool HasPPX = false;
166   bool HasNDD = false;
167   bool HasCCMP = false;
168   bool HasNF = false;
169   bool HasCF = false;
170   bool HasZU = false;
171   bool HasInlineAsmUseGPR32 = false;
172   bool HasBranchHint = false;
173 
174 protected:
175   llvm::X86::CPUKind CPU = llvm::X86::CK_None;
176 
177   enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
178 
179 public:
X86TargetInfo(const llvm::Triple & Triple,const TargetOptions &)180   X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
181       : TargetInfo(Triple) {
182     BFloat16Width = BFloat16Align = 16;
183     BFloat16Format = &llvm::APFloat::BFloat();
184     LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
185     AddrSpaceMap = &X86AddrSpaceMap;
186     HasStrictFP = true;
187     HasUnalignedAccess = true;
188 
189     bool IsWinCOFF =
190         getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
191     if (IsWinCOFF)
192       MaxVectorAlign = MaxTLSAlign = 8192u * getCharWidth();
193   }
194 
getLongDoubleMangling()195   const char *getLongDoubleMangling() const override {
196     return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e";
197   }
198 
getFPEvalMethod()199   LangOptions::FPEvalMethodKind getFPEvalMethod() const override {
200     // X87 evaluates with 80 bits "long double" precision.
201     return SSELevel == NoSSE ? LangOptions::FPEvalMethodKind::FEM_Extended
202                              : LangOptions::FPEvalMethodKind::FEM_Source;
203   }
204 
205   // EvalMethod `source` is not supported for targets with `NoSSE` feature.
supportSourceEvalMethod()206   bool supportSourceEvalMethod() const override { return SSELevel > NoSSE; }
207 
208   ArrayRef<const char *> getGCCRegNames() const override;
209 
getGCCRegAliases()210   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
211     return std::nullopt;
212   }
213 
214   ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
215 
isSPRegName(StringRef RegName)216   bool isSPRegName(StringRef RegName) const override {
217     return RegName == "esp" || RegName == "rsp";
218   }
219 
supportsCpuSupports()220   bool supportsCpuSupports() const override { return true; }
supportsCpuIs()221   bool supportsCpuIs() const override { return true; }
supportsCpuInit()222   bool supportsCpuInit() const override { return true; }
223 
224   bool validateCpuSupports(StringRef FeatureStr) const override;
225 
226   bool validateCpuIs(StringRef FeatureStr) const override;
227 
228   bool validateCPUSpecificCPUDispatch(StringRef Name) const override;
229 
230   char CPUSpecificManglingCharacter(StringRef Name) const override;
231 
232   void getCPUSpecificCPUDispatchFeatures(
233       StringRef Name,
234       llvm::SmallVectorImpl<StringRef> &Features) const override;
235 
236   std::optional<unsigned> getCPUCacheLineSize() const override;
237 
238   bool validateAsmConstraint(const char *&Name,
239                              TargetInfo::ConstraintInfo &info) const override;
240 
validateGlobalRegisterVariable(StringRef RegName,unsigned RegSize,bool & HasSizeMismatch)241   bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
242                                       bool &HasSizeMismatch) const override {
243     // esp and ebp are the only 32-bit registers the x86 backend can currently
244     // handle.
245     if (RegName == "esp" || RegName == "ebp") {
246       // Check that the register size is 32-bit.
247       HasSizeMismatch = RegSize != 32;
248       return true;
249     }
250 
251     return false;
252   }
253 
254   bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
255                           StringRef Constraint, unsigned Size) const override;
256 
257   bool validateInputSize(const llvm::StringMap<bool> &FeatureMap,
258                          StringRef Constraint, unsigned Size) const override;
259 
260   bool
checkCFProtectionReturnSupported(DiagnosticsEngine & Diags)261   checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
262     if (CPU == llvm::X86::CK_None || CPU >= llvm::X86::CK_PentiumPro)
263       return true;
264     return TargetInfo::checkCFProtectionReturnSupported(Diags);
265   };
266 
267   bool
checkCFProtectionBranchSupported(DiagnosticsEngine & Diags)268   checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override {
269     if (CPU == llvm::X86::CK_None || CPU >= llvm::X86::CK_PentiumPro)
270       return true;
271     return TargetInfo::checkCFProtectionBranchSupported(Diags);
272   };
273 
274   virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
275                                    StringRef Constraint, unsigned Size) const;
276 
277   std::string convertConstraint(const char *&Constraint) const override;
getClobbers()278   std::string_view getClobbers() const override {
279     return "~{dirflag},~{fpsr},~{flags}";
280   }
281 
getConstraintRegister(StringRef Constraint,StringRef Expression)282   StringRef getConstraintRegister(StringRef Constraint,
283                                   StringRef Expression) const override {
284     StringRef::iterator I, E;
285     for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
286       if (isalpha(*I) || *I == '@')
287         break;
288     }
289     if (I == E)
290       return "";
291     switch (*I) {
292     // For the register constraints, return the matching register name
293     case 'a':
294       return "ax";
295     case 'b':
296       return "bx";
297     case 'c':
298       return "cx";
299     case 'd':
300       return "dx";
301     case 'S':
302       return "si";
303     case 'D':
304       return "di";
305     // In case the constraint is 'r' we need to return Expression
306     case 'r':
307       return Expression;
308     // Double letters Y<x> constraints
309     case 'Y':
310       if ((++I != E) && ((*I == '0') || (*I == 'z')))
311         return "xmm0";
312       break;
313     default:
314       break;
315     }
316     return "";
317   }
318 
useFP16ConversionIntrinsics()319   bool useFP16ConversionIntrinsics() const override {
320     return false;
321   }
322 
323   void getTargetDefines(const LangOptions &Opts,
324                         MacroBuilder &Builder) const override;
325 
326   void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
327                          bool Enabled) const final;
328 
329   bool
330   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
331                  StringRef CPU,
332                  const std::vector<std::string> &FeaturesVec) const override;
333 
334   bool isValidFeatureName(StringRef Name) const override;
335 
336   bool hasFeature(StringRef Feature) const final;
337 
338   bool handleTargetFeatures(std::vector<std::string> &Features,
339                             DiagnosticsEngine &Diags) override;
340 
getABI()341   StringRef getABI() const override {
342     if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
343       return "avx512";
344     if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
345       return "avx";
346     if (getTriple().getArch() == llvm::Triple::x86 && !HasMMX)
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 };
517 
518 class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
519     : public OpenBSDTargetInfo<X86_32TargetInfo> {
520 public:
OpenBSDI386TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)521   OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
522       : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
523     SizeType = UnsignedLong;
524     IntPtrType = SignedLong;
525     PtrDiffType = SignedLong;
526   }
527 };
528 
529 class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
530     : public DarwinTargetInfo<X86_32TargetInfo> {
531 public:
DarwinI386TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)532   DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
533       : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
534     LongDoubleWidth = 128;
535     LongDoubleAlign = 128;
536     SuitableAlign = 128;
537     MaxVectorAlign = 256;
538     // The watchOS simulator uses the builtin bool type for Objective-C.
539     llvm::Triple T = llvm::Triple(Triple);
540     if (T.isWatchOS())
541       UseSignedCharForObjCBool = false;
542     SizeType = UnsignedLong;
543     IntPtrType = SignedLong;
544     resetDataLayout("e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-"
545                     "f64:32:64-f80:128-n8:16:32-S128",
546                     "_");
547     HasAlignMac68kSupport = true;
548   }
549 
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)550   bool handleTargetFeatures(std::vector<std::string> &Features,
551                             DiagnosticsEngine &Diags) override {
552     if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
553                                                                   Diags))
554       return false;
555     // We now know the features we have: we can decide how to align vectors.
556     MaxVectorAlign =
557         hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
558     return true;
559   }
560 };
561 
562 // x86-32 Windows target
563 class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
564     : public WindowsTargetInfo<X86_32TargetInfo> {
565 public:
WindowsX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)566   WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
567       : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
568     DoubleAlign = LongLongAlign = 64;
569     bool IsWinCOFF =
570         getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
571     bool IsMSVC = getTriple().isWindowsMSVCEnvironment();
572     std::string Layout = IsWinCOFF ? "e-m:x" : "e-m:e";
573     Layout += "-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-";
574     Layout += IsMSVC ? "f80:128" : "f80:32";
575     Layout += "-n8:16:32-a:0:32-S32";
576     resetDataLayout(Layout, IsWinCOFF ? "_" : "");
577   }
578 };
579 
580 // x86-32 Windows Visual Studio target
581 class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
582     : public WindowsX86_32TargetInfo {
583 public:
MicrosoftX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)584   MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
585                             const TargetOptions &Opts)
586       : WindowsX86_32TargetInfo(Triple, Opts) {
587     LongDoubleWidth = LongDoubleAlign = 64;
588     LongDoubleFormat = &llvm::APFloat::IEEEdouble();
589   }
590 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)591   void getTargetDefines(const LangOptions &Opts,
592                         MacroBuilder &Builder) const override {
593     WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
594     // The value of the following reflects processor type.
595     // 300=386, 400=486, 500=Pentium, 600=Blend (default)
596     // We lost the original triple, so we use the default.
597     Builder.defineMacro("_M_IX86", "600");
598   }
599 };
600 
601 // x86-32 MinGW target
602 class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
603     : public WindowsX86_32TargetInfo {
604 public:
MinGWX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)605   MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
606       : WindowsX86_32TargetInfo(Triple, Opts) {
607     HasFloat128 = true;
608   }
609 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)610   void getTargetDefines(const LangOptions &Opts,
611                         MacroBuilder &Builder) const override {
612     WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
613     Builder.defineMacro("_X86_");
614   }
615 };
616 
617 // x86-32 Cygwin target
618 class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
619 public:
CygwinX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)620   CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
621       : X86_32TargetInfo(Triple, Opts) {
622     this->WCharType = TargetInfo::UnsignedShort;
623     DoubleAlign = LongLongAlign = 64;
624     resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-"
625                     "i128:128-f80:32-n8:16:32-a:0:32-S32",
626                     "_");
627   }
628 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)629   void getTargetDefines(const LangOptions &Opts,
630                         MacroBuilder &Builder) const override {
631     X86_32TargetInfo::getTargetDefines(Opts, Builder);
632     Builder.defineMacro("_X86_");
633     Builder.defineMacro("__CYGWIN__");
634     Builder.defineMacro("__CYGWIN32__");
635     addCygMingDefines(Opts, Builder);
636     DefineStd(Builder, "unix", Opts);
637     if (Opts.CPlusPlus)
638       Builder.defineMacro("_GNU_SOURCE");
639   }
640 };
641 
642 // x86-32 Haiku target
643 class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
644     : public HaikuTargetInfo<X86_32TargetInfo> {
645 public:
HaikuX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)646   HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
647       : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
648 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)649   void getTargetDefines(const LangOptions &Opts,
650                         MacroBuilder &Builder) const override {
651     HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
652     Builder.defineMacro("__INTEL__");
653   }
654 };
655 
656 // X86-32 MCU target
657 class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
658 public:
MCUX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)659   MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
660       : X86_32TargetInfo(Triple, Opts) {
661     LongDoubleWidth = 64;
662     DefaultAlignForAttributeAligned = 32;
663     LongDoubleFormat = &llvm::APFloat::IEEEdouble();
664     resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-"
665                     "f64:32-f128:32-n8:16:32-a:0:32-S32");
666     WIntType = UnsignedInt;
667   }
668 
checkCallingConvention(CallingConv CC)669   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
670     // On MCU we support only C calling convention.
671     return CC == CC_C ? CCCR_OK : CCCR_Warning;
672   }
673 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)674   void getTargetDefines(const LangOptions &Opts,
675                         MacroBuilder &Builder) const override {
676     X86_32TargetInfo::getTargetDefines(Opts, Builder);
677     Builder.defineMacro("__iamcu");
678     Builder.defineMacro("__iamcu__");
679   }
680 
allowsLargerPreferedTypeAlignment()681   bool allowsLargerPreferedTypeAlignment() const override { return false; }
682 };
683 
684 // x86-32 RTEMS target
685 class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
686 public:
RTEMSX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)687   RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
688       : X86_32TargetInfo(Triple, Opts) {
689     SizeType = UnsignedLong;
690     IntPtrType = SignedLong;
691     PtrDiffType = SignedLong;
692   }
693 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)694   void getTargetDefines(const LangOptions &Opts,
695                         MacroBuilder &Builder) const override {
696     X86_32TargetInfo::getTargetDefines(Opts, Builder);
697     Builder.defineMacro("__INTEL__");
698     Builder.defineMacro("__rtems__");
699   }
700 };
701 
702 // x86-64 generic target
703 class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
704 public:
X86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)705   X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
706       : X86TargetInfo(Triple, Opts) {
707     const bool IsX32 = getTriple().isX32();
708     bool IsWinCOFF =
709         getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
710     LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
711     LongDoubleWidth = 128;
712     LongDoubleAlign = 128;
713     LargeArrayMinWidth = 128;
714     LargeArrayAlign = 128;
715     SuitableAlign = 128;
716     SizeType = IsX32 ? UnsignedInt : UnsignedLong;
717     PtrDiffType = IsX32 ? SignedInt : SignedLong;
718     IntPtrType = IsX32 ? SignedInt : SignedLong;
719     IntMaxType = IsX32 ? SignedLongLong : SignedLong;
720     Int64Type = IsX32 ? SignedLongLong : SignedLong;
721     RegParmMax = 6;
722 
723     // Pointers are 32-bit in x32.
724     resetDataLayout(IsX32 ? "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-"
725                             "i64:64-i128:128-f80:128-n8:16:32:64-S128"
726                     : IsWinCOFF ? "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:"
727                                   "64-i128:128-f80:128-n8:16:32:64-S128"
728                                 : "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:"
729                                   "64-i128:128-f80:128-n8:16:32:64-S128");
730 
731     // Use fpret only for long double.
732     RealTypeUsesObjCFPRetMask = (unsigned)FloatModeKind::LongDouble;
733 
734     // Use fp2ret for _Complex long double.
735     ComplexLongDoubleUsesFP2Ret = true;
736 
737     // Make __builtin_ms_va_list available.
738     HasBuiltinMSVaList = true;
739 
740     // x86-64 has atomics up to 16 bytes.
741     MaxAtomicPromoteWidth = 128;
742     MaxAtomicInlineWidth = 64;
743   }
744 
getBuiltinVaListKind()745   BuiltinVaListKind getBuiltinVaListKind() const override {
746     return TargetInfo::X86_64ABIBuiltinVaList;
747   }
748 
getEHDataRegisterNumber(unsigned RegNo)749   int getEHDataRegisterNumber(unsigned RegNo) const override {
750     if (RegNo == 0)
751       return 0;
752     if (RegNo == 1)
753       return 1;
754     return -1;
755   }
756 
checkCallingConvention(CallingConv CC)757   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
758     switch (CC) {
759     case CC_C:
760     case CC_Swift:
761     case CC_SwiftAsync:
762     case CC_X86VectorCall:
763     case CC_IntelOclBicc:
764     case CC_Win64:
765     case CC_PreserveMost:
766     case CC_PreserveAll:
767     case CC_PreserveNone:
768     case CC_X86RegCall:
769     case CC_OpenCLKernel:
770       return CCCR_OK;
771     default:
772       return CCCR_Warning;
773     }
774   }
775 
getDefaultCallingConv()776   CallingConv getDefaultCallingConv() const override {
777     return CC_C;
778   }
779 
780   // for x32 we need it here explicitly
hasInt128Type()781   bool hasInt128Type() const override { return true; }
782 
getUnwindWordWidth()783   unsigned getUnwindWordWidth() const override { return 64; }
784 
getRegisterWidth()785   unsigned getRegisterWidth() const override { return 64; }
786 
validateGlobalRegisterVariable(StringRef RegName,unsigned RegSize,bool & HasSizeMismatch)787   bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
788                                       bool &HasSizeMismatch) const override {
789     // rsp and rbp are the only 64-bit registers the x86 backend can currently
790     // handle.
791     if (RegName == "rsp" || RegName == "rbp") {
792       // Check that the register size is 64-bit.
793       HasSizeMismatch = RegSize != 64;
794       return true;
795     }
796 
797     // Check if the register is a 32-bit register the backend can handle.
798     return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
799                                                          HasSizeMismatch);
800   }
801 
setMaxAtomicWidth()802   void setMaxAtomicWidth() override {
803     if (hasFeature("cx16"))
804       MaxAtomicInlineWidth = 128;
805   }
806 
807   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
808 
hasBitIntType()809   bool hasBitIntType() const override { return true; }
getMaxBitIntWidth()810   size_t getMaxBitIntWidth() const override {
811     return llvm::IntegerType::MAX_INT_BITS;
812   }
813 };
814 
815 // x86-64 Windows target
816 class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
817     : public WindowsTargetInfo<X86_64TargetInfo> {
818 public:
WindowsX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)819   WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
820       : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
821     LongWidth = LongAlign = 32;
822     DoubleAlign = LongLongAlign = 64;
823     IntMaxType = SignedLongLong;
824     Int64Type = SignedLongLong;
825     SizeType = UnsignedLongLong;
826     PtrDiffType = SignedLongLong;
827     IntPtrType = SignedLongLong;
828   }
829 
getBuiltinVaListKind()830   BuiltinVaListKind getBuiltinVaListKind() const override {
831     return TargetInfo::CharPtrBuiltinVaList;
832   }
833 
checkCallingConvention(CallingConv CC)834   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
835     switch (CC) {
836     case CC_X86StdCall:
837     case CC_X86ThisCall:
838     case CC_X86FastCall:
839       return CCCR_Ignore;
840     case CC_C:
841     case CC_X86VectorCall:
842     case CC_IntelOclBicc:
843     case CC_PreserveMost:
844     case CC_PreserveAll:
845     case CC_PreserveNone:
846     case CC_X86_64SysV:
847     case CC_Swift:
848     case CC_SwiftAsync:
849     case CC_X86RegCall:
850     case CC_OpenCLKernel:
851       return CCCR_OK;
852     default:
853       return CCCR_Warning;
854     }
855   }
856 };
857 
858 // x86-64 Windows Visual Studio target
859 class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
860     : public WindowsX86_64TargetInfo {
861 public:
MicrosoftX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)862   MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
863                             const TargetOptions &Opts)
864       : WindowsX86_64TargetInfo(Triple, Opts) {
865     LongDoubleWidth = LongDoubleAlign = 64;
866     LongDoubleFormat = &llvm::APFloat::IEEEdouble();
867   }
868 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)869   void getTargetDefines(const LangOptions &Opts,
870                         MacroBuilder &Builder) const override {
871     WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
872     Builder.defineMacro("_M_X64", "100");
873     Builder.defineMacro("_M_AMD64", "100");
874   }
875 
876   TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4)877   getCallingConvKind(bool ClangABICompat4) const override {
878     return CCK_MicrosoftWin64;
879   }
880 };
881 
882 // x86-64 MinGW target
883 class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
884     : public WindowsX86_64TargetInfo {
885 public:
MinGWX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)886   MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
887       : WindowsX86_64TargetInfo(Triple, Opts) {
888     // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
889     // with x86 FP ops. Weird.
890     LongDoubleWidth = LongDoubleAlign = 128;
891     LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
892     HasFloat128 = true;
893   }
894 };
895 
896 // x86-64 Cygwin target
897 class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
898 public:
CygwinX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)899   CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
900       : X86_64TargetInfo(Triple, Opts) {
901     this->WCharType = TargetInfo::UnsignedShort;
902     TLSSupported = false;
903   }
904 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder)905   void getTargetDefines(const LangOptions &Opts,
906                         MacroBuilder &Builder) const override {
907     X86_64TargetInfo::getTargetDefines(Opts, Builder);
908     Builder.defineMacro("__x86_64__");
909     Builder.defineMacro("__CYGWIN__");
910     Builder.defineMacro("__CYGWIN64__");
911     addCygMingDefines(Opts, Builder);
912     DefineStd(Builder, "unix", Opts);
913     if (Opts.CPlusPlus)
914       Builder.defineMacro("_GNU_SOURCE");
915   }
916 };
917 
918 class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
919     : public DarwinTargetInfo<X86_64TargetInfo> {
920 public:
DarwinX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)921   DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
922       : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
923     Int64Type = SignedLongLong;
924     // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
925     llvm::Triple T = llvm::Triple(Triple);
926     if (T.isiOS())
927       UseSignedCharForObjCBool = false;
928     resetDataLayout("e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-"
929                     "f80:128-n8:16:32:64-S128",
930                     "_");
931   }
932 
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)933   bool handleTargetFeatures(std::vector<std::string> &Features,
934                             DiagnosticsEngine &Diags) override {
935     if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
936                                                                   Diags))
937       return false;
938     // We now know the features we have: we can decide how to align vectors.
939     MaxVectorAlign =
940         hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
941     return true;
942   }
943 };
944 
945 class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
946     : public OpenBSDTargetInfo<X86_64TargetInfo> {
947 public:
OpenBSDX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)948   OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
949       : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
950     IntMaxType = SignedLongLong;
951     Int64Type = SignedLongLong;
952   }
953 };
954 
955 // x86_32 Android target
956 class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
957     : public LinuxTargetInfo<X86_32TargetInfo> {
958 public:
AndroidX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)959   AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
960       : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
961     SuitableAlign = 32;
962     LongDoubleWidth = 64;
963     LongDoubleFormat = &llvm::APFloat::IEEEdouble();
964   }
965 };
966 
967 // x86_64 Android target
968 class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
969     : public LinuxTargetInfo<X86_64TargetInfo> {
970 public:
AndroidX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)971   AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
972       : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
973     LongDoubleFormat = &llvm::APFloat::IEEEquad();
974   }
975 };
976 
977 // x86_32 OHOS target
978 class LLVM_LIBRARY_VISIBILITY OHOSX86_32TargetInfo
979     : public OHOSTargetInfo<X86_32TargetInfo> {
980 public:
OHOSX86_32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)981   OHOSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
982       : OHOSTargetInfo<X86_32TargetInfo>(Triple, Opts) {
983     SuitableAlign = 32;
984     LongDoubleWidth = 64;
985     LongDoubleFormat = &llvm::APFloat::IEEEdouble();
986   }
987 };
988 
989 // x86_64 OHOS target
990 class LLVM_LIBRARY_VISIBILITY OHOSX86_64TargetInfo
991     : public OHOSTargetInfo<X86_64TargetInfo> {
992 public:
OHOSX86_64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)993   OHOSX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
994       : OHOSTargetInfo<X86_64TargetInfo>(Triple, Opts) {
995     LongDoubleFormat = &llvm::APFloat::IEEEquad();
996   }
997 };
998 } // namespace targets
999 } // namespace clang
1000 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
1001