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