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