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 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
174protected:
175 llvm::X86::CPUKind CPU = llvm::X86::CK_None;
176
177 enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
178
179public:
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
195 const char *getLongDoubleMangling() const override {
196 return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e";
197 }
198
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.
206 bool supportSourceEvalMethod() const override { return SSELevel > NoSSE; }
207
208 ArrayRef<const char *> getGCCRegNames() const override;
209
210 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
211 return std::nullopt;
212 }
213
214 ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
215
216 bool isSPRegName(StringRef RegName) const override {
217 return RegName == "esp" || RegName == "rsp";
218 }
219
220 bool supportsCpuSupports() const override { return true; }
221 bool supportsCpuIs() const override { return true; }
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
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
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
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;
278 std::string_view getClobbers() const override {
279 return "~{dirflag},~{fpsr},~{flags}";
280 }
281
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
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
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
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(CPU: 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(CPU: 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(CPU: 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(AS: 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(DL: 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 UserLabelPrefix: 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(Feature: "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
518class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
519 : public OpenBSDTargetInfo<X86_32TargetInfo> {
520public:
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
529class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
530 : public DarwinTargetInfo<X86_32TargetInfo> {
531public:
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(DL: "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 UserLabelPrefix: "_");
547 HasAlignMac68kSupport = true;
548 }
549
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(Feature: "avx512f") ? 512 : hasFeature(Feature: "avx") ? 256 : 128;
558 return true;
559 }
560};
561
562// x86-32 Windows target
563class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
564 : public WindowsTargetInfo<X86_32TargetInfo> {
565public:
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(DL: Layout, UserLabelPrefix: IsWinCOFF ? "_" : "");
577 }
578};
579
580// x86-32 Windows Visual Studio target
581class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
582 : public WindowsX86_32TargetInfo {
583public:
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
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(Name: "_M_IX86", Value: "600");
598 }
599};
600
601// x86-32 MinGW target
602class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
603 : public WindowsX86_32TargetInfo {
604public:
605 MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
606 : WindowsX86_32TargetInfo(Triple, Opts) {
607 HasFloat128 = true;
608 }
609
610 void getTargetDefines(const LangOptions &Opts,
611 MacroBuilder &Builder) const override {
612 WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
613 Builder.defineMacro(Name: "_X86_");
614 }
615};
616
617// x86-32 Cygwin target
618class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
619public:
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(DL: "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 UserLabelPrefix: "_");
627 }
628
629 void getTargetDefines(const LangOptions &Opts,
630 MacroBuilder &Builder) const override {
631 X86_32TargetInfo::getTargetDefines(Opts, Builder);
632 Builder.defineMacro(Name: "_X86_");
633 Builder.defineMacro(Name: "__CYGWIN__");
634 Builder.defineMacro(Name: "__CYGWIN32__");
635 addCygMingDefines(Opts, Builder);
636 DefineStd(Builder, MacroName: "unix", Opts);
637 if (Opts.CPlusPlus)
638 Builder.defineMacro(Name: "_GNU_SOURCE");
639 }
640};
641
642// x86-32 Haiku target
643class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
644 : public HaikuTargetInfo<X86_32TargetInfo> {
645public:
646 HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
647 : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
648
649 void getTargetDefines(const LangOptions &Opts,
650 MacroBuilder &Builder) const override {
651 HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
652 Builder.defineMacro(Name: "__INTEL__");
653 }
654};
655
656// X86-32 MCU target
657class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
658public:
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(DL: "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
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
674 void getTargetDefines(const LangOptions &Opts,
675 MacroBuilder &Builder) const override {
676 X86_32TargetInfo::getTargetDefines(Opts, Builder);
677 Builder.defineMacro(Name: "__iamcu");
678 Builder.defineMacro(Name: "__iamcu__");
679 }
680
681 bool allowsLargerPreferedTypeAlignment() const override { return false; }
682};
683
684// x86-32 RTEMS target
685class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
686public:
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
694 void getTargetDefines(const LangOptions &Opts,
695 MacroBuilder &Builder) const override {
696 X86_32TargetInfo::getTargetDefines(Opts, Builder);
697 Builder.defineMacro(Name: "__INTEL__");
698 Builder.defineMacro(Name: "__rtems__");
699 }
700};
701
702// x86-64 generic target
703class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
704public:
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(DL: 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
745 BuiltinVaListKind getBuiltinVaListKind() const override {
746 return TargetInfo::X86_64ABIBuiltinVaList;
747 }
748
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
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
776 CallingConv getDefaultCallingConv() const override {
777 return CC_C;
778 }
779
780 // for x32 we need it here explicitly
781 bool hasInt128Type() const override { return true; }
782
783 unsigned getUnwindWordWidth() const override { return 64; }
784
785 unsigned getRegisterWidth() const override { return 64; }
786
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
802 void setMaxAtomicWidth() override {
803 if (hasFeature(Feature: "cx16"))
804 MaxAtomicInlineWidth = 128;
805 }
806
807 ArrayRef<Builtin::Info> getTargetBuiltins() const override;
808
809 bool hasBitIntType() const override { return true; }
810 size_t getMaxBitIntWidth() const override {
811 return llvm::IntegerType::MAX_INT_BITS;
812 }
813};
814
815// x86-64 Windows target
816class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
817 : public WindowsTargetInfo<X86_64TargetInfo> {
818public:
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
830 BuiltinVaListKind getBuiltinVaListKind() const override {
831 return TargetInfo::CharPtrBuiltinVaList;
832 }
833
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
859class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
860 : public WindowsX86_64TargetInfo {
861public:
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
869 void getTargetDefines(const LangOptions &Opts,
870 MacroBuilder &Builder) const override {
871 WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
872 Builder.defineMacro(Name: "_M_X64", Value: "100");
873 Builder.defineMacro(Name: "_M_AMD64", Value: "100");
874 }
875
876 TargetInfo::CallingConvKind
877 getCallingConvKind(bool ClangABICompat4) const override {
878 return CCK_MicrosoftWin64;
879 }
880};
881
882// x86-64 MinGW target
883class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
884 : public WindowsX86_64TargetInfo {
885public:
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
897class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
898public:
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
905 void getTargetDefines(const LangOptions &Opts,
906 MacroBuilder &Builder) const override {
907 X86_64TargetInfo::getTargetDefines(Opts, Builder);
908 Builder.defineMacro(Name: "__x86_64__");
909 Builder.defineMacro(Name: "__CYGWIN__");
910 Builder.defineMacro(Name: "__CYGWIN64__");
911 addCygMingDefines(Opts, Builder);
912 DefineStd(Builder, MacroName: "unix", Opts);
913 if (Opts.CPlusPlus)
914 Builder.defineMacro(Name: "_GNU_SOURCE");
915 }
916};
917
918class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
919 : public DarwinTargetInfo<X86_64TargetInfo> {
920public:
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(DL: "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 UserLabelPrefix: "_");
931 }
932
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(Feature: "avx512f") ? 512 : hasFeature(Feature: "avx") ? 256 : 128;
941 return true;
942 }
943};
944
945class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
946 : public OpenBSDTargetInfo<X86_64TargetInfo> {
947public:
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
956class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
957 : public LinuxTargetInfo<X86_32TargetInfo> {
958public:
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
968class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
969 : public LinuxTargetInfo<X86_64TargetInfo> {
970public:
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
978class LLVM_LIBRARY_VISIBILITY OHOSX86_32TargetInfo
979 : public OHOSTargetInfo<X86_32TargetInfo> {
980public:
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
990class LLVM_LIBRARY_VISIBILITY OHOSX86_64TargetInfo
991 : public OHOSTargetInfo<X86_64TargetInfo> {
992public:
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