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