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 0, // hlsl_constant
50 0, // hlsl_private
51 0, // hlsl_device
52 0, // hlsl_input
53 0, // hlsl_push_constant
54 // Wasm address space values for this target are dummy values,
55 // as it is only enabled for Wasm targets.
56 20, // wasm_funcref
57};
58
59// X86 target abstract base class; x86-32 and x86-64 are very close, so
60// most of the implementation can be shared.
61class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
62
63 enum X86SSEEnum {
64 NoSSE,
65 SSE1,
66 SSE2,
67 SSE3,
68 SSSE3,
69 SSE41,
70 SSE42,
71 AVX,
72 AVX2,
73 AVX512F
74 } SSELevel = NoSSE;
75 bool HasMMX = false;
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_2 = false;
100 bool HasAVX512CD = false;
101 bool HasAVX512VPOPCNTDQ = false;
102 bool HasAVX512VNNI = false;
103 bool HasAVX512FP16 = false;
104 bool HasAVX512BF16 = false;
105 bool HasAVX512DQ = false;
106 bool HasAVX512BITALG = false;
107 bool HasAVX512BW = false;
108 bool HasAVX512VL = false;
109 bool HasAVX512VBMI = false;
110 bool HasAVX512VBMI2 = false;
111 bool HasAVXIFMA = false;
112 bool HasAVX512IFMA = false;
113 bool HasAVX512VP2INTERSECT = false;
114 bool HasSHA = false;
115 bool HasSHA512 = false;
116 bool HasSHSTK = false;
117 bool HasSM3 = false;
118 bool HasSGX = false;
119 bool HasSM4 = false;
120 bool HasCX8 = false;
121 bool HasCX16 = false;
122 bool HasFXSR = false;
123 bool HasXSAVE = false;
124 bool HasXSAVEOPT = false;
125 bool HasXSAVEC = false;
126 bool HasXSAVES = false;
127 bool HasMWAITX = false;
128 bool HasCLZERO = false;
129 bool HasCLDEMOTE = false;
130 bool HasPCONFIG = false;
131 bool HasPKU = false;
132 bool HasCLFLUSHOPT = false;
133 bool HasCLWB = false;
134 bool HasMOVBE = false;
135 bool HasMOVRS = false;
136 bool HasPREFETCHI = false;
137 bool HasRDPID = false;
138 bool HasRDPRU = false;
139 bool HasRetpolineExternalThunk = false;
140 bool HasLAHFSAHF = false;
141 bool HasWBNOINVD = false;
142 bool HasWAITPKG = false;
143 bool HasMOVDIRI = false;
144 bool HasMOVDIR64B = false;
145 bool HasPTWRITE = false;
146 bool HasINVPCID = false;
147 bool HasENQCMD = false;
148 bool HasAVXVNNIINT16 = false;
149 bool HasAMXFP16 = false;
150 bool HasCMPCCXADD = false;
151 bool HasRAOINT = false;
152 bool HasAVXVNNIINT8 = false;
153 bool HasAVXNECONVERT = false;
154 bool HasKL = false; // For key locker
155 bool HasWIDEKL = false; // For wide key locker
156 bool HasHRESET = false;
157 bool HasAVXVNNI = false;
158 bool HasAMXTILE = false;
159 bool HasAMXINT8 = false;
160 bool HasAMXBF16 = false;
161 bool HasAMXCOMPLEX = false;
162 bool HasAMXFP8 = false;
163 bool HasAMXMOVRS = false;
164 bool HasAMXAVX512 = false;
165 bool HasAMXTF32 = false;
166 bool HasSERIALIZE = false;
167 bool HasTSXLDTRK = false;
168 bool HasUSERMSR = false;
169 bool HasUINTR = false;
170 bool HasCRC32 = false;
171 bool HasX87 = false;
172 bool HasEGPR = false;
173 bool HasPush2Pop2 = false;
174 bool HasPPX = false;
175 bool HasNDD = false;
176 bool HasCCMP = false;
177 bool HasNF = false;
178 bool HasCF = false;
179 bool HasZU = false;
180 bool HasJMPABS = false;
181 bool HasInlineAsmUseGPR32 = false;
182 bool HasBranchHint = false;
183
184protected:
185 llvm::X86::CPUKind CPU = llvm::X86::CK_None;
186
187 enum FPMathKind { FP_Default, FP_SSE, FP_387 } FPMath = FP_Default;
188
189public:
190 X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
191 : TargetInfo(Triple) {
192 BFloat16Width = BFloat16Align = 16;
193 BFloat16Format = &llvm::APFloat::BFloat();
194 LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
195 AddrSpaceMap = &X86AddrSpaceMap;
196 HasStrictFP = true;
197 HasUnalignedAccess = true;
198
199 bool IsWinCOFF =
200 getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
201 if (IsWinCOFF)
202 MaxVectorAlign = MaxTLSAlign = 8192u * getCharWidth();
203 }
204
205 const char *getLongDoubleMangling() const override {
206 return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e";
207 }
208
209 LangOptions::FPEvalMethodKind getFPEvalMethod() const override {
210 // X87 evaluates with 80 bits "long double" precision.
211 return SSELevel == NoSSE ? LangOptions::FPEvalMethodKind::FEM_Extended
212 : LangOptions::FPEvalMethodKind::FEM_Source;
213 }
214
215 // EvalMethod `source` is not supported for targets with `NoSSE` feature.
216 bool supportSourceEvalMethod() const override { return SSELevel > NoSSE; }
217
218 ArrayRef<const char *> getGCCRegNames() const override;
219
220 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
221 return {};
222 }
223
224 ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
225
226 bool isSPRegName(StringRef RegName) const override {
227 return RegName == "esp" || RegName == "rsp";
228 }
229
230 bool supportsCpuSupports() const override { return true; }
231 bool supportsCpuIs() const override { return true; }
232 bool supportsCpuInit() const override { return true; }
233
234 bool validateCpuSupports(StringRef FeatureStr) const override;
235
236 bool validateCpuIs(StringRef FeatureStr) const override;
237
238 bool validateCPUSpecificCPUDispatch(StringRef Name) const override;
239
240 char CPUSpecificManglingCharacter(StringRef Name) const override;
241
242 void getCPUSpecificCPUDispatchFeatures(
243 StringRef Name,
244 llvm::SmallVectorImpl<StringRef> &Features) const override;
245
246 std::optional<unsigned> getCPUCacheLineSize() const override;
247
248 bool validateAsmConstraint(const char *&Name,
249 TargetInfo::ConstraintInfo &info) const override;
250
251 bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
252 bool &HasSizeMismatch) const override {
253 // esp and ebp are the only 32-bit registers the x86 backend can currently
254 // handle.
255 if (RegName == "esp" || RegName == "ebp") {
256 // Check that the register size is 32-bit.
257 HasSizeMismatch = RegSize != 32;
258 return true;
259 }
260
261 return false;
262 }
263
264 bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap,
265 StringRef Constraint, unsigned Size) const override;
266
267 bool validateInputSize(const llvm::StringMap<bool> &FeatureMap,
268 StringRef Constraint, unsigned Size) const override;
269
270 bool
271 checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override {
272 if (CPU == llvm::X86::CK_None || CPU >= llvm::X86::CK_PentiumPro)
273 return true;
274 return TargetInfo::checkCFProtectionReturnSupported(Diags);
275 };
276
277 bool
278 checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override {
279 if (CPU == llvm::X86::CK_None || CPU >= llvm::X86::CK_PentiumPro)
280 return true;
281 return TargetInfo::checkCFProtectionBranchSupported(Diags);
282 };
283
284 virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
285 StringRef Constraint, unsigned Size) const;
286
287 std::string convertConstraint(const char *&Constraint) const override;
288 std::string_view getClobbers() const override {
289 return "~{dirflag},~{fpsr},~{flags}";
290 }
291
292 StringRef getConstraintRegister(StringRef Constraint,
293 StringRef Expression) const override {
294 StringRef::iterator I, E;
295 for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
296 if (isalpha(*I) || *I == '@')
297 break;
298 }
299 if (I == E)
300 return "";
301 switch (*I) {
302 // For the register constraints, return the matching register name
303 case 'a':
304 return "ax";
305 case 'b':
306 return "bx";
307 case 'c':
308 return "cx";
309 case 'd':
310 return "dx";
311 case 'S':
312 return "si";
313 case 'D':
314 return "di";
315 // In case the constraint is 'r' we need to return Expression
316 case 'r':
317 return Expression;
318 // Double letters Y<x> constraints
319 case 'Y':
320 if ((++I != E) && ((*I == '0') || (*I == 'z')))
321 return "xmm0";
322 break;
323 default:
324 break;
325 }
326 return "";
327 }
328
329 bool useFP16ConversionIntrinsics() const override {
330 return false;
331 }
332
333 void getTargetDefines(const LangOptions &Opts,
334 MacroBuilder &Builder) const override;
335
336 void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
337 bool Enabled) const final;
338
339 bool
340 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
341 StringRef CPU,
342 const std::vector<std::string> &FeaturesVec) const override;
343
344 bool isValidFeatureName(StringRef Name) const override;
345
346 bool hasFeature(StringRef Feature) const final;
347
348 bool handleTargetFeatures(std::vector<std::string> &Features,
349 DiagnosticsEngine &Diags) override;
350
351 StringRef getABI() const override {
352 if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
353 return "avx512";
354 if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
355 return "avx";
356 if (getTriple().getArch() == llvm::Triple::x86 && !HasMMX)
357 return "no-mmx";
358 return "";
359 }
360
361 bool supportsTargetAttributeTune() const override {
362 return true;
363 }
364
365 bool isValidCPUName(StringRef Name) const override {
366 bool Only64Bit = getTriple().getArch() != llvm::Triple::x86;
367 return llvm::X86::parseArchX86(CPU: Name, Only64Bit) != llvm::X86::CK_None;
368 }
369
370 bool isValidTuneCPUName(StringRef Name) const override {
371 if (Name == "generic")
372 return true;
373
374 // Allow 32-bit only CPUs regardless of 64-bit mode unlike isValidCPUName.
375 // NOTE: gcc rejects 32-bit mtune CPUs in 64-bit mode. But being lenient
376 // since mtune was ignored by clang for so long.
377 return llvm::X86::parseTuneCPU(CPU: Name) != llvm::X86::CK_None;
378 }
379
380 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
381 void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
382
383 bool setCPU(const std::string &Name) override {
384 bool Only64Bit = getTriple().getArch() != llvm::Triple::x86;
385 CPU = llvm::X86::parseArchX86(CPU: Name, Only64Bit);
386 return CPU != llvm::X86::CK_None;
387 }
388
389 llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override;
390
391 bool setFPMath(StringRef Name) override;
392
393 bool supportsExtendIntArgs() const override {
394 return getTriple().getArch() != llvm::Triple::x86;
395 }
396
397 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
398 // Most of the non-ARM calling conventions are i386 conventions.
399 switch (CC) {
400 case CC_X86ThisCall:
401 case CC_X86FastCall:
402 case CC_X86StdCall:
403 case CC_X86VectorCall:
404 case CC_X86RegCall:
405 case CC_C:
406 case CC_PreserveMost:
407 case CC_Swift:
408 case CC_X86Pascal:
409 case CC_IntelOclBicc:
410 return CCCR_OK;
411 case CC_SwiftAsync:
412 return CCCR_Error;
413 case CC_DeviceKernel:
414 return IsOpenCL ? CCCR_OK : CCCR_Warning;
415 default:
416 return CCCR_Warning;
417 }
418 }
419
420 bool checkArithmeticFenceSupported() const override { return true; }
421
422 CallingConv getDefaultCallingConv() const override {
423 return CC_C;
424 }
425
426 bool hasSjLjLowering() const override { return true; }
427
428 void setSupportedOpenCLOpts() override { supportAllOpenCLOpts(); }
429
430 uint64_t getPointerWidthV(LangAS AS) const override {
431 unsigned TargetAddrSpace = getTargetAddressSpace(AS);
432 if (TargetAddrSpace == ptr32_sptr || TargetAddrSpace == ptr32_uptr)
433 return 32;
434 if (TargetAddrSpace == ptr64)
435 return 64;
436 return PointerWidth;
437 }
438
439 uint64_t getPointerAlignV(LangAS AddrSpace) const override {
440 return getPointerWidthV(AS: AddrSpace);
441 }
442 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
443 const TargetInfo *Aux) override {
444 TargetInfo::adjust(Diags, Opts, Aux);
445 IsOpenCL = Opts.OpenCL;
446 }
447
448private:
449 bool IsOpenCL = false;
450};
451
452// X86-32 generic target
453class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
454public:
455 X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
456 : X86TargetInfo(Triple, Opts) {
457 DoubleAlign = LongLongAlign = 32;
458 LongDoubleWidth = 96;
459 LongDoubleAlign = 32;
460 SuitableAlign = 128;
461 resetDataLayout();
462 SizeType = UnsignedInt;
463 PtrDiffType = SignedInt;
464 IntPtrType = SignedInt;
465 RegParmMax = 3;
466
467 // Use fpret for all types.
468 RealTypeUsesObjCFPRetMask =
469 (unsigned)(FloatModeKind::Float | FloatModeKind::Double |
470 FloatModeKind::LongDouble);
471
472 // x86-32 has atomics up to 8 bytes
473 MaxAtomicPromoteWidth = 64;
474 MaxAtomicInlineWidth = 32;
475 }
476
477 BuiltinVaListKind getBuiltinVaListKind() const override {
478 return TargetInfo::CharPtrBuiltinVaList;
479 }
480
481 int getEHDataRegisterNumber(unsigned RegNo) const override {
482 if (RegNo == 0)
483 return 0;
484 if (RegNo == 1)
485 return 2;
486 return -1;
487 }
488
489 bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
490 StringRef Constraint, unsigned Size) const override {
491 switch (Constraint[0]) {
492 default:
493 break;
494 case 'R':
495 case 'q':
496 case 'Q':
497 case 'a':
498 case 'b':
499 case 'c':
500 case 'd':
501 case 'S':
502 case 'D':
503 return Size <= 32;
504 case 'A':
505 return Size <= 64;
506 }
507
508 return X86TargetInfo::validateOperandSize(FeatureMap, Constraint, Size);
509 }
510
511 void setMaxAtomicWidth() override {
512 if (hasFeature(Feature: "cx8"))
513 MaxAtomicInlineWidth = 64;
514 }
515
516 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
517
518 bool hasBitIntType() const override { return true; }
519 size_t getMaxBitIntWidth() const override {
520 return llvm::IntegerType::MAX_INT_BITS;
521 }
522};
523
524class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo
525 : public NetBSDTargetInfo<X86_32TargetInfo> {
526public:
527 NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
528 : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
529};
530
531class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
532 : public OpenBSDTargetInfo<X86_32TargetInfo> {
533public:
534 OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
535 : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
536 SizeType = UnsignedLong;
537 IntPtrType = SignedLong;
538 PtrDiffType = SignedLong;
539 }
540};
541
542class LLVM_LIBRARY_VISIBILITY AppleMachOI386TargetInfo
543 : public AppleMachOTargetInfo<X86_32TargetInfo> {
544public:
545 AppleMachOI386TargetInfo(const llvm::Triple &Triple,
546 const TargetOptions &Opts)
547 : AppleMachOTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
548};
549
550class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
551 : public DarwinTargetInfo<X86_32TargetInfo> {
552public:
553 DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
554 : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
555 LongDoubleWidth = 128;
556 LongDoubleAlign = 128;
557 SuitableAlign = 128;
558 MaxVectorAlign = 256;
559 // The watchOS simulator uses the builtin bool type for Objective-C.
560 llvm::Triple T = llvm::Triple(Triple);
561 if (T.isWatchOS())
562 UseSignedCharForObjCBool = false;
563 SizeType = UnsignedLong;
564 IntPtrType = SignedLong;
565 resetDataLayout();
566 HasAlignMac68kSupport = true;
567 }
568
569 bool handleTargetFeatures(std::vector<std::string> &Features,
570 DiagnosticsEngine &Diags) override {
571 if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
572 Diags))
573 return false;
574 // We now know the features we have: we can decide how to align vectors.
575 MaxVectorAlign =
576 hasFeature(Feature: "avx512f") ? 512 : hasFeature(Feature: "avx") ? 256 : 128;
577 return true;
578 }
579};
580
581// x86-32 Windows target
582class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
583 : public WindowsTargetInfo<X86_32TargetInfo> {
584public:
585 WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
586 : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
587 DoubleAlign = LongLongAlign = 64;
588 bool IsWinCOFF =
589 getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
590 bool IsMSVC = getTriple().isWindowsMSVCEnvironment();
591 std::string Layout = IsWinCOFF ? "e-m:x" : "e-m:e";
592 Layout += "-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-";
593 Layout += IsMSVC ? "f80:128" : "f80:32";
594 Layout += "-n8:16:32-a:0:32-S32";
595 if (IsWinCOFF)
596 UserLabelPrefix = "_";
597 resetDataLayout();
598 }
599};
600
601// x86-32 Windows Visual Studio target
602class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
603 : public WindowsX86_32TargetInfo {
604public:
605 MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
606 const TargetOptions &Opts)
607 : WindowsX86_32TargetInfo(Triple, Opts) {
608 LongDoubleWidth = LongDoubleAlign = 64;
609 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
610 }
611
612 void getTargetDefines(const LangOptions &Opts,
613 MacroBuilder &Builder) const override {
614 WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
615 // The value of the following reflects processor type.
616 // 300=386, 400=486, 500=Pentium, 600=Blend (default)
617 // We lost the original triple, so we use the default.
618 Builder.defineMacro(Name: "_M_IX86", Value: "600");
619 }
620};
621
622// x86-32 MinGW target
623class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
624 : public WindowsX86_32TargetInfo {
625public:
626 MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
627 : WindowsX86_32TargetInfo(Triple, Opts) {
628 HasFloat128 = true;
629 }
630
631 void getTargetDefines(const LangOptions &Opts,
632 MacroBuilder &Builder) const override {
633 WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
634 Builder.defineMacro(Name: "_X86_");
635 }
636};
637
638// x86-32 Cygwin target
639class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
640public:
641 CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
642 : X86_32TargetInfo(Triple, Opts) {
643 this->WCharType = TargetInfo::UnsignedShort;
644 this->WIntType = TargetInfo::UnsignedInt;
645 this->UseMicrosoftManglingForC = true;
646 DoubleAlign = LongLongAlign = 64;
647 UserLabelPrefix = "_";
648 resetDataLayout();
649 }
650
651 void getTargetDefines(const LangOptions &Opts,
652 MacroBuilder &Builder) const override {
653 X86_32TargetInfo::getTargetDefines(Opts, Builder);
654 Builder.defineMacro(Name: "_X86_");
655 Builder.defineMacro(Name: "__CYGWIN__");
656 Builder.defineMacro(Name: "__CYGWIN32__");
657 addCygMingDefines(Opts, Builder);
658 DefineStd(Builder, MacroName: "unix", Opts);
659 if (Opts.CPlusPlus)
660 Builder.defineMacro(Name: "_GNU_SOURCE");
661 }
662};
663
664// x86-32 Haiku target
665class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
666 : public HaikuTargetInfo<X86_32TargetInfo> {
667public:
668 HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
669 : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
670
671 void getTargetDefines(const LangOptions &Opts,
672 MacroBuilder &Builder) const override {
673 HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
674 Builder.defineMacro(Name: "__INTEL__");
675 }
676};
677
678// X86-32 MCU target
679class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
680public:
681 MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
682 : X86_32TargetInfo(Triple, Opts) {
683 LongDoubleWidth = 64;
684 DefaultAlignForAttributeAligned = 32;
685 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
686 resetDataLayout();
687 WIntType = UnsignedInt;
688 }
689
690 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
691 // On MCU we support only C calling convention.
692 return CC == CC_C ? CCCR_OK : CCCR_Warning;
693 }
694
695 void getTargetDefines(const LangOptions &Opts,
696 MacroBuilder &Builder) const override {
697 X86_32TargetInfo::getTargetDefines(Opts, Builder);
698 Builder.defineMacro(Name: "__iamcu");
699 Builder.defineMacro(Name: "__iamcu__");
700 }
701
702 bool allowsLargerPreferedTypeAlignment() const override { return false; }
703};
704
705// x86-32 RTEMS target
706class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
707public:
708 RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
709 : X86_32TargetInfo(Triple, Opts) {
710 SizeType = UnsignedLong;
711 IntPtrType = SignedLong;
712 PtrDiffType = SignedLong;
713 }
714
715 void getTargetDefines(const LangOptions &Opts,
716 MacroBuilder &Builder) const override {
717 X86_32TargetInfo::getTargetDefines(Opts, Builder);
718 Builder.defineMacro(Name: "__INTEL__");
719 Builder.defineMacro(Name: "__rtems__");
720 }
721};
722
723// x86-64 generic target
724class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
725public:
726 X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
727 : X86TargetInfo(Triple, Opts) {
728 const bool IsX32 = getTriple().isX32();
729 LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
730 LongDoubleWidth = 128;
731 LongDoubleAlign = 128;
732 LargeArrayMinWidth = 128;
733 LargeArrayAlign = 128;
734 SuitableAlign = 128;
735 SizeType = IsX32 ? UnsignedInt : UnsignedLong;
736 PtrDiffType = IsX32 ? SignedInt : SignedLong;
737 IntPtrType = IsX32 ? SignedInt : SignedLong;
738 IntMaxType = IsX32 ? SignedLongLong : SignedLong;
739 Int64Type = IsX32 ? SignedLongLong : SignedLong;
740 RegParmMax = 6;
741
742 resetDataLayout();
743
744 // Use fpret only for long double.
745 RealTypeUsesObjCFPRetMask = (unsigned)FloatModeKind::LongDouble;
746
747 // Use fp2ret for _Complex long double.
748 ComplexLongDoubleUsesFP2Ret = true;
749
750 // Make __builtin_ms_va_list available.
751 HasBuiltinMSVaList = true;
752
753 // x86-64 has atomics up to 16 bytes.
754 MaxAtomicPromoteWidth = 128;
755 MaxAtomicInlineWidth = 64;
756 }
757
758 BuiltinVaListKind getBuiltinVaListKind() const override {
759 return TargetInfo::X86_64ABIBuiltinVaList;
760 }
761
762 int getEHDataRegisterNumber(unsigned RegNo) const override {
763 if (RegNo == 0)
764 return 0;
765 if (RegNo == 1)
766 return 1;
767 return -1;
768 }
769
770 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
771 switch (CC) {
772 case CC_C:
773 case CC_Swift:
774 case CC_SwiftAsync:
775 case CC_X86VectorCall:
776 case CC_IntelOclBicc:
777 case CC_Win64:
778 case CC_PreserveMost:
779 case CC_PreserveAll:
780 case CC_PreserveNone:
781 case CC_X86RegCall:
782 return CCCR_OK;
783 case CC_DeviceKernel:
784 return IsOpenCL ? CCCR_OK : CCCR_Warning;
785 default:
786 return CCCR_Warning;
787 }
788 }
789
790 CallingConv getDefaultCallingConv() const override {
791 return CC_C;
792 }
793
794 // for x32 we need it here explicitly
795 bool hasInt128Type() const override { return true; }
796
797 unsigned getUnwindWordWidth() const override { return 64; }
798
799 unsigned getRegisterWidth() const override { return 64; }
800
801 bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
802 bool &HasSizeMismatch) const override {
803 // rsp and rbp are the only 64-bit registers the x86 backend can currently
804 // handle.
805 if (RegName == "rsp" || RegName == "rbp") {
806 // Check that the register size is 64-bit.
807 HasSizeMismatch = RegSize != 64;
808 return true;
809 }
810
811 // -ffixed-r8 through -ffixed-r31 are lowered to reserve-r8 through
812 // reserve-r31 target features, so canonicalize subregister spellings
813 // like r15d/r15w/r15b back to the corresponding 64-bit register first.
814 StringRef Reg64 = RegName;
815 if (Reg64.back() == 'd' || Reg64.back() == 'w' || Reg64.back() == 'b') {
816 Reg64 = Reg64.substr(Start: 0, N: Reg64.size() - 1);
817 }
818 if (getTargetOpts().FeatureMap.lookup(Key: ("reserve-" + Reg64).str()))
819 return true;
820
821 // Check if the register is a 32-bit register the backend can handle.
822 return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
823 HasSizeMismatch);
824 }
825 void setMaxAtomicWidth() override {
826 if (hasFeature(Feature: "cx16"))
827 MaxAtomicInlineWidth = 128;
828 }
829
830 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
831
832 bool hasBitIntType() const override { return true; }
833 size_t getMaxBitIntWidth() const override {
834 return llvm::IntegerType::MAX_INT_BITS;
835 }
836
837 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
838 const TargetInfo *Aux) override {
839 TargetInfo::adjust(Diags, Opts, Aux);
840 IsOpenCL = Opts.OpenCL;
841 }
842
843private:
844 bool IsOpenCL = false;
845};
846
847// x86-64 UEFI target
848class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo
849 : public UEFITargetInfo<X86_64TargetInfo> {
850public:
851 UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
852 : UEFITargetInfo<X86_64TargetInfo>(Triple, Opts) {
853 // The UEFI spec does not mandate specific C++ ABI, integer widths, or
854 // alignment. We are setting these defaults to match the Windows target as
855 // it is the only way to build EFI applications with Clang/LLVM today. We
856 // intend to offer flexibility by supporting choices that are not default in
857 // Windows target in the future.
858 this->TheCXXABI.set(TargetCXXABI::Microsoft);
859 LongWidth = LongAlign = 32;
860 DoubleAlign = LongLongAlign = 64;
861 LongDoubleWidth = LongDoubleAlign = 64;
862 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
863 IntMaxType = SignedLongLong;
864 Int64Type = SignedLongLong;
865 SizeType = UnsignedLongLong;
866 PtrDiffType = SignedLongLong;
867 IntPtrType = SignedLongLong;
868 WCharType = UnsignedShort;
869 WIntType = UnsignedShort;
870 this->resetDataLayout();
871 }
872
873 BuiltinVaListKind getBuiltinVaListKind() const override {
874 return TargetInfo::CharPtrBuiltinVaList;
875 }
876
877 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
878 switch (CC) {
879 case CC_C:
880 case CC_Win64:
881 case CC_X86_64SysV:
882 return CCCR_OK;
883 default:
884 return CCCR_Warning;
885 }
886 }
887
888 TargetInfo::CallingConvKind
889 getCallingConvKind(bool ClangABICompat4) const override {
890 return CCK_MicrosoftWin64;
891 }
892};
893
894// x86-64 Windows target
895class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
896 : public WindowsTargetInfo<X86_64TargetInfo> {
897public:
898 WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
899 : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
900 LongWidth = LongAlign = 32;
901 DoubleAlign = LongLongAlign = 64;
902 IntMaxType = SignedLongLong;
903 Int64Type = SignedLongLong;
904 SizeType = UnsignedLongLong;
905 PtrDiffType = SignedLongLong;
906 IntPtrType = SignedLongLong;
907 }
908
909 BuiltinVaListKind getBuiltinVaListKind() const override {
910 return TargetInfo::CharPtrBuiltinVaList;
911 }
912
913 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
914 switch (CC) {
915 case CC_X86StdCall:
916 case CC_X86ThisCall:
917 case CC_X86FastCall:
918 return CCCR_Ignore;
919 case CC_C:
920 case CC_X86VectorCall:
921 case CC_IntelOclBicc:
922 case CC_PreserveMost:
923 case CC_PreserveAll:
924 case CC_PreserveNone:
925 case CC_X86_64SysV:
926 case CC_Swift:
927 case CC_SwiftAsync:
928 case CC_X86RegCall:
929 case CC_DeviceKernel:
930 return CCCR_OK;
931 default:
932 return CCCR_Warning;
933 }
934 }
935};
936
937// x86-64 Windows Visual Studio target
938class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
939 : public WindowsX86_64TargetInfo {
940public:
941 MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
942 const TargetOptions &Opts)
943 : WindowsX86_64TargetInfo(Triple, Opts) {
944 LongDoubleWidth = LongDoubleAlign = 64;
945 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
946 }
947
948 void getTargetDefines(const LangOptions &Opts,
949 MacroBuilder &Builder) const override {
950 WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
951 Builder.defineMacro(Name: "_M_X64", Value: "100");
952 Builder.defineMacro(Name: "_M_AMD64", Value: "100");
953 }
954
955 TargetInfo::CallingConvKind
956 getCallingConvKind(bool ClangABICompat4) const override {
957 return CCK_MicrosoftWin64;
958 }
959};
960
961// x86-64 MinGW target
962class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
963 : public WindowsX86_64TargetInfo {
964public:
965 MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
966 : WindowsX86_64TargetInfo(Triple, Opts) {
967 // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
968 // with x86 FP ops. Weird.
969 LongDoubleWidth = LongDoubleAlign = 128;
970 LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
971 HasFloat128 = true;
972 }
973};
974
975// x86-64 Cygwin target
976class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
977public:
978 CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
979 : X86_64TargetInfo(Triple, Opts) {
980 this->WCharType = TargetInfo::UnsignedShort;
981 this->WIntType = TargetInfo::UnsignedInt;
982 this->UseMicrosoftManglingForC = true;
983 }
984
985 void getTargetDefines(const LangOptions &Opts,
986 MacroBuilder &Builder) const override {
987 X86_64TargetInfo::getTargetDefines(Opts, Builder);
988 Builder.defineMacro(Name: "__x86_64__");
989 Builder.defineMacro(Name: "__CYGWIN__");
990 Builder.defineMacro(Name: "__CYGWIN64__");
991 addCygMingDefines(Opts, Builder);
992 DefineStd(Builder, MacroName: "unix", Opts);
993 if (Opts.CPlusPlus)
994 Builder.defineMacro(Name: "_GNU_SOURCE");
995 }
996
997 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
998 switch (CC) {
999 case CC_X86StdCall:
1000 case CC_X86ThisCall:
1001 case CC_X86FastCall:
1002 return CCCR_Ignore;
1003 case CC_C:
1004 case CC_X86VectorCall:
1005 case CC_IntelOclBicc:
1006 case CC_PreserveMost:
1007 case CC_PreserveAll:
1008 case CC_PreserveNone:
1009 case CC_X86_64SysV:
1010 case CC_Swift:
1011 case CC_SwiftAsync:
1012 case CC_X86RegCall:
1013 case CC_DeviceKernel:
1014 return CCCR_OK;
1015 default:
1016 return CCCR_Warning;
1017 }
1018 }
1019
1020 BuiltinVaListKind getBuiltinVaListKind() const override {
1021 return TargetInfo::CharPtrBuiltinVaList;
1022 }
1023};
1024
1025class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
1026 : public DarwinTargetInfo<X86_64TargetInfo> {
1027public:
1028 DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1029 : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1030 Int64Type = SignedLongLong;
1031 // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
1032 llvm::Triple T = llvm::Triple(Triple);
1033 if (T.isiOS())
1034 UseSignedCharForObjCBool = false;
1035 resetDataLayout();
1036 }
1037
1038 bool handleTargetFeatures(std::vector<std::string> &Features,
1039 DiagnosticsEngine &Diags) override {
1040 if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
1041 Diags))
1042 return false;
1043 // We now know the features we have: we can decide how to align vectors.
1044 MaxVectorAlign =
1045 hasFeature(Feature: "avx512f") ? 512 : hasFeature(Feature: "avx") ? 256 : 128;
1046 return true;
1047 }
1048};
1049
1050class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
1051 : public OpenBSDTargetInfo<X86_64TargetInfo> {
1052public:
1053 OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1054 : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1055 IntMaxType = SignedLongLong;
1056 Int64Type = SignedLongLong;
1057 }
1058};
1059
1060// x86_32 Android target
1061class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
1062 : public LinuxTargetInfo<X86_32TargetInfo> {
1063public:
1064 AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1065 : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
1066 SuitableAlign = 32;
1067 LongDoubleWidth = 64;
1068 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1069 }
1070};
1071
1072// x86_64 Android target
1073class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
1074 : public LinuxTargetInfo<X86_64TargetInfo> {
1075public:
1076 AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1077 : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1078 LongDoubleFormat = &llvm::APFloat::IEEEquad();
1079 }
1080};
1081
1082// x86_32 OHOS target
1083class LLVM_LIBRARY_VISIBILITY OHOSX86_32TargetInfo
1084 : public OHOSTargetInfo<X86_32TargetInfo> {
1085public:
1086 OHOSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1087 : OHOSTargetInfo<X86_32TargetInfo>(Triple, Opts) {
1088 SuitableAlign = 32;
1089 LongDoubleWidth = 64;
1090 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1091 }
1092};
1093
1094// x86_64 OHOS target
1095class LLVM_LIBRARY_VISIBILITY OHOSX86_64TargetInfo
1096 : public OHOSTargetInfo<X86_64TargetInfo> {
1097public:
1098 OHOSX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1099 : OHOSTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1100 LongDoubleFormat = &llvm::APFloat::IEEEquad();
1101 }
1102};
1103} // namespace targets
1104} // namespace clang
1105#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
1106