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