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