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