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