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

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