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