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) override {
445 TargetInfo::adjust(Diags, Opts);
446 IsOpenCL = Opts.OpenCL;
447 }
448
449private:
450 bool IsOpenCL = false;
451};
452
453// X86-32 generic target
454class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
455public:
456 X86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
457 : X86TargetInfo(Triple, Opts) {
458 DoubleAlign = LongLongAlign = 32;
459 LongDoubleWidth = 96;
460 LongDoubleAlign = 32;
461 SuitableAlign = 128;
462 resetDataLayout(DL: Triple.isOSBinFormatMachO()
463 ? "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:"
464 "128-f64:32:64-f80:32-n8:16:32-S128"
465 : "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:"
466 "128-f64:32:64-f80:32-n8:16:32-S128",
467 UserLabelPrefix: Triple.isOSBinFormatMachO() ? "_" : "");
468 SizeType = UnsignedInt;
469 PtrDiffType = SignedInt;
470 IntPtrType = SignedInt;
471 RegParmMax = 3;
472
473 // Use fpret for all types.
474 RealTypeUsesObjCFPRetMask =
475 (unsigned)(FloatModeKind::Float | FloatModeKind::Double |
476 FloatModeKind::LongDouble);
477
478 // x86-32 has atomics up to 8 bytes
479 MaxAtomicPromoteWidth = 64;
480 MaxAtomicInlineWidth = 32;
481 }
482
483 BuiltinVaListKind getBuiltinVaListKind() const override {
484 return TargetInfo::CharPtrBuiltinVaList;
485 }
486
487 int getEHDataRegisterNumber(unsigned RegNo) const override {
488 if (RegNo == 0)
489 return 0;
490 if (RegNo == 1)
491 return 2;
492 return -1;
493 }
494
495 bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
496 StringRef Constraint, unsigned Size) const override {
497 switch (Constraint[0]) {
498 default:
499 break;
500 case 'R':
501 case 'q':
502 case 'Q':
503 case 'a':
504 case 'b':
505 case 'c':
506 case 'd':
507 case 'S':
508 case 'D':
509 return Size <= 32;
510 case 'A':
511 return Size <= 64;
512 }
513
514 return X86TargetInfo::validateOperandSize(FeatureMap, Constraint, Size);
515 }
516
517 void setMaxAtomicWidth() override {
518 if (hasFeature(Feature: "cx8"))
519 MaxAtomicInlineWidth = 64;
520 }
521
522 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
523
524 bool hasBitIntType() const override { return true; }
525 size_t getMaxBitIntWidth() const override {
526 return llvm::IntegerType::MAX_INT_BITS;
527 }
528};
529
530class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo
531 : public NetBSDTargetInfo<X86_32TargetInfo> {
532public:
533 NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
534 : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
535};
536
537class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo
538 : public OpenBSDTargetInfo<X86_32TargetInfo> {
539public:
540 OpenBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
541 : OpenBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {
542 SizeType = UnsignedLong;
543 IntPtrType = SignedLong;
544 PtrDiffType = SignedLong;
545 }
546};
547
548class LLVM_LIBRARY_VISIBILITY AppleMachOI386TargetInfo
549 : public AppleMachOTargetInfo<X86_32TargetInfo> {
550public:
551 AppleMachOI386TargetInfo(const llvm::Triple &Triple,
552 const TargetOptions &Opts)
553 : AppleMachOTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
554};
555
556class LLVM_LIBRARY_VISIBILITY DarwinI386TargetInfo
557 : public DarwinTargetInfo<X86_32TargetInfo> {
558public:
559 DarwinI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
560 : DarwinTargetInfo<X86_32TargetInfo>(Triple, Opts) {
561 LongDoubleWidth = 128;
562 LongDoubleAlign = 128;
563 SuitableAlign = 128;
564 MaxVectorAlign = 256;
565 // The watchOS simulator uses the builtin bool type for Objective-C.
566 llvm::Triple T = llvm::Triple(Triple);
567 if (T.isWatchOS())
568 UseSignedCharForObjCBool = false;
569 SizeType = UnsignedLong;
570 IntPtrType = SignedLong;
571 resetDataLayout(DL: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-"
572 "f64:32:64-f80:128-n8:16:32-S128",
573 UserLabelPrefix: "_");
574 HasAlignMac68kSupport = true;
575 }
576
577 bool handleTargetFeatures(std::vector<std::string> &Features,
578 DiagnosticsEngine &Diags) override {
579 if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
580 Diags))
581 return false;
582 // We now know the features we have: we can decide how to align vectors.
583 MaxVectorAlign =
584 hasFeature(Feature: "avx512f") ? 512 : hasFeature(Feature: "avx") ? 256 : 128;
585 return true;
586 }
587};
588
589// x86-32 Windows target
590class LLVM_LIBRARY_VISIBILITY WindowsX86_32TargetInfo
591 : public WindowsTargetInfo<X86_32TargetInfo> {
592public:
593 WindowsX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
594 : WindowsTargetInfo<X86_32TargetInfo>(Triple, Opts) {
595 DoubleAlign = LongLongAlign = 64;
596 bool IsWinCOFF =
597 getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
598 bool IsMSVC = getTriple().isWindowsMSVCEnvironment();
599 std::string Layout = IsWinCOFF ? "e-m:x" : "e-m:e";
600 Layout += "-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-";
601 Layout += IsMSVC ? "f80:128" : "f80:32";
602 Layout += "-n8:16:32-a:0:32-S32";
603 resetDataLayout(DL: Layout, UserLabelPrefix: IsWinCOFF ? "_" : "");
604 }
605};
606
607// x86-32 Windows Visual Studio target
608class LLVM_LIBRARY_VISIBILITY MicrosoftX86_32TargetInfo
609 : public WindowsX86_32TargetInfo {
610public:
611 MicrosoftX86_32TargetInfo(const llvm::Triple &Triple,
612 const TargetOptions &Opts)
613 : WindowsX86_32TargetInfo(Triple, Opts) {
614 LongDoubleWidth = LongDoubleAlign = 64;
615 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
616 }
617
618 void getTargetDefines(const LangOptions &Opts,
619 MacroBuilder &Builder) const override {
620 WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
621 // The value of the following reflects processor type.
622 // 300=386, 400=486, 500=Pentium, 600=Blend (default)
623 // We lost the original triple, so we use the default.
624 Builder.defineMacro(Name: "_M_IX86", Value: "600");
625 }
626};
627
628// x86-32 MinGW target
629class LLVM_LIBRARY_VISIBILITY MinGWX86_32TargetInfo
630 : public WindowsX86_32TargetInfo {
631public:
632 MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
633 : WindowsX86_32TargetInfo(Triple, Opts) {
634 HasFloat128 = true;
635 }
636
637 void getTargetDefines(const LangOptions &Opts,
638 MacroBuilder &Builder) const override {
639 WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
640 Builder.defineMacro(Name: "_X86_");
641 }
642};
643
644// x86-32 Cygwin target
645class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
646public:
647 CygwinX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
648 : X86_32TargetInfo(Triple, Opts) {
649 this->WCharType = TargetInfo::UnsignedShort;
650 this->WIntType = TargetInfo::UnsignedInt;
651 DoubleAlign = LongLongAlign = 64;
652 resetDataLayout(DL: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-"
653 "i128:128-f80:32-n8:16:32-a:0:32-S32",
654 UserLabelPrefix: "_");
655 }
656
657 void getTargetDefines(const LangOptions &Opts,
658 MacroBuilder &Builder) const override {
659 X86_32TargetInfo::getTargetDefines(Opts, Builder);
660 Builder.defineMacro(Name: "_X86_");
661 Builder.defineMacro(Name: "__CYGWIN__");
662 Builder.defineMacro(Name: "__CYGWIN32__");
663 addCygMingDefines(Opts, Builder);
664 DefineStd(Builder, MacroName: "unix", Opts);
665 if (Opts.CPlusPlus)
666 Builder.defineMacro(Name: "_GNU_SOURCE");
667 }
668};
669
670// x86-32 Haiku target
671class LLVM_LIBRARY_VISIBILITY HaikuX86_32TargetInfo
672 : public HaikuTargetInfo<X86_32TargetInfo> {
673public:
674 HaikuX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
675 : HaikuTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
676
677 void getTargetDefines(const LangOptions &Opts,
678 MacroBuilder &Builder) const override {
679 HaikuTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
680 Builder.defineMacro(Name: "__INTEL__");
681 }
682};
683
684// X86-32 MCU target
685class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
686public:
687 MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
688 : X86_32TargetInfo(Triple, Opts) {
689 LongDoubleWidth = 64;
690 DefaultAlignForAttributeAligned = 32;
691 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
692 resetDataLayout(DL: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-"
693 "f64:32-f128:32-n8:16:32-a:0:32-S32");
694 WIntType = UnsignedInt;
695 }
696
697 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
698 // On MCU we support only C calling convention.
699 return CC == CC_C ? CCCR_OK : CCCR_Warning;
700 }
701
702 void getTargetDefines(const LangOptions &Opts,
703 MacroBuilder &Builder) const override {
704 X86_32TargetInfo::getTargetDefines(Opts, Builder);
705 Builder.defineMacro(Name: "__iamcu");
706 Builder.defineMacro(Name: "__iamcu__");
707 }
708
709 bool allowsLargerPreferedTypeAlignment() const override { return false; }
710};
711
712// x86-32 RTEMS target
713class LLVM_LIBRARY_VISIBILITY RTEMSX86_32TargetInfo : public X86_32TargetInfo {
714public:
715 RTEMSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
716 : X86_32TargetInfo(Triple, Opts) {
717 SizeType = UnsignedLong;
718 IntPtrType = SignedLong;
719 PtrDiffType = SignedLong;
720 }
721
722 void getTargetDefines(const LangOptions &Opts,
723 MacroBuilder &Builder) const override {
724 X86_32TargetInfo::getTargetDefines(Opts, Builder);
725 Builder.defineMacro(Name: "__INTEL__");
726 Builder.defineMacro(Name: "__rtems__");
727 }
728};
729
730// x86-64 generic target
731class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
732public:
733 X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
734 : X86TargetInfo(Triple, Opts) {
735 const bool IsX32 = getTriple().isX32();
736 bool IsWinCOFF =
737 getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
738 LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
739 LongDoubleWidth = 128;
740 LongDoubleAlign = 128;
741 LargeArrayMinWidth = 128;
742 LargeArrayAlign = 128;
743 SuitableAlign = 128;
744 SizeType = IsX32 ? UnsignedInt : UnsignedLong;
745 PtrDiffType = IsX32 ? SignedInt : SignedLong;
746 IntPtrType = IsX32 ? SignedInt : SignedLong;
747 IntMaxType = IsX32 ? SignedLongLong : SignedLong;
748 Int64Type = IsX32 ? SignedLongLong : SignedLong;
749 RegParmMax = 6;
750
751 // Pointers are 32-bit in x32.
752 resetDataLayout(DL: IsX32 ? "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-"
753 "i64:64-i128:128-f80:128-n8:16:32:64-S128"
754 : IsWinCOFF ? "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:"
755 "64-i128:128-f80:128-n8:16:32:64-S128"
756 : "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:"
757 "64-i128:128-f80:128-n8:16:32:64-S128");
758
759 // Use fpret only for long double.
760 RealTypeUsesObjCFPRetMask = (unsigned)FloatModeKind::LongDouble;
761
762 // Use fp2ret for _Complex long double.
763 ComplexLongDoubleUsesFP2Ret = true;
764
765 // Make __builtin_ms_va_list available.
766 HasBuiltinMSVaList = true;
767
768 // x86-64 has atomics up to 16 bytes.
769 MaxAtomicPromoteWidth = 128;
770 MaxAtomicInlineWidth = 64;
771 }
772
773 BuiltinVaListKind getBuiltinVaListKind() const override {
774 return TargetInfo::X86_64ABIBuiltinVaList;
775 }
776
777 int getEHDataRegisterNumber(unsigned RegNo) const override {
778 if (RegNo == 0)
779 return 0;
780 if (RegNo == 1)
781 return 1;
782 return -1;
783 }
784
785 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
786 switch (CC) {
787 case CC_C:
788 case CC_Swift:
789 case CC_SwiftAsync:
790 case CC_X86VectorCall:
791 case CC_IntelOclBicc:
792 case CC_Win64:
793 case CC_PreserveMost:
794 case CC_PreserveAll:
795 case CC_PreserveNone:
796 case CC_X86RegCall:
797 return CCCR_OK;
798 case CC_DeviceKernel:
799 return IsOpenCL ? CCCR_OK : CCCR_Warning;
800 default:
801 return CCCR_Warning;
802 }
803 }
804
805 CallingConv getDefaultCallingConv() const override {
806 return CC_C;
807 }
808
809 // for x32 we need it here explicitly
810 bool hasInt128Type() const override { return true; }
811
812 unsigned getUnwindWordWidth() const override { return 64; }
813
814 unsigned getRegisterWidth() const override { return 64; }
815
816 bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
817 bool &HasSizeMismatch) const override {
818 // rsp and rbp are the only 64-bit registers the x86 backend can currently
819 // handle.
820 if (RegName == "rsp" || RegName == "rbp") {
821 // Check that the register size is 64-bit.
822 HasSizeMismatch = RegSize != 64;
823 return true;
824 }
825
826 // Check if the register is a 32-bit register the backend can handle.
827 return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
828 HasSizeMismatch);
829 }
830 void setMaxAtomicWidth() override {
831 if (hasFeature(Feature: "cx16"))
832 MaxAtomicInlineWidth = 128;
833 }
834
835 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
836
837 bool hasBitIntType() const override { return true; }
838 size_t getMaxBitIntWidth() const override {
839 return llvm::IntegerType::MAX_INT_BITS;
840 }
841
842 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
843 TargetInfo::adjust(Diags, Opts);
844 IsOpenCL = Opts.OpenCL;
845 }
846
847private:
848 bool IsOpenCL = false;
849};
850
851// x86-64 UEFI target
852class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo
853 : public UEFITargetInfo<X86_64TargetInfo> {
854public:
855 UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
856 : UEFITargetInfo<X86_64TargetInfo>(Triple, Opts) {
857 // The UEFI spec does not mandate specific C++ ABI, integer widths, or
858 // alignment. We are setting these defaults to match the Windows target as
859 // it is the only way to build EFI applications with Clang/LLVM today. We
860 // intend to offer flexibility by supporting choices that are not default in
861 // Windows target in the future.
862 this->TheCXXABI.set(TargetCXXABI::Microsoft);
863 LongWidth = LongAlign = 32;
864 DoubleAlign = LongLongAlign = 64;
865 LongDoubleWidth = LongDoubleAlign = 64;
866 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
867 IntMaxType = SignedLongLong;
868 Int64Type = SignedLongLong;
869 SizeType = UnsignedLongLong;
870 PtrDiffType = SignedLongLong;
871 IntPtrType = SignedLongLong;
872 WCharType = UnsignedShort;
873 WIntType = UnsignedShort;
874 this->resetDataLayout(DL: "e-m:w-p270:32:32-p271:32:32-p272:64:64-"
875 "i64:64-i128:128-f80:128-n8:16:32:64-S128");
876 }
877
878 BuiltinVaListKind getBuiltinVaListKind() const override {
879 return TargetInfo::CharPtrBuiltinVaList;
880 }
881
882 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
883 switch (CC) {
884 case CC_C:
885 case CC_Win64:
886 case CC_X86_64SysV:
887 return CCCR_OK;
888 default:
889 return CCCR_Warning;
890 }
891 }
892
893 TargetInfo::CallingConvKind
894 getCallingConvKind(bool ClangABICompat4) const override {
895 return CCK_MicrosoftWin64;
896 }
897};
898
899// x86-64 Windows target
900class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
901 : public WindowsTargetInfo<X86_64TargetInfo> {
902public:
903 WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
904 : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
905 LongWidth = LongAlign = 32;
906 DoubleAlign = LongLongAlign = 64;
907 IntMaxType = SignedLongLong;
908 Int64Type = SignedLongLong;
909 SizeType = UnsignedLongLong;
910 PtrDiffType = SignedLongLong;
911 IntPtrType = SignedLongLong;
912 }
913
914 BuiltinVaListKind getBuiltinVaListKind() const override {
915 return TargetInfo::CharPtrBuiltinVaList;
916 }
917
918 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
919 switch (CC) {
920 case CC_X86StdCall:
921 case CC_X86ThisCall:
922 case CC_X86FastCall:
923 return CCCR_Ignore;
924 case CC_C:
925 case CC_X86VectorCall:
926 case CC_IntelOclBicc:
927 case CC_PreserveMost:
928 case CC_PreserveAll:
929 case CC_PreserveNone:
930 case CC_X86_64SysV:
931 case CC_Swift:
932 case CC_SwiftAsync:
933 case CC_X86RegCall:
934 case CC_DeviceKernel:
935 return CCCR_OK;
936 default:
937 return CCCR_Warning;
938 }
939 }
940};
941
942// x86-64 Windows Visual Studio target
943class LLVM_LIBRARY_VISIBILITY MicrosoftX86_64TargetInfo
944 : public WindowsX86_64TargetInfo {
945public:
946 MicrosoftX86_64TargetInfo(const llvm::Triple &Triple,
947 const TargetOptions &Opts)
948 : WindowsX86_64TargetInfo(Triple, Opts) {
949 LongDoubleWidth = LongDoubleAlign = 64;
950 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
951 }
952
953 void getTargetDefines(const LangOptions &Opts,
954 MacroBuilder &Builder) const override {
955 WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
956 Builder.defineMacro(Name: "_M_X64", Value: "100");
957 Builder.defineMacro(Name: "_M_AMD64", Value: "100");
958 }
959
960 TargetInfo::CallingConvKind
961 getCallingConvKind(bool ClangABICompat4) const override {
962 return CCK_MicrosoftWin64;
963 }
964};
965
966// x86-64 MinGW target
967class LLVM_LIBRARY_VISIBILITY MinGWX86_64TargetInfo
968 : public WindowsX86_64TargetInfo {
969public:
970 MinGWX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
971 : WindowsX86_64TargetInfo(Triple, Opts) {
972 // Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
973 // with x86 FP ops. Weird.
974 LongDoubleWidth = LongDoubleAlign = 128;
975 LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
976 HasFloat128 = true;
977 }
978};
979
980// x86-64 Cygwin target
981class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
982public:
983 CygwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
984 : X86_64TargetInfo(Triple, Opts) {
985 this->WCharType = TargetInfo::UnsignedShort;
986 this->WIntType = TargetInfo::UnsignedInt;
987 }
988
989 void getTargetDefines(const LangOptions &Opts,
990 MacroBuilder &Builder) const override {
991 X86_64TargetInfo::getTargetDefines(Opts, Builder);
992 Builder.defineMacro(Name: "__x86_64__");
993 Builder.defineMacro(Name: "__CYGWIN__");
994 Builder.defineMacro(Name: "__CYGWIN64__");
995 addCygMingDefines(Opts, Builder);
996 DefineStd(Builder, MacroName: "unix", Opts);
997 if (Opts.CPlusPlus)
998 Builder.defineMacro(Name: "_GNU_SOURCE");
999 }
1000
1001 BuiltinVaListKind getBuiltinVaListKind() const override {
1002 return TargetInfo::CharPtrBuiltinVaList;
1003 }
1004};
1005
1006class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
1007 : public DarwinTargetInfo<X86_64TargetInfo> {
1008public:
1009 DarwinX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1010 : DarwinTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1011 Int64Type = SignedLongLong;
1012 // The 64-bit iOS simulator uses the builtin bool type for Objective-C.
1013 llvm::Triple T = llvm::Triple(Triple);
1014 if (T.isiOS())
1015 UseSignedCharForObjCBool = false;
1016 resetDataLayout(DL: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-"
1017 "f80:128-n8:16:32:64-S128",
1018 UserLabelPrefix: "_");
1019 }
1020
1021 bool handleTargetFeatures(std::vector<std::string> &Features,
1022 DiagnosticsEngine &Diags) override {
1023 if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
1024 Diags))
1025 return false;
1026 // We now know the features we have: we can decide how to align vectors.
1027 MaxVectorAlign =
1028 hasFeature(Feature: "avx512f") ? 512 : hasFeature(Feature: "avx") ? 256 : 128;
1029 return true;
1030 }
1031};
1032
1033class LLVM_LIBRARY_VISIBILITY OpenBSDX86_64TargetInfo
1034 : public OpenBSDTargetInfo<X86_64TargetInfo> {
1035public:
1036 OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1037 : OpenBSDTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1038 IntMaxType = SignedLongLong;
1039 Int64Type = SignedLongLong;
1040 }
1041};
1042
1043// x86_32 Android target
1044class LLVM_LIBRARY_VISIBILITY AndroidX86_32TargetInfo
1045 : public LinuxTargetInfo<X86_32TargetInfo> {
1046public:
1047 AndroidX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1048 : LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
1049 SuitableAlign = 32;
1050 LongDoubleWidth = 64;
1051 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1052 }
1053};
1054
1055// x86_64 Android target
1056class LLVM_LIBRARY_VISIBILITY AndroidX86_64TargetInfo
1057 : public LinuxTargetInfo<X86_64TargetInfo> {
1058public:
1059 AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1060 : LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1061 LongDoubleFormat = &llvm::APFloat::IEEEquad();
1062 }
1063};
1064
1065// x86_32 OHOS target
1066class LLVM_LIBRARY_VISIBILITY OHOSX86_32TargetInfo
1067 : public OHOSTargetInfo<X86_32TargetInfo> {
1068public:
1069 OHOSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1070 : OHOSTargetInfo<X86_32TargetInfo>(Triple, Opts) {
1071 SuitableAlign = 32;
1072 LongDoubleWidth = 64;
1073 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1074 }
1075};
1076
1077// x86_64 OHOS target
1078class LLVM_LIBRARY_VISIBILITY OHOSX86_64TargetInfo
1079 : public OHOSTargetInfo<X86_64TargetInfo> {
1080public:
1081 OHOSX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1082 : OHOSTargetInfo<X86_64TargetInfo>(Triple, Opts) {
1083 LongDoubleFormat = &llvm::APFloat::IEEEquad();
1084 }
1085};
1086} // namespace targets
1087} // namespace clang
1088#endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H
1089

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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