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