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