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