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