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

source code of clang/lib/Basic/Targets/X86.h